Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [ZendFramework] Problem z Zend_Db
Forum PHP.pl > Forum > PHP > Frameworki
kalipek
Witam serdecznie,

od wieeeelu godzin próbuję rozwiązać ten dziwaczny problem, szukam w różnych tutorialach, na różnych forach, stosuję niby rozwiązania identyczne jak tam, jak widzę, że nie działa to sam próbuję kombinować i ciągle to samo: "An error occurred. Application error." albo "Fatal error: Call to a member function select() on a non-object ..."

Chcę mieć model, do którego przez kontroler będę przesyłał zmienną wziętą z parametru w URLu, która to zmienna będzie nazwą tabeli w bazie danych. Potrafię to zrobić w ten sposób:

Bootstrap.php:
  1. // setup database
  2. $config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'production');
  3. Zend_Registry::set('config', $config);
  4.  
  5. // setup database
  6. $db = Zend_Db::factory($config->resources->db->adapter,
  7. $config->resources->db->params->toArray());
  8. Zend_Db_Table::setDefaultAdapter($db);
  9. Zend_Registry::set('db', $db);


Funkcja w modelu:
  1. $dbAdapter = Zend_Registry::get('db');
  2. $stmt = $dbAdapter->query('select * from ' . $nazwaTabeli);
  3. return $stmt->fetchAll();



Ale chciałbym wykorzystać w pełni możliwości ZF i skorzystać z Zend_Db_Select. Przykładowy kod, który starałem się ujarzmić:

w modelu:
  1. $_reg = Zend_Registry::getInstance();
  2. $_db = $_reg->db;
  3. $select = $_db->select();
  4. $select->from($nazwaTabeli);
  5. return $select->fetchAll();


Co ja mam zrobić/dodać/usunąć w modelu/kontrolerze/bootstrapie, żeby ta lub jeszcze prostsza wersja (bez dwóch pierwszych linijek) działała? :/ Aha, i te rozwiązania nie działają mi nawet kiedy w samym modelu na sztywno ustawię z jakiej tabeli ma brać dane. Niestety manual Zenda również mi nic nie dał..
melkorm
Jeżeli masz
  1. Zend_Db_Table::setDefaultAdapter($db);


To w modelu nie musisz się odwoływać do adaptera (bo bierze defaultowy uprzednio zdefiniowany)

W tym przypadku to też nie jest potrzebne:
  1. Zend_Registry::set('db', $db);


Bo możesz to uzyskać poprzez
  1. Zend_Db_Table::getDefaultAdapter();


W modelu:
  1. $sql = $this->select()->where(...)->order(..); //itp
  2. return $this->fetchAll($sql );

kalipek
Zrobiłem jak piszesz, wyszło:

  1. Fatal error: Call to undefined method Application_Model_Oferta::select() in D:\xampp\htdocs\zend_proba_bazy\application\models\Oferta.php on line 9


wkleję cały kod z modelu:

  1. class Application_Model_Oferta
  2. {
  3.  
  4. function listaProduktow($kategoria)
  5. {
  6.  
  7. $sql = $this->select()->from($kategoria);
  8. return $this->fetchAll($sql);
  9.  
  10. }
  11.  
  12. }


czy to tak miało wyglądać? Czy np z nazwą klasy jest wszystko ok? Wiem, że jak chcę mieć jeden model dla jednej tabeli to wtedy nazywam go tak jak tabelę w bazie i korzystam z Zend_Db_Table_Abstract, przykładowo:

  1. class Application_Model_DbTable_Ofirmie extends Zend_Db_Table_Abstract
  2. {
  3.  
  4. protected $_name = 'ofirmie';
  5.  
  6. function Artykul($strona)
  7. {
  8.  
  9. $sql = $this->select()->where('nazwa = ?', $strona);
  10. return $this->fetchRow($sql);
  11.  
  12. }
  13. }


działa pięknie i rozumiem w jaki sposób, niczego nie muszę dodawać w bootstrapie, bo dane bierze bezpośrednio z application.ini.

A z tamtym ustrojstwem za chiny nie daję rady :-) Mogę oczywiście skorzystać z rozwiązania "jeden model = jedna tabela", ale chciałbym nauczyć się robić to na różne sposoby.
bendi
Jezeli dobrze, widze to ustawiasz dbAdaptor'a w stylu "tablicowym"
Cytat(kalipek @ 6.03.2011, 21:55:12 ) *
  1. // setup database
  2. // (...)
  3. Zend_Registry::set('db', $db);


A odwolujesz sie w stylu "obiektowym"
Cytat(kalipek @ 6.03.2011, 21:55:12 ) *
  1. // (...)
  2. $_db = $_reg->db;


I stad masz oryginalny blad: "Call to a member function select() on a non-object ..."
kalipek
Tak, to było jedno z miliona wypróbowanych rozwiązań i działało w przypadku tej łopatologicznej metody, którą opisałem w pierwszym poście ;-) teraz pozbyłem się tego zgodnie z radą Melkorma i dalej nic.


EDIT. Udało sięexclamation.gif biggrin.gif Dzięki chłopaki. Dla potomnych, po kolei:

w bootstrapie:
  1. function _initDB()
  2. {
  3. // setup database
  4. $config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'production');
  5. Zend_Registry::set('config', $config);
  6.  
  7. // setup database
  8. $db = Zend_Db::factory($config->resources->db->adapter,
  9. $config->resources->db->params->toArray());
  10. Zend_Db_Table::setDefaultAdapter($db);
  11. }


w kontrolerze:
  1. public function indexAction()
  2. {
  3. $this->view->kategoria = $this->_getParam("kategoria");
  4. $modelOferta = new Application_Model_Oferta();
  5. $this->view->produkty = $modelOferta->listaProduktow($this->view->kategoria);
  6. }


w modelu:
  1. function listaProduktow($nazwaTabeli)
  2. {
  3. $db = Zend_Db_Table::getDefaultAdapter();
  4. $sql = $db->select()->from($nazwaTabeli);
  5. return $db->fetchAll($sql);
  6. }


w widoku:
  1. <pre>
  2. <?php print_r($this->produkty); ?>
  3. </pre>
melkorm
1. Po co w bootstrapie piszesz metodę inicjującą bazę danych skoro dzięki resources możesz to wszystko zapisać w pliku konfiguracyjnym (application.ini)

2.Model powinien być odzwierciedleniem jednego źródła danych, jeżeli chcesz grupę metod dla kilku/wszystkich tabel to stwórz sobie klasę która będzie pomostem między Twoimi modelami a Zend_Db_Table_Abstract.

3. Nazwa modelu nie musi mieć nazwy takiej jak w bazie, teoretycznie może ona nazywać sie dowolnie z odpowiednim przedrostkiem by Autoloader ją znalazł, jeżeli dziedziczy po Zend_Db_Table_Abstract (a powinna) nie musisz pisać zbędnego kodu by odwołać się do adaptera, wtedy wystarczy zrobić tak jak pisałem i wszystko będzie śmigać.

Plusem tego wszystkiego jest to że to jak Ty to piszesz jest "na około" i robisz sobie tylko więcej pracy nie wykorzystując całej mocy Zend_Framework'a.
kalipek
Masz rację, z pkt 1 to już po prostu zmęczenie wzięło górę. Uczę się dopiero Zenda i chcę najpierw zrobić aplikację, która działa tak jak sobie tego życzę i dopiero potem ją ulepszać, uczyć się coraz bardziej efektywnych i optymalnych metod.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.