CakePHP: JSON w widokach

Pomysł jak i klasa do realizacji pomysłu są zaczerpnięte z tego wpisu. Jeżeli mamy akcję, której zadaniem jest zwrócić wynik w JSON; zazwyczaj nie ma potrzeby korzystania z plików widoków i layoutów. Niektórzy pokusiliby się o wyłączenie autorenderowania i następnie wpisali echo json_encode($something);.Bardziej doświadczeni programiście wiedzą, że jest to niezgodne z architekturą MVC. Do tego celu stworzona została klasa JsonView. Poniższy kod ląduje w pliku app/views/json.php.

class JsonView extends View {
  var $content = null;
  function __construct(&$controller, $register = true) {
    if (is_object($controller) && isset($controller->viewVars['json'])) {
      $this->content = $controller->viewVars['json'];
    }
    if ($register) {
      ClassRegistry::addObject('view', $this);
    }
    Configure::write('debug', 0);
  }
 
  function render($action = null, $layout = null, $file = null) {
    if ($this->content === null) {
      $data = '';
    } else {
      $data = json_encode($this->content);
    }
    return $data;
  }
}

Teraz w naszej akcji, której zadaniem jest wypisać obiekt JSON wystarczy wpisać:

function my_action() {
    $this->view='json';
    $json = array('myobject'=>true,'mvc'=>'not broken');
    $this->set(compact($json));
}

W odpowiedzi akcji powinniśmy otrzymać:

{"myobject":true,"mvc":"not broken"}

Mechanizm bardzo prosty w implementacji, pozwalający znacząco przyspieszyć pisanie kodu z użyciem JSON.

Javascript: Przypisać this, czyli metoda apply i call obiektu Function

Czasami, szczególnie przy obiektowym javascriptcie istnieje potrzeba określenia czym jest this w danej funkcji/metodzie. Istnieją dwa sposoby określenia this, za pomocą metod apply i call obiektu Function:

function car() {
    this.name = 'car';
}
car.prototype.getName = function() {
    alert('car.getName(): '+this.name);
}
 
function person() {
    this.name = 'person';
}
person.prototype.getName = function() {
     alert('person.getName(): '+this.name);
}
person.prototype.test1 = function(car) {
     car.getName.apply(this);  
}
person.prototype.test2 = function(car) {
     car.getName.call(this);  
}
 
 
var car = new car();
var person = new person();
car.getName();
person.getName();
person.test1(car);
person.test2(car);

Pierwszym parametrem w obydwu metodach jest zmienna, która w wywołanej funkcji/metodzie będzie przypisana do this. Wykonując powyższy kod, tworzymy 2 obiekty, person i car. Wywołujemy po koleji metody getName obudwu obiektów i dostajemy w komunikatach:

car.getName(): car
person.getName(): person

Czyli wszystko standardowo. W obiekcie car this=car, a w obiekcie person this=person; W kolejnych 2 wywołaniach, metody test1 i test2 obiektu person, wywołujemy metode getName obiektu car, przekazując w pierwszym argumencie metod apply/call this, czyli person(bo wywołujemy z poziomu obiektu person). Spodziewamy się wywołać z poziomu obiektu car metode getName z this=person. Brzmi absurdalnie, ale w kolejnych dwóch komunikatach dostajemy:

car.getName(): person
car.getName(): person

Przykład ten nie niesie większego sensu, ale wydaje mi się, że dobrze oddaje ideę działania tych metod. Metody apply i call różnią się sposobem przekazywania dodatkowych argumentów, co nie zostanie omówione w tym artykule.

jQuery: Jak sprawdzić czy element istnieje?

Jak sprawdzić czy element istnieje za pomocą jQuery? Jak sprawdzić ile takich elementów istnieje? Ostatnio spotkałem się z takim problemem. Naturalnym odruchem jest napisanie następującego kawałka kodu:

var x = $('.some-element');
if(x) {//zakładamy że ten fragment kodu wykona się tylko wtedy gdy element istnieje
   alert('Błędne rozwiązanie!');
}

Niestety rozwiązanie to jest jak najbardziej błędne. Zmienna x zawsze będzie istnieć, będzie obiektem jQuery. Prawidłowy sposób polega na sprawdzeniu właściwości length tego obiektu. Wartość tej właściwości jes równa ilości znaleźionych elementów.

var x = $('.some-element');
if(x.length) {
   alert('Znaleziono ' + x.length + ' elementów.');
}

Rozwiązanie proste, ale może wpędzić w chwilę zakłopotania, jeżeli nie znamy prawidłowego sposobu.