Posts Tagged PHP

Module Specific Plugins with Zend Framework

I have been looking over Zend Framework modules for some time now. Although I have some experience with the Zend Framework, my experience with modules is quite limited.

Setting up modules is not that difficult. Tutorials like the one of Jeroen will guide you flawlessly through this process. Jeroen uses another approach to layout switching though. I prefer to put all layouts in the layout folder and give them the same name as their module. Like this, switching can be easily done with the following plugin.

class Mist_Controller_Plugin_ModularLayout extends Zend_Controller_Plugin_Abstract
{
	public function preDispatch(Zend_Controller_Request_Abstract $request)
	{
		$layout = Zend_Layout::getMvcInstance();
		$layout->setLayout($request->getModuleName());
	}
}

Now, let’s get back to the problem.

The big misconception

The big problem with Zend_Application, for me, was that it did not do what I supposed it would do.

In a non-modular application I would use the Bootstrap to set up the View and other things (like illustrated in the tutorial of Rob Allen).

protected function _initView()
{
    $this->bootstrap('layout');
    $layout = $this->getResource('layout');
    $view = $layout->getView();
    $view->doctype(Zend_View_Helper_Doctype::XHTML1_STRICT);
    $view->headTitle('Some Application');
    $view->headTitle()->setSeparator(' - ');
}

Ome might think you could extend this behaviour to modules (by adding Zend_Application_Module_Bootstrap classes) and set up a different title for each module. Think again! Zend_Application bootstraps the entire application. So, if you were to make separate Bootstrap classes with _initView() methods, you would end up with a title ‘Trunk – *title set in Module1_Bootstrap*- *title set in Module2_Bootstrap* – …’ on each page.

The answer to this behaviour is simple, but it is hard to find (I did not fins it in the manual). There are three basic steps from request to response when working with Zend Framework.

  1. Bootstrapping
  2. Routing
  3. Dispatching

Zend_Application only takes care of the bootstrapping. So, at that point, it is not aware of the routing. That is why your application get fully bootstrapped first. As this happens for each request, it is a good practise to make bootstrapping as light as possible.

How does this resolve my problem? It does not. All module specific loading should happen using Plugins or Helpers. But how do you implement module specific Plugins? Adding the following line to my application.ini file did not do the trick.

admin.resources.frontController.plugins.view = Admin_Plugin_View

The plugin was used in every module. That is not what I wanted.

The solution

Because Zend_Application registered my plugins with all modules, I decided to register only one plugin (and my layout switcher) to manage the plugins. And here it is!

class Mist_Controller_Plugin_ModuleSpecificPluginLoader extends Zend_Controller_Plugin_Abstract
{
	public function preDispatch(Zend_Controller_Request_Abstract $request)
	{
		if($request->getModuleName() != 'default')
		{
			$plugins = $this->_getModuleSpecificPlugins($request->getModuleName());
 
			foreach($plugins as $plugin)
			{
				$instance = new $plugin();
				$instance->preDispatch($request);
			}
		}
	}
 
	public function routeShutdown(Zend_Controller_Request_Abstract $request)
	{
		if($request->getModuleName() != 'default')
		{
			$plugins = $this->_getModuleSpecificPlugins($request->getModuleName());
 
			foreach($plugins as $plugin)
			{
				$instance = new $plugin();
				$instance->routeShutdown($request);
			}
		}
	}
 
	protected function _getModuleSpecificPlugins($module)
	{
		$result = array();
		$fc = Zend_Controller_Front::getInstance();
		$pluginsPath = realpath($fc->getModuleDirectory() . "/plugins");
 
		$files = scandir($pluginsPath);
 
		foreach($files as $file)
		{
			if($file != '.' && $file != '..')
			{
				if(!in_array(realpath($pluginsPath . '/' . $file), get_included_files()))
				{
					require($pluginsPath . '/' . $file);
				}
 
				$reflectionFile = new Zend_Reflection_File($pluginsPath . '/' . $file);
				$classes = $reflectionFile->getClasses();
				foreach($classes as $class)
				{
					/* @var $class Zend_Reflection_Class */
					if($class->isSubclassOf('Zend_Controller_Plugin_Abstract'))
					{
						$result[] = $class->getName();
					}
				}
			}
		}
		return $result;
	}
}

It just looks for classes in the module plugin directory, checks whether they are plugins, and uses them if they are called for.

In closing

