Autor wpisu: batman, dodany: 12.11.2010 08:00, tagi: zend_framework
Co by nie pisać o Zend_Db, można z niego sporo wycisnąć. Jedną z takich wyciśniętych funkcjonalności są relacje. Wystarczy zdefiniować w klasach modelu zależne klasy i możemy cieszyć się relacjami, zamiast kombinować z joinami. Z początku relacje mogą być niejasne, jednak jak już je poznacie, nie będziecie mogli się bez nich obejść.
Wszystko zaczyna się w bazie. Przykładowe tabele to:
- users – lista użytkowników
- user_params – dodatkowe parametry użytkownika
- roles – role, np admin
- user_role – relacja między użytkownikami i rolami
CREATE TABLE users ( id serial NOT NULL, "login" character varying(50), "password" character varying(32), CONSTRAINT users_pkey PRIMARY KEY (id) ) CREATE TABLE user_params ( id serial NOT NULL, iduser integer, param_name character varying(250), param_value text, CONSTRAINT user_params_pkey PRIMARY KEY (id), CONSTRAINT user_params_iduser_fkey FOREIGN KEY (iduser) REFERENCES users (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE ) CREATE TABLE roles ( id serial NOT NULL, "name" character varying(150), CONSTRAINT roles_pkey PRIMARY KEY (id) ) CREATE TABLE user_role ( iduser integer NOT NULL, idrole integer NOT NULL, CONSTRAINT user_role_pkey PRIMARY KEY (iduser, idrole), CONSTRAINT user_role_idrole_fkey FOREIGN KEY (idrole) REFERENCES roles (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT user_role_iduser_fkey FOREIGN KEY (iduser) REFERENCES users (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE )
Następnie musimy stworzyć odpowiadające im klasy modeli (każda klasa powinna znaleźć się w osobnym pliku).
class Application_Model_DbTable_Users extends Zend_Db_Table_Abstract { protected $_name = 'users'; protected $_dependentTables = array( 'Application_Model_DbTable_UserParams', 'Application_Model_DbTable_UserRole' ); } class Application_Model_DbTable_UserParams extends Zend_Db_Table_Abstract { protected $_name = 'user_params'; protected $_referenceMap = array( 'User' => array( 'columns' => array('iduser'), 'refTableClass' => 'Application_Model_DbTable_Users', 'refColumns' => array('id') ) ); } class Application_Model_DbTable_Roles extends Zend_Db_Table_Abstract { protected $_name = 'roles'; protected $_dependentTables = array( 'Application_Model_DbTable_UserRole' ); } class Application_Model_DbTable_UserRole extends Zend_Db_Table_Abstract { protected $_name = 'user_role'; protected $_referenceMap = array( 'User' => array( 'columns' => array('iduser'), 'refTableClass' => 'Application_Model_DbTable_Users', 'refColumns' => array('id') ), 'Role' => array( 'columns' => array('idrole'), 'refTableClass' => 'Application_Model_DbTable_Roles', 'refColumns' => array('id') ) ); }
Jak to działa? W klasie “rodzica”, należy określić jaka tabela jest od tego rodzica zależna. Innymi słowy należy wskazać, w której klasie znajduje się klucz główny bieżącej klasy.
Zastosowanie relacji jest banalne i sprowadza się do wywołania jednej metody oraz wskazania, do której tabeli się odwołujemy. Jeśli chcielibyśmy pobrać wszystkie możliwe informacje, wystarczy, że napisze coś takiego:
$modelUser = new Application_Model_DbTable_Users(); // dane o uzytkowniku $user = $modelUser->find(1)->current(); // parametry uzytkownika. jako parametr podajemy nazwe klasy, z ktorej pobieramy dane $userParams = $user->findDependentRowset( 'Application_Model_DbTable_UserParams' ); // role uzytkownika. pierwszym parametrem jest tabela docelowa, drugim - tabela posrednia $userRoles = $user->findManyToManyRowset( 'Application_Model_DbTable_Roles', 'Application_Model_DbTable_UserRole' );
Relacje oferują jeszcze jedną ciekawą funkcjonalność. Możliwość pobrania danych z tabeli na podstawie relacji. Czyli mamy dany wiersz, np z tabeli user_params i na jego podstawie możemy pobrać dane powiązanego z nim użytkownika z tabeli users. Wygląda to następująco.
$modelUserParams = new Application_Model_DbTable_UserParams(); $userParam = $modelUserParams->find(1)->current(); $user = $userParam->findParentRow('Application_Model_DbTable_Users');
Do opisanych powyżej funkcjonalności dochodzi jeszcze jedna. W każdym z przypadków możemy do metody dodać obiekt Zend_Db_Table_Select, którym mamy możliwość ograniczania wyników.
Nie są to jedyne możliwości oferowane przez relacje w Zend_Db. Mamy możliwość skorzystania z “magii”, czyli z metod automatycznie tłumaczonych na odpowiednie klasy oraz reguł (jeśli w jednej tabeli jest kilka kluczy obcych z innej tabeli).