Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: ZF:llä tuotetun sivuston julkaisu

Sivun loppuun

tsuriga [24.04.2008 09:57:32]

#

ZF = Zend Framework, ongelmia kaksi:

1) Kuinka sivusto laitetaan julkiseen käyttöön siten, että vain index.php (+media) on webbihakemistoissa, application ja library webrootin ulkopuolella? Pika-aloitusoppaan rakenne on ainut, minkä olen saanut toimimaan, muilla tulee aina 'Exception: script 'main.phtml' not found in path (../application/layouts/scripts/:/home/<user>/application/views/scripts/)'. Domainin alla on useampia sivuja, joten pitäisi saada sivustolle omaan hakemistoon ainakin tuo application-hakemisto, librarynhan kaikki sivustot voisivat jakaa keskenään.

2) Mikähän on vikana kun serveri heittää 400/Bad Requestia jos osoiteriviltä jää uupumaan kauttaviiva? Ja Order deny, allow -rivin kanssa Internal Erroria, pelkkä Deny from all kyllä toimii.
Tämänhetkinen .htaccess, joka suoltaa Bad Requestia:

RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php

EDIT:

Lisäkysymys 3) Kuinkahan navigaatiolinkkien tulostus on hoidetaan oikein(TM)? Tällä hetkellä minun täytyy ympätä jokaiseen kontrolleriin seuraava,

<?php
    public function preDispatch()
    {
        $this->view->baseUrl = $this->_request->getBaseUrl();
    }
?>

jotta voin sitten käyttää viewissä seuraavaa:

<a href="<?php echo $this->baseUrl; ?>/auth">Login</a>

Vaan tässä tulee tuota toistoa ja olikohan tässä jopa jotain vikaakin.

Wizard [24.04.2008 18:59:17]

#

Oma työkoneeni teki lakon ja räjäytti näytönohjaimesta konkat pystyyn. Tietoaseman pojat lupasit koneen huomiseksi perjantaiksi joten lisää vastauksia voi odottaa silloin jos kukaan ei ehdi vastata ja vastauksia lisää kaipaat. Mutta mutta tässä alustavasti:

1) todennäköisesti ongelma on ZF:n alustuksessa. Jos käytät module/controller/action rakennetta, niin sinun pitää myös nimetä controllerit "oikein". Tähän törmäsin itsekin ja manuaalit olivat TOSI HUONOJA selittämään sitä. Itse asiassa sitä ei edes löytynyt manuaaleista vaan sain oikean infon keskustelupalstoilta. MCA (module-controller-action) on todella hyödyllinen, käytä sitä.

Jokatapauksessa: varmista, että omassa loaderissasi on Zend_Loader:autoload alustettu (jos nyt muistan tuon metodin nimen oikein).

Toinen asia minkä muuttaisin tuosta pika-alustuksesta, on rivi:

$frontController->setControllerDirectory('../application/controllers');

...muotoon:

$frontController->setModuleDirectory('jotain');

Nyt siis ilman IDE:ä tuo metodin nimi, varmista se omalla IDE:lläsi joka osaa kaivaa nuo käytettävissä olevat metodit.

Tuo pikaohje kertoo vain tuon systeemin käytön ILMAN moduleita jotka ovat suuremmissa projekteissa kuitenkin ehdoton "must".

Tulevassa oppaassa käytän tuota module -rakennetta, muut on minusta hömppää. Default on kuitenkin oletusmoduli ja ZF:ssä on onneksi älykkyyttä routerissa ymmärtää tuota URL riviä ja sitäkin voi säätää.

Mutta en ihan ymmärrä kuitenkin kysymystäsi tai ongelmaasi? Yritä napata errorit jos ne pääsee controlleriin asti, multimaagisella metodilla seuraavasti:

<?php
public function __call($method, $args) {
  echo 'action '.$method.' puuttuu';
  #$this->__forward('index'); // Ohjaa toisella actionille jos haluat
}
?>

Jolla siis ohjaat nuo kaikki ei-nimeämättömät actionit indexiin.

Jos taas virhe on puuttuvassa controllerissa tai puuttuvassa modulissa, on sinun tehtävä plugin joka nappaa nuo virheet. Plugarilla voit sitten uudelleenohjata tarvittaessa jos puuttuu controlleri tai moduli, mutta ne on aika karkeita ongelmia jotka kyllä pitäisi huomata testauksessa. Epäilen ongelman olevan väärin nimetyissä asioissa joissa ZF:ää on vaikea ymmärtää joskus.