As you might have thought, this is not a very elegant approach to fix the module-specific-plugins problem, but it’s a quick one, and that’s all that mattered for me for now. Modules are – as Matthew said – second class citizens in ZF v1. I really hope for improvement in ZF2.0.

, , ,

2 Comments

Michiel kan niet meer mee

Wat is dat toch met die evolutie en toestanden? Ik ben een jaloers man, denk ik, maar ook een beetje bezorgd misschien van wat er op de markt komt van wannabees.

Zeg nooit dat ik beweerd heb dat ik de überpro ben. Wat ik wel zeg, is dat ik denk meer te weten dan de gemiddelde 14-jarige die wat rondkijkt, knipt, plakt en doet en dan zegt dat hij een website gemaakt heeft. Er is maar 1 ding dat meestal in mij opkomt als ik zo’n dingen zie…

*SLIK*, soms met plaatsvervangende schaamte.

De laatste tijd hang ik wat rond op www.sitemasters.be. Ik vind het leuk om de vragen van anderen te beantwoorden, om mee te zoeken naar oplossingen, om dingen te ontdekken waarvan ik het bestaan niet afweet! Alleen… *zucht*

Kijk, er zijn enkele dingen waar ik niet tegen kan: Opscheppers. “Oooooooooh, look at me, kijk wat ik gemaakt heeeeeeb, ik ben keeeeiiiiii goed….’ Vul de rest maar zelf aan, je kent zo’n mensen ook wel (als ik dat ben voor u, graag even melden ;) danku). Kenmerken: GROOT bakkes, klein verstand (vaak ook in grootte sterk beperkt, wat het voorgaande ook enigszins impliceert).

Er zijn er zo’n die immens ver staan en mij evenaren qua kennis (op hun 14e! :o ) en er zijn er die alleen maar knippen en plakken (het resultaat trekt op niets en ze snappen niet dat het niet werkt). Die eerste hoor je nooit (en daar ben ik stikjaloers op, echt wel, zeg nog eens dat IK de freak ben :D ) en je bent dus niet op de hoogte van hun bestaan. Die tweede categorie… post 3/4e van de berichten op sitemasters (of ‘t zal niet veel schelen).

Nu zijn er 2 dingen die mij opvallen:

  1. Sitemasters is geregistreerd met een belgisch domein
  2. 99,9% van die vragenstellers zijn Nederlanders.

(Hier toch al even nota maken dat ik niets tegen nederlanders heb, ik heb genoeg contact met enkele (:p) maar ik meen hier een mentaliteitsverschil te merken)

De volgende vragen komen bij mij op:

  1. Wat is de Nederlanders/Vlamingen verhouding?
  2. Waarom zijn er zo weinig vragen van Vlamingen?
  3. Waarom zijn er zo veel (domme?) vragen van Nederlanders?
  4. Waarom zijn het bijna alleen -25-jarigen?

Enkele mogelijke antwoorden:

  • Vlamingen zijn slimmer (wie weet… ik beweer niets)
  • Vlamingen durven geen vragen stellen (te veel schrik om iets doms te zeggen, dat wordt wel vaker vastgesteld tijdens de lessen)
  • -25-jarigen denken niet genoeg na, het enige dat telt is: ‘je mag er niets voor doen en toch moet het werken’, al de rest is af te keuren

Ik heb er geen problemen mee dat er vragen gesteld worden, maar waar ik wel problemen mee heb, is dat sommigen niet meer nadenken bij wat ze doen. Ik weet dat wat ik hier lig te verkondigen terug op mij toe te passen is ook, maar ik heb het hier over iets wat nauw aan mijn hart ligt en waar ik dus ook over wil zeveren.

Moraal van het verhaal: Als je niet wil nadenken bij het betere “programmeer”werk, laat het dan, of trek je een jaar terug op in een donker hoekje met een computer en kom terug als je iets geleerd hebt. Open source is mooi, zien hoe anderen iets maken is mooi, maar met kopieren kom je NERGENS!

Ik denk dat moest je aan meerdere van de vraagstellers vraagt wat de rest van hun programma doet, ze niet eens kunnen zeggen wat er gebeurt. Jammer…

Ik ben weer aan het zagen, tijd om te gaan slapen. Over and Out!

, , , ,

No Comments

OOP in PHP

  • PHP is leuk
  • OOP is leuk en krachtig

De combinatie van beide is zeer interessant. Helaas, OOP PHP staat nog maar in zijn beginschoenen. Er wordt echter hard aan gewerkt om hier meer functionaliteit in te pompen. Helaas verschilt het PHP OOP paradigma ook een beetje van het algemene OOP paradigma. Deze post is vooral voor mijzelf bedoeld (ik vergeet altijd wat mogelijk is en wat niet), maar kan tegelijk ook voor anderen zeer nuttig zijn.

