Toon posts:

[PHP/ZF] Autoloader en DB adapter globaal beschikbaar maken

Pagina: 1
Acties:

Onderwerpen


  • GWTommy
  • Registratie: Mei 2008
  • Laatst online: 29-05 09:34
Hallo,
Een twee jaar geleden heb ik een systeem opgezet met ZF. Gewoon het standaard forum gedoe, etc. Dat is nooit echt verder ontwikkeld of heb ik geen aandacht aan besteed. Nu ben ik weer met iets bezig, maar ik wil toch wat basis dingen weten. OO basis snap ik toch wel denk ik zelf, een aantal dingen wil ik even duidelijk hebben. Ik maak gebruik van de ingebouwde MVC implementatie van ZF.

Als eerste.
In m'n bootstrap wordt de Zend_Db_Adapter gezet:
PHP:
1
2
3
4
<?php
    public function _initDatabase() {
        $db = Zend_Db::factory($this->config->resources->db);
        Zend_Registry::set('db', $db);

Zoals je ziet gaat die naar Zend_Registry om vervolgens in modellen weer uit het register te trekken in de init() om vervolgens naar $this->db te schrijven (van het betreffende model). Is hier een betere manier voor om dit niet iedere keer in ieder model te hoeven doen maar globaal te regelen?

Tweede.
Wat is de beste manier om in ZF 1.11.6 de autoloader neer te zetten en alle classes te autoloaden? Sinds mijn eerste kennismaking met ZF lijkt Zend_Autoloader niet meer beschikbaar te zijn (of hoe heette die ook al weer?). Het is natuurlijk vanzelfsprekend dat ik dit in of voor m'n bootstrap al geïnitialiseerd wil hebben. Hoe doe ik dat?

Thnx

  • YopY
  • Registratie: September 2003
  • Laatst online: 01:11
Kort antwoord: Nee.

Lang antwoord: Er zijn andere mogelijke aanpakken.

Ten eerste, je 'kopieert' nu telkens je DB verbindingsobject naar je model, en dat stukje code kopieer je voor elk model. Kopieren betekent dat er een betere oplossing voor moet zijn.

Je zou in dit geval je model classes een 'common ancestor' kunnen geven, een class die je models extenden die zelf de logica bevat voor het onthouden van een verwijzing naar je model. Een alternatief is om een functie in die base class te bouwen die Zend Registry ophaalt.

Ten tweede, je zou ook kunnen kijken naar Dependency Injection. In plaats van dat je Model verantwoordelijk is voor het ophalen van een verwijzing naar je db, geeft je bootstrap deze verwijzing zelf door naar het Model. Dit is echter niet echt een geschikte oplossing voor gebruik in PHP, aangezien het verspilling is om alle models te initialiseren terwijl er misschien maar 1 gebruikt wordt.

(als je nieuwsgierig bent, zend registry zoals je het hier gebruikt is een implementatie van het Service Locator pattern)

  • kwaakvaak_v2
  • Registratie: Juni 2009
  • Laatst online: 06-06 21:46
In de 1.11 documentatie staat toch echt iets over de autoloader

En wat betreft die eerste vraag, geen idee hoe ZF het nu precies verwacht, maar ik zou zeggen dat je met een centraal config object en wat dependency injection een eindje zou moeten kunnen komen.

Driving a cadillac in a fool's parade.


  • Cartman!
  • Registratie: April 2000
  • Niet online
Ik gebruik altijd:

PHP:
1
Zend_Db_Table_Abstract::setDefaultAdapter( $db );


in de bootstrap, dat werkt als een zonnetje :)

  • Freeaqingme
  • Registratie: April 2006
  • Laatst online: 21:15
Waarom zou je niet gewoon Zend_Application_Resource_Db gebruiken?

No trees were harmed in creating this message. However, a large number of electrons were terribly inconvenienced.


Acties:
  • 0Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Als je iets _altijd_ in de init functie zet dan kun je gebruik maken van Action Helpers.

Let bij het bootstrappen ook altijd op dat je de volgorde correct hebt. Je bovenstaande code zou nog iets als $this->bootstrap('autoload'); moeten hebben. Deze _init werkt namelijk niet zonder.

Acties:
  • 0Henk 'm!

  • GWTommy
  • Registratie: Mei 2008
  • Laatst online: 29-05 09:34
De autloader heb ik nou zo gedaan:
PHP:
1
2
3
4
<?php
        require_once ("Zend/Loader/Autoloader.php");
        $autoloader = Zend_Loader_Autoloader::getInstance();
        $autoloader->setFallbackAutoloader(true);


De Zend_Db_Adapter heb ik zo gedaan:
PHP:
1
2
3
4
<?php
        $db = Zend_Db::factory($this->config->resources->db);
        Zend_Registry::set('db', $db);
        Zend_Db_Table_Abstract::setDefaultAdapter($db);


En ieder model extend ik nou met Zend_Db_Table_Abstract. Dat werkt goed, alleen zit ik met één probleem. Dat is dat de functie _setupPrimaryKey() op de controller waar het allemaal begint wordt aangeroepen (dus door de abstracte class). Dat is dus niet de bedoeling want die controller kent die methode helemaal niet. Die moet dus aangeroepen worden op de class van het model of de abstracte class (is inweze het zelfde omdat het model gebaseerd is op de abstracte class). Wat een gedoe. Ben er maar even uit geweest en het is toch veel veranderd in zo'n korte tijd, en ik weet niet eens meer hoe het wás.

In ieder geval bedankt voor jullie hulp.

Acties:
  • 0Henk 'm!

  • GWTommy
  • Registratie: Mei 2008
  • Laatst online: 29-05 09:34
Diverse mensen ondertussen hierover gesproken en zouden totaal niet weten wat het probleem is. Wat een oponthoud..

Acties:
  • 0Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
is dat de functie _setupPrimaryKey() op de controller
Je haalt hier vanalles door elkaar. Je moet gewoon je primary key in je table model instellen:
klik

Acties:
  • 0Henk 'm!

  • GWTommy
  • Registratie: Mei 2008
  • Laatst online: 29-05 09:34
PHP:
1
2
3
4
5
6
<?php

class SessionModel extends Zend_Db_Table_Abstract
{
    protected $_name = 'sessions';
    protected $_primary = 'id';


Dat doe ik al ;-)
Maar dan nog gaat het fout.

Hier te zien in m'n stack trace:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
#0 /home/***/domains/***.nl/library/Zend/Db/Table/Abstract.php(1031): Zend_Controller_Action->__call('_setupPrimaryKe...', Array)
#1 /home/***/domains/***.nl/library/Zend/Db/Table/Abstract.php(1031): LoginController->_setupPrimaryKey()
#2 /home/***/domains/***.nl/application/alpha/models/SessionModel.php(15): Zend_Db_Table_Abstract->insert(Array)
#3 /home/***/domains/***.nl/application/alpha/controllers/SessionController.php(86): SessionModel->armSession('973', '013748b2d049a25...')
#4 /home/***/domains/***.nl/application/alpha/controllers/SessionController.php(54): SessionController->armSession()
#5 /home/***/domains/***.nl/application/alpha/controllers/LoginController.php(55): SessionController->setSession('credentials', Array)
#6 /home/***/domains/***.nl/library/Zend/Controller/Action.php(513): LoginController->indexAction()
#7 /home/***/domains/***.nl/library/Zend/Controller/Dispatcher/Standard.php(295): Zend_Controller_Action->dispatch('indexAction')
#8 /home/***/domains/***.nl/library/Zend/Controller/Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
#9 /home/***/domains/***.nl/library/Zend/Application/Bootstrap/Bootstrap.php(97): Zend_Controller_Front->dispatch()
#10 /home/***/domains/***.nl/library/Zend/Application.php(366): Zend_Application_Bootstrap_Bootstrap->run()
#11 /home/***/domains/***.nl/public_html/alpha/index.php(30): Zend_Application->run()
#12 {main}


Je ziet dat _setupPrimaryKey() op LoginController wordt aangeroepen in plaats van het model of Zend_Db_Table_Abstract

Acties:
  • 0Henk 'm!

  • Freeaqingme
  • Registratie: April 2006
  • Laatst online: 21:15
En dan wel je stacktrace posten, maar niet de exception...

No trees were harmed in creating this message. However, a large number of electrons were terribly inconvenienced.


Acties:
  • 0Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Stack trace is wel handig, maar zoals freeaqingme zegt is het weinig waard zonder foutmelding. Ook relevante code kan helpen.

Volgens mij gaat het bij SessionModel op line 15 fout. Dat is in de armSession functie.

Acties:
  • 0Henk 'm!

  • GWTommy
  • Registratie: Mei 2008
  • Laatst online: 29-05 09:34
Excuses. De foutmelding zelf is niet zo bruisend aangezien ik 'm al vrij vertaald hier neer heb gezet:
code:
1
2
3
Exception information:

Message: Method "_setupPrimaryKey" does not exist and was not trapped in __call()