Multimaagisesti voit napata puuttuvan actionin nimen myös suoraan requestista tuolla tämän viestin lopussa olevalla plugarilla jotakuinkin tyyliin:

echo 'Halutaan seuraava yhdistelmä: '.$request->getModuleName().'/'.$request->getControllerName().'/'.$request->getActionName();

...kun lisäät tuon edellämainitun routeShutdown metodille. Pääset virheen jäljille helposti.

EDIT: ja nyt löytyi tuo ongelma tuosta pikaoppaasta.

QuickStart/
application/
controllers/
views/
scripts/
library/
public/

Tuo on VÄÄRIN! Tuon application kansion alla TULEE OLLA kansio nimeltä DEFAULT jonka alla on sitten controllerit, modelit ja viewit. Siis tämä pätee vain ja KUN käytät moduleita projektissasi ja annat alustuksessa $front->getModuleDirectory('./Quickstart/application/');

Äää...menee sekavaksi. Kysy lisää kun et ymmärrä. ;)

2) Tuo on ihan oikein tuo rewrite rule, mutta onko sinun web-palvelin nyt sitten oikein säädetty ja onko rewrite mokkula edes päällä? Tuo on hieman outo ongelma, mutta jotenkin muistelisin törmänneeni joskus samantyyppiseen ongelmaan ja ongelman syy oli vajaasti toimita rewrite tai kokonaan puuttuva tuki sille.

Kohtaan 3 en ota kantaa, koska en käytä tuollaista tapaa.


Edit: tuohon kohtaan 1 voisin lisätä seuraavaa: joskus tein parin kolmen päivän työn kun kirjoitin kokonaan uuden bootloaderin. Tein sen ZF:n rakenteeseen ja tuon application hakemiston pistin sellaiseen järjestykseen, että itse Frameworkit eli library hakemisto oli include_dir:ssä luonnollisesti ja sitten application hakemisto on räjäytetty domainin perusteella. Sieltä se käy kyselemässä sitten domainin nimen "väärinpäin" eli ensin puurakenteessa on TLD (com/net/org/fi...), sitten itse domain nimi ja sen jälkeen muuttava ja vapaa määrä prefixejä (www, web, www2...). Tuo bootloader tukee nyt sitten rakennelmaa jossa voit aina lisätä uuden palvelun uudella URL nimellä tuonne puurakenteeseen, frameworkit on aina samoja jne. On säästänyt työmäärää jotakuinkin 3-4 viikon edestä jälkeenpäin kun teen tosi paljon backend koodausta kuitenkin.

Vinkiksi voisin antaa, että ammu tuo ZF:n oma .phtml syvimpään suohon eli yliaja pääte loaderissa (enpä nyt muista syntaxia). Toinen vaihtoehto on se, että älä oletuksena kutsu Viewiä vaan kutsu sitä vain ja kun on oikeasti tarve. Varsinkin sellaiset sivustot jossa AUTH on pakollinen, on helpompi rakentaa sekä tehdä forwardeja jos ei oletuksena kutsuta koko ajan jotain oletus viewiä. Lisäksi se antaa hirveästi lisää muunneltavuutta projektiin, mutta toisella puolella vaakakuppia on sitten se, että joudut rakentamaan jonkin verran noita preDispatch & postDispatch metodeja sekä lisäämään actioniin $this->render actionin viimeiseksi riviksi kun actionin suoritus lopetetaan ja ennen kuin siirrytään postDispatchin puolelle dispatcherin suorituksessa.

Suosittelen myös käyttämään plugaria jossa on koko router rakenne ammuttuna palasiin ja voit tehdä yleisluontoisia ajoja ilman controllerien tukea.

Eli jotakuinkin näin:

<?php
class MyPlugin extends Zend_Controller_Plugin_Abstract
{
    public function routeStartup(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>routeStartup() called</p>\n");
    }

    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>routeShutdown() called</p>\n");
    }

    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>dispatchLoopStartup() called</p>\n");
    }

    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>preDispatch() called</p>\n");
    }

    public function postDispatch(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>postDispatch() called</p>\n");
    }

    public function dispatchLoopShutdown()
    {
        $this->getResponse()->appendBody("<p>dispatchLoopShutdown() called</p>\n");
    }
}