Wat kan er wel?

  • Klassen definiëren (duh)
  • Encapsulatie door visibility modifiers (private, protected, public)
  • static en final (alleen voor methodes en klassen) keyword
  • Overerving (extends)
  • Interfaces
  • abstracte klassen
  • Destructoren

Wat kan er niet?

  • Overloading (dikke bummer, me dunkt!)
  • namespaces (wel vanaf PHP6)
  • throws definitie meegeven in header
  • returntype meegeven in header

Wat is er anders?

  • public static final voor attributen heet ‘const’ en hoeven geen $ (omdat het geen variabelen zijn)
  • PHP OOP heeft ‘magic methods’. Deze beginnen allemaal met 2 underscores (‘_’) en zijn gereserveerd voor PHP. Je kan ze echter wel overriden (in een uitgebreide klasse) en er nuttig gebruik van maken.
  • wanneer je wil verwijzen naar methodes binnen je klasse moet je ALTIJD refereren met ‘$this->’.
  • het puntje uit Java is ‘->’ voor objecten en ‘::’ voor klassen in PHP

Klassedefinitie

Zoals het gebruikelijke paradigma: class <classname> {}

Constructor

Waar in Java de constructor een (soort van) methode is die dezelfde naam heeft als de klasse, is dit bij PHP niet het geval. Het gaat wel (het was de eerste benadering van OOP in PHP4); sinds PHP5 is het gebruik van de magische methode __construct() echter aangeraden. Dit is perfect mogelijk wegens het missen van het concept overloading.

In PHP is de constructor ook een methode en krijgt dus als header ‘public function __construct()’

Nieuwe objecten aanmaken gebeurt ook op de gebruikelijke manier: $obj = new <classname>();

Overerving

De gebruikelijke manier: class <classname1> extends <classname2>

Meervoudige overerving wordt – zoals in Java – niet ondersteund.

Vergeet ook de parent::__construct() niet aan te roepen bij creatie en andere parent::methode() als je methodes overschrijft.

Interfaces

De gebruikelijke manier: class <classname> implements <interfacename>

Je kan wel meerdere interfaces implementeren (ook zoals Java)

Visibility modifiers

Ook in PHP kan je inhoud afschermen van de buitenwereld.

  • public is voor iedereen toegankelijk
  • protected is alleen toegankelijk voor zichzelf en kinderen
  • private is alleen toegankelijk voor zichzelf
  • publieke getters die private of protected waarden weergeven werken altijd

Autoload

Je kan in PHP meerdere klassen definieren in hetzelfde bestand. Hoewel het gaat, is het toch ook afgeraden, das niet handig. Je moet echter wel de nodige bestanden hebben geïntegreerd als je objecten van die klasse wilt aanmaken.

Hiervoor kan je de magische methode __autoload($classname) gebruiken. Wanneer PHP een klassedefinitie nodig heeft en deze niet gevonden heeft, zal hij uit zichzelf deze methode aanroepen (vandaar ‘magisch’). Als deze niet bestaat en de klasse niet is gevonden, heb je pech, en zal niet werken. Door de methode __autoload($classname) uit te werken kan je vooralsnog errors vermijden, zonder in elke klassedefinities een ellendig lange lijst met requires/includes te schrijven.

Magische Methodes

Met overloading bedoelt men in PHP het gebruik van de magische methodes. __construct() en __autoload werden al toegelicht. Verder zijn er nog:

  • __destruct() — Objecten vernietigen, vanaf PHP6 komt er ook een Garbage Collector.
  • __call() — wordt aangeroepen als je ontoegankelijke (private of protected) methoden aanroept
  • __callStatic() — wordt aangeroepen als je ontoegankelijke (private of protected) methoden aanroept in statische context.
  • __get() — wordt aangeroepen als je een ontoegankelijk (private of protected in enkele gevallen) attribuut oproept
  • __set() — wordt aangeroepen als je een ontoegankelijk  attribuut wil overschrijven
  • __isset() — wordt gebruikt wanneer je isset() test op ontoegankelijke attributen
  • __unset() — wordt aangeroepen wanneer je unset() uitvoert op ontoegankelijke attributen
  • __sleep() — Opslaan van een object voor later gebruik
  • __wakeup() — Terughalen van een object
  • __toString() — objecten omzetten naar een String-representatie
  • __invoke() — Wanneer een object wordt aangeroepen alsof het een methode was, zal deze methode uitgevoerd worden
  • __set_state() — doet iets wanneer een object tot string wordt vervormd met var_export()
  • __clone() — objecten klonen

Type Hinting

Zeer leuk dat ze hier aan gedacht hebben. PHP is zeer tolerant: floats, integers, booleans, … Je kan het allemaal door elkaar gebruiken, PHP converteert en interpreteert waar nodig. Toch is dit niet altijd handig wanneer je argumenten wil meegeven. Daarom kan je het type specifiëren en zo de input mogelijkheid limiteren.

public function __construct(Integer $number);

EDIT: Ik dacht dat deze hierboven kon, helaas: “Traditional type hinting with int and string isn’t supported.” Hier is het nog voor verbetering vatbaar!

public function __construct(array $array);
public function __construct(MyClass $myClass);

Exceptions

Zoals gebruikelijk:  throwable en catchable :) Je kan je eigen exceptions ook definieren door de klasse Exception te extenden.

Weetjes

  • Een PHP bestand dat niets rechtstreeks output, heeft geen sluittag ‘?>’ nodig. Het gebruik ervan is in dat geval zelfs afgeraden, omdat het bij includes een hoop lastig debugwerk voorkomt (wanneer je layout ineens een lijn verspringt enzo).
  • Je kan objecten aanmaken vanuit een variabele. Stel $var = “MyClass”, dan kan je schrijven: $obj = new $var(); en dan heb je een object van de klasse MyClass (als die voor PHP vindbaar is). Zelfde geldt voor methodes. $obj->$method(); Het is natuurlijk niet aan te raden dit zo te gebruiken gezien het niet echt een goede manier van programmeren is in mijn ogen.
  • De superklasse van PHP heet ‘stdClass’. Alle objecten erven hiervan.
  • Include nooit het bestand waarin je include regel staat, dan crasht apache…
  • In PHP kan je op een luie manier velden initialiseren. Wanneer in Java een veld niet bestaat, compileert het niet; wanneer je bij PHP een veld aanroept dat niet gedefinieerd is, wordt het on-the-go aangemaakt en aangeroepen (omwille van de dynamische types in PHP).

Dat is het zowat, als me nog iets te binnen schiet, voeg ik het toe.

,

No Comments

Update: ZF on One.com Servers (and for other providers too)

Hi All!

This post will be in English because I thought this information might be of any interest for everybody trying to get the Zend Framework to work on servers, which you can’t control completely (Shared Hosting, etc).

I updated the Compatibility Script. You can download it here.

What you should do:

  1. Download the script above and unzip it to a location on your server.
  2. run the script and discover all your server settings (It’s kind of a PHP info :) )
  3. Since you are reading this, I assume that you are not a Zend Framework Expert (trust me, neither am I)
    This would mean you used the instructions about the directory structure in the quick start provided on the homepage of Zend Framework.
    This also mean you need a .htaccess file in your public folder that goes like:
  4. RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} -s [OR]
    RewriteCond %{REQUEST_FILENAME} -l [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^.*$ - [NC,L]
    RewriteRule ^.*$ /path/to/your/public/folder/from/root/index.php [NC,L]
  5. Finished! All should work properly…

I hope this information was helpful.

Greetings,
MiST

,

1 Comment

Beginnen met Zend

Zonet mijn eerste stappen gezet in de richting van programmeren met Zend als tussendoortje voor afmattende examens… Ondertussen de officiële QuickStart aan het doornemen en er eveneens een Nederlandse tutorial bijgehaald (om onduidelijkheden, vakspecifieke terminologie die essentieel is voor het begrijpen te verhelderen).

Ik had al eens eerder deze maand een kijkje geworpen op Zend, en nu staan er twee dingen vast:

  1. Op het eerste zicht lijkt Zend Framework een hoop Chinees (mensen die PHP al chinees vinden, beware! :p) Het is echter een schitterende manier van programmeren. Natuurlijk heeft schoonheid zijn prijs en dat is nummer 2.
  2. Als je geen tijd hebt om je eerste stappen rustig te zetten, zet ze dan ook niet. Als je niet lijn per lijn gaat beredeneren wat er gebeurt, ga je er niet veel van snappen. Dit was toch mijn ervaring.

Anyway, ik ga er zeker mee doorzetten en er zullen ooit Zend-kindjes volgen… :)

, ,

No Comments