Mijn code:
in LoginController::action r55:
PHP:
1
2
<?php
$attemptReturn = SessionController::setSession('credentials', $_POST);


in SessionController::setSession r86:
PHP:
1
2
<?php
SessionModel::armSession(self::uId(), session_id());


in SessionModel::armSession r10/12:
PHP:
1
2
3
4
<?php
    public function armSession($uId, $sessionId)
    {
        self::insert(array('...


Ik heb alleen de nuttig stukken gepost, anders komen hier elle lange classes die jullie moeten gaan doorspitten, dus ik bepaar jullie wat werk.

Overigens lijkt de functie static maken dé oplossing, maar dat wil ook niet, om de simpele reden dat ZF dan moeilijk gaat doen omdat het dus niet in een object omgeving is en toch het object probeert aan te roepen.
code:
1
Fatal error: Using $this when not in object context in /home/***/domains/***.nl/library/Zend/Db/Table/Abstract.php on line 1031


Er zit toch een fout in mijn logica ergens vrees ik. Bug in ZF lijkt me sterk ;-)
Waarschijnlijk zal mijn denkwijze gewoon knullig zijn.

Acties:
  • 0Henk 'm!

  • Freeaqingme
  • Registratie: April 2006
  • Laatst online: 21:15
Ik gok dat jij _setupPrimaryKey() aanroept op een object dat geen instance is van zend_db_table. Wat overigens een nonstatic method is:
root@dolf-laptop:/home/dolf/Projects/ZF/trunk# grep setupPrimaryKey library/ -Rni
library/Zend/Db/Table/Abstract.php:870: protected function _setupPrimaryKey()

No trees were harmed in creating this message. However, a large number of electrons were terribly inconvenienced.


  • GWTommy
  • Registratie: Mei 2008
  • Laatst online: 29-05 09:34
Bijna correct. De functie wordt inderdaad op een object aangeroepen dat een instance is van Zend_Controller_Action, maar dat doe ik niet zelf. Het zal mij een worst weze of die functie wordt aangeroepen of wat die doet, ZF doet het namelijk zelf.

Na jouw bericht het ik overigens het probleem gevonden denk ik.
Je zegt dat het geen statische functie is, dus heb ik in plaats van
PHP:
1
2
<?php
SessionModel::armSession(self::uId(), session_id());


PHP:
1
2
$sessionModel = new SessionModel();
$sessionModel->armSession(self::uId(), session_id());


Achteraf lijkt het dus super makkelijk, maar goed. Het zat inderdaad in mijn logica.

Bedankt allemaal!
Pagina: 1


Tweakers maakt gebruik van cookies

Tweakers plaatst functionele en analytische cookies voor het functioneren van de website en het verbeteren van de website-ervaring. Deze cookies zijn noodzakelijk. Om op Tweakers relevantere advertenties te tonen en om ingesloten content van derden te tonen (bijvoorbeeld video's), vragen we je toestemming. Via ingesloten content kunnen derde partijen diensten leveren en verbeteren, bezoekersstatistieken bijhouden, gepersonaliseerde content tonen, gerichte advertenties tonen en gebruikersprofielen opbouwen. Hiervoor worden apparaatgegevens, IP-adres, geolocatie en surfgedrag vastgelegd.

Meer informatie vind je in ons cookiebeleid.

Sluiten

Toestemming beheren

Hieronder kun je per doeleinde of partij toestemming geven of intrekken. Meer informatie vind je in ons cookiebeleid.

Functioneel en analytisch

Deze cookies zijn noodzakelijk voor het functioneren van de website en het verbeteren van de website-ervaring. Klik op het informatie-icoon voor meer informatie. Meer details

janee

    Relevantere advertenties

    Dit beperkt het aantal keer dat dezelfde advertentie getoond wordt (frequency capping) en maakt het mogelijk om binnen Tweakers contextuele advertenties te tonen op basis van pagina's die je hebt bezocht. Meer details

    Tweakers genereert een willekeurige unieke code als identifier. Deze data wordt niet gedeeld met adverteerders of andere derde partijen en je kunt niet buiten Tweakers gevolgd worden. Indien je bent ingelogd, wordt deze identifier gekoppeld aan je account. Indien je niet bent ingelogd, wordt deze identifier gekoppeld aan je sessie die maximaal 4 maanden actief blijft. Je kunt deze toestemming te allen tijde intrekken.

    Ingesloten content van derden

    Deze cookies kunnen door derde partijen geplaatst worden via ingesloten content. Klik op het informatie-icoon voor meer informatie over de verwerkingsdoeleinden. Meer details

    janee