// Ja sitten omaan loaderiin hieman muokkausta:
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('/path/to/controllers')
      ->setRouter(new Zend_Controller_Router_Rewrite())
      ->registerPlugin(new MyPlugin());
$front->dispatch();

?>

Tuo plugari koskee KAIKKIA moduleita ja controllereita. Erittäin kätevä, suosittelen!

Toivon mukaan oli ymmärrettävä selitys?


-W-

tsuriga [25.04.2008 00:04:51]

#

1. Eli puhe varmaankin tästä: 7.11. Using a Conventional Modular Directory Structure. Kokeilen korjailla rakennetta tuohon suuntaan.

2. Futuronin PHP5-servu, ykkössarjan apassi. Omassa apassissa toimii ilman päättävää kauttaviivaa, ja rewrite-tuenkin laitoin äsken päälle, mutta silti tulee not foundia, eli ei ohjaudu tuonne index.php.

3. Plugaria meinasin vaan en taida päästä sieltä käsiksi viewiin mitenkään järkevästi? Myös layout-plugaria, mutta siinäkin antoi nullia getLayout(), ja lopetin sitten siihen. Noh, eipä tuota baseUrlia välttämättä tarvitse kaikissa kontrollereissa, joten menköön noin. Tai itse asiassa, laitoin index.php:n asettamaan hakemistojuuren, jonka bootloaderi sitten iskee rekisteriin, josta layout sen sitten hakee tyylejä ja javascriptejä varten. Vähän purkkaratkaisun makua kieltämäti.

Nyt en valitettavasti kerkee kauhiasti kirjottelemaan uusiks kokonaisia rakenteita, mutta mitä nyt ideoin tulevaisuudessa niin:
-Oma routeri, joka ohjaisi roolien mukaan niin, että mikäli löytyy view-tiedosto kera roolin (index.admin.phtml), niin käytetään sitten sitä oletustiedoston sijaan. Tässä vaiheessa tuntuu omassa mielessä järkevältä, varsinkin jos tähän saa kaveriksi vielä:
-Rooliloaderin, joka lukee roolit ja relaatiot .ini-tiedostosta. Saapahan lisättyä helposti eri käyttäjätasoille vaikka kokonaan erilaiset sivut, ja tarvittaessa uusia rooleja.

Wizard [25.04.2008 07:24:28]

#

1) Juuri tuosta on kyse, tuo on oikein kätevä systeemi ja rakenne. Antaa lisää skaalautuvuutta softiin.

2) Ykkössarjan Apache?!?! Jopas ajaa pojat vanhoilla jutuilla...kokeile personal.fi palvelua jos ei muuten, toimii varmasti. Jos ei toimi, niin ilmoita. ;)

3) Käytännössä view on vain tyhmä sivu jolla tulostetaan kaikki mitä sille työnnetään. Siinä ei ole älyä eikä logiikkaan sen enempää. Controllerissa ohjaat sitä mitä viewille tullaan tulostamaan ja tarvittaessa controller hakee tietoa modelsien avulla.

Tuossa plugarissa on nuo samat preDispatch & postDispatch metodit kuin sinulla controllerissa, mutta sillä edellytyksellä, että ne ovat globaaleja. Tosin niissä oli jokin sääntö, milloin nuo globaalit tulee yliajetuksi ja se sääntö ei nyt muistu mieleen.


Itse en ole koskaan edes miettinyt sitä, että kirjoittaisin oman routerin. Noita ZF:n routereita saa customoitua ihan kivasti jos on tarpeen, mutta itse päätin vain ottaa tuon viewin automaattisen tulostuksen pois päältä. Sitten lisäsin tuohon jo mainitsemaani plugariin omat ACL & AUTH laajennukset sekä hieman oma Framework vielä tekee multimaagisia asioita ja nyt sitten pelittää huomattavasti paremmin.

Noilla plugareilla saa aikaan ihmeitä ja ne on siitä kivoja, että ne ajataan aina joka controllerin yhteydessä ja joka softassa. Pitää vain plugarit ja niissä ajettavat omat laajennukset kyllä sitten suunnitella todella hyvin. Itsellänikin on tällä hetkellä 14 eri palvelua (yli 40 erilaista URL osoitetta) samassa hakemistopuussa (application). Sama Framework hakemisto kaikissa, sama loader ja samat omat laajennukset kuten ACL & AUTH jne. Toimii hyvin, korjauksia helppo tehdä, varsinkin ylläpito on erittäin helppoa ja sen sellaista. ZF on hyvä taustarakenne josta saa paljon apuja omalle Frameworkille, mutta en olisi ikinä saanut siitä niin paljon irti jos en olisi kirjoittanut omaa Frameworkkia rinnalle.


-W-

tsuriga [25.04.2008 19:55:33]

#

EDIT: Siirsin tuon main.phtml views\scripts\-polun alle ja tämä toimii. Onko tämä ns. hyväksytty ratkaisuTM, vai pitäisikö käyttää tuota layouts-hakemistoa?

1) Tulee vieläkin 'Exception: script 'main.phtml' not found in path....

Nyt on rakenne seuraava:

www/
  ->htdocs/
      ->myapp/
          ->index.php
  ->zend/
      ->application/
          ->modules/
              ->myapp/
                  ->controllers/
                  ->models/
                  ->views/
                  ->layouts/
                  ->bootstrap.php
      ->library/

index.php

<?php

$modName = 'myapp';
require_once '../../zend/application/modules/myapp/bootstrap.php';

bootstrap.php (riisuttu)

<?php

$modRoot = dirname( dirname( __FILE__ ) );
$modDir = $modRoot . '/' . $modName;
$zendPath = dirname ( $_SERVER[ 'DOCUMENT_ROOT' ] ) . '/zend';

set_include_path(
                  get_include_path() . PATH_SEPARATOR .
                  $modDir . '/config' . PATH_SEPARATOR .
                  $modDir . '/models' . PATH_SEPARATOR .
                  $zendPath . '/library' . PATH_SEPARATOR .
                  $_SERVER[ 'DOCUMENT_ROOT' ] . '/' . $modName
                );

// ...

try {
    // ...
    /** Initiate FrontController **/
    $frontController = Zend_Controller_Front::getInstance();

    $frontController->addModuleDirectory( $modRoot )
                    ->setDefaultModule( $modName )
                    ->dispatch();
}

2) Omalla servulla oli vika AllowOverriden arvossa None, vaihdoin All niin johan pelittää rewritet.

3) Ideassani näin sen hyvän puolen, että noita viewejä voisi kirjoitella täysin PHP:stä tietämätönkin. Nyt joutuu sumppailemaan ehtolauseilla viewissä tulostellessa poistolinkkejä yms.

tsuriga [27.04.2008 11:19:08]

#

Äeh, unohdin kokonaan määritelleeni layoutille asetuksia .ini-tiedostossa, pika-aloitusoppaassa oppien mukaisesti - tästä siis virheet. Järkevää installeria tässä yritän väsäillä, tällä hetkellä löytyy InstallController, joka tunnistaa asennushetken tyhjästä index-tiedostosta. Omaa Ini-luokkaa meinasin kanssa notta voisi hoitaa konffauksen kokonaan webin kautta, vaan jääköön tuonnemmaksi.

Opiskelija [28.04.2008 22:15:01]

#

3) http://akrabat.com/2008/03/17/updated-tutorial-for-zend-framework-15/ siellä neuvotaan tekemään helppi tuolle baseUrlille jolloin viewissä $this->baseUrl().

Kyllä pluginista viewiä pystyy käsittelee helposti mikäli tarvis.

<?php
class MyPlugin extends Zend_Controller_Plugin_Abstract
{
	public function preDispatch( Zend_Controller_Request_Abstract $request )
	{
		if ( !Zend_Controller_Action_HelperBroker::hasHelper('viewRenderer') )
		{
			Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setView( new Zend_View() );
		}

		Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->view->baseUrl
			= $request->getBaseUrl();
	}
}
?>

Mitenkäs ZF:n käyttö vaikuttaa sivujen nopeuteen jne...., kun kuitenkin välissä on periaatteessa turhia luokkia?

Wizard [29.04.2008 09:48:40]

#

ZF lataa automaagisesti noita luokkia lennosta. Joskus tuota asiaa tutkin syvemminkin ja huomasin, että tuo ei tuota juurikaan mitään häviöätä verrattuna normaaliin koodiin. Enemmänkin se on niin päin, että perinteisesti ohjelmoitu on paljon hitaampaa kuin ZF + omat oliot.

Nykyisillä laitteilla ja PHP tulkilla ei tuo ZF tuota yhtään ylimääräistä päänvaivaa.

-W-


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta