locknet.ro

archive

Filtre ActiveRecord (before)

Update: (11.07.2006)

Incepand cu medick 0.3.0pre1 sintaxa pentru validari a fost modificata.
Am corectat acest articol pentru a reflecta ultimile schimbari.

Vorbeam acum cateva zile despre detalii foarte tehnice legate de validarea obiectelor ActiveRecord in medick. Spuneam ca aceste validari au loc in filtrele before_*, insa pana acum nu am explicat povestea lor.

Din nou, un articol lung, ce poate servi insa ca documentatie pentru framework.

Filtrele ActiveRecord pentru medick sunt practic niste metode oferite de framework, dar implementate de utilizator prin care se poate interveni in cel putin doua puncte cheie din viata unui obiect ActiveRecord: inaintea sau dupa efectuarea unei operatii legate de baza de date cu acel obiect.
Voi detalia filtrele before_, urmand ca intr-un articol viitor sa explic ce se intampla in filtrele after.

1) Filtre before_

Sunt 4 metode ce pot fi implementate, executate inainte de efectuarea unei operatii cu obiectul detinut. Aceste filtre sunt declarate ca metode cu vizibilitate protected si vor returna o valoare boolean , TRUE va permite continuare operatiei curente iar FALSE va intrerupe aceasta operatie.
Cele mai cunoscute utilizari includ: validarea anumitor proprietati ale obiectului curent, setarea de valori implicite pentru anumite campuri sau efectuarea unor operatii suplimentare declansate de crearea obiectului curent (db triggers).
Operatiile posibile (numele metodelor) sunt:

1a) before_insert

Executat inainte de inserarea obiectului in baza de date.
Poate cel mai bun exemplu este un obiect user care inainte de a fi creat, va trebui sa aibe proprietatea terms_and_conditions cu valoarea 1 pentru a semnala ca user-ul curent a fost de acord cu termenii si conditiile prezentate:

class User extends ActiveRecord {

  protected function before_insert() {
    // conditiile impuse nu au fost aceptate:
    if ($this->terms_and_conditions != 1) {
      // adaugam un mesaj de eroare:
      $this->getField('terms_and_conditions')->addError('Conditiile nu au fost acceptate');
      return FALSE;
    }
    // setarea unui camp cu valoare initiala:
    $this->created_at= time();
  }
[ ... ]
}

// utilizare (in controller de exemplu):

$user= new User();
$user->insert(); // filtrul este executat!
// sau:
$user->save(); // filtrul este si in acest caz executat!
1b) before_update

Este un filtru executat inaintea actualizarii unui obiect ActiveRecord.


class User extends ActiveRecord {

  protected function before_update() {
    [....]
    // setarea unui camp cu valoare initiala:
    $this->updated_at= time();
    return TRUE;
  }

[....]

}

// utilizare:
$user= User::find(1); // gaseste user-ul cu id=1
$user->update(); // filtrul este executat
// sau:
$user->save(); // filtrul este executat si in acest caz.
1c) before_save

Filtru executat inaintea salvarii obiectului curent in baza de date.
Poate contine, de exemplu, metode comune de validare atat in cazul in care obiectul curent este nou (creat cu insert) sau se incearca doar actualizarea acestuia.


class User extends ActiveRecord {

  protected function before_update() {
    $this->validates_presence_of('name');
    return TRUE;
  }

[....]

}

// utilizare:
$user= User::find(1); // gaseste user-ul cu id=1
$user->save(); // filtrul este executat
// sau
$user= new User();
$user->name= 'Mihai';
$user->save(); // filtrul este executat
1d) before_delete

Este executat inaintea stergerii obiectului curent din baza de date. Un exemplu bun de folosire este stergerea mesajelor detinute de utilizatorul (user-ul) curent.


class User extends ActiveRecord {

  protected function before_delete() {

    // gaseste mesajele detinute de acest user
    $messages= Message::find('all', array('condition'=>'user_id=?'), array($this->id));
    // sterge mesajele.
    [....]
    return TRUE;
}

[....]

}

// utilizare:
$user= User::find(1); // gaseste user-ul cu id=1
$user->delete(); // filtrul este executat

Cam astea sunt cateva detalii si metode mai intalnite pentru folosirea acestor filtre.
Foarte important: nu uita sa adaugi linia return true chiar la sfarsitul filtrului, in caz contrar php va returna in mod implicit false!