Posts Tagged PHP
Module Specific Plugins with Zend Framework
Posted by MiST in Gedeelde Kennis, Projecten on Wednesday 5 May 2010
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.
- Bootstrapping
- Routing
- 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.
Michiel kan niet meer mee
Posted by MiST in Persoonlijk on Thursday 12 March 2009
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!
) 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
) 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:
- Sitemasters is geregistreerd met een belgisch domein
- 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:
- Wat is de Nederlanders/Vlamingen verhouding?
- Waarom zijn er zo weinig vragen van Vlamingen?
- Waarom zijn er zo veel (domme?) vragen van Nederlanders?
- 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!
OOP in PHP
Posted by MiST in Gedeelde Kennis on Saturday 7 March 2009
- 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.
Update: ZF on One.com Servers (and for other providers too)
Posted by MiST in Gedeelde Kennis on Tuesday 11 November 2008
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:
- Download the script above and unzip it to a location on your server.
- run the script and discover all your server settings (It’s kind of a PHP info
) - 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: - Finished! All should work properly…
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]
I hope this information was helpful.
Greetings,
MiST
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:
- 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.
- 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…
Naïve semi-ontwikkelaars en logins…
Posted by MiST in Gedeelde Kennis on Sunday 8 June 2008
Het www is ongelooflijk gegroeid sinds het ontstaan. Steeds meer en meer mensen beginnen uit te zoeken hoe ze webpagina’s moeten maken. De ene al wat geavanceerder (PHP, MySQL, .NET, …) dan de andere (HTML, CSS, …). (En dan heb je nog de soort die denkt dat hij een website heeft gebouwd als ie een blog of MySpace heeft opgezet…)
Anyway, dit betoog gaat over de geavanceerdere soort. Want het ultieme uitdaging waar ze ooit mee geconfronteerd worden is veiligheid. Tenminste, als ze dit ook zien als een uitdaging. Sta me toe dit even uit te leggen.
Vele scripters denken al gauw dat hun pagina veilig is als ze 2 vakjes hebben voor een username en password en een knopje om in te loggen. Zo staan er ook duizenden scripts op het internet. De uitdaging is quasi nihil (tenzij je nog niet kan werken met forms). Het enige wat ze over het hoofd hebben gezien is net waar het om gaat: veiligheid!
Nu weten we wel allemaal dat veiligheid nog weinig voorstelt dezer tijden, maar met het voorbeeld hierboven zou je dat niet mogen verbazen. Toch is dit – in mijn opinie – de verkeerde mentaliteit. Het gevoel van veiligheid is er misschien wel, maar de veiligheid is er juist helemaal niet! Nergens eigenlijk. Laatst las ik (een gerucht) dat de hele UAC van Windows Vista maar een hoop extra irritante venstertjes zou zijn. Het hele systeem is zo lek alsof je soep zou eten met een vork.
Even later dook dan nog een demo (http://youtube.com/watch?v=cOxWuKL2hWI) op van een persoon die met een Linux LiveCD het loginscherm van Vista kan omzeilen. Je krijgt gewoon de desktop op je loginscherm, en opgestart is Windows. Zielig eigenlijk. Zeker als je dan 2 posts verder leest dat de Kernel van de volgende Windows versie niet gewijzigd zal worden. Bye bye veiligheid, bye bye prestaties!
Toch zou ik graag bij het maken van mijn eigen webtoepassingen mijn gebruikers een zo hoog mogelijke veiligheid willen verlenen. Hier is een voorbeeld van hoe het NIET moet (een van die debiele scriptjes op internet dus, met allerlei tirlantijntjes, maar geen enkele vorm van veiligheid).
Stel je een pagina voor met 2 vakjes: username en password. De verwerking gaat als volgt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php require_once("config.php"); $username = $_POST['username']; $pass = md5($_POST['password']); $sql = "SELECT * FROM users WHERE username = $username AND password = $password"; $query = mysql_query($sql); if(mysql_num_rows($query)) == 1) { header('Location: private.php'); } else { header('Location: public.php'); } ?> |
Wat gebeurt er nu? Het script controleert of er in de database een unieke gebruiker zit met deze username-password combinatie en als dat zo is, wordt deze doorverwezen naar de private pagina, anders komt hij terug op het publieke gedeelte. Buiten het feit dat dit script niet SQL Injection safe is, is er nog geen sprake van veiligheid.
Stel, ik ben een hacker. Ik zie een login. Wat doe ik? Ik typ gewoon in de adresbalk “www.[het-domein].[de-extensie]/[de-folder]/private.php”. Wat gebeurt er? Ik kom in het privaat gedeelte zonder ook maar iets van een wachtwoord in te moeten geven. Met andere woorden, er is wel een deur, maar geen muur.
De bedoeling is dus een veilig script te maken. Het is noodzakelijk om op elke pagina te controleren of de gebruiker wel toegang heeft tot deze pagina (en dus niet er een pagina voor zetten, die controleert of je wel binnen mag). Dit moet lietst zo kort mogelijk.
validLogin() or die('No acces');
of
validLogin() or die(header('Location: public.php'));
Dit is hoe ik beveiliging zie. Ik weet ook wel dat er nog steeds achterdeurtjes zijn dan, maar dit garandeert wel meer veiligheid dan het vorige script.
De geïnteresseerde lezer wil uiteraard weten hoe de methode validLogin() dan moet ingevuld worden. Ik had gedacht aan het volgende.
Bij het inloggen wordt een session aangemaakt. Deze houdt de username, rechten, sessionid (standaard), IP-adres bij van de client. Bij het bekijken van een beveiligde pagina worden de rechten (voor het bekijken van de pagina) vergeleken met de rechten in de sessie en wordt het IP-adres gecontroleerd. Als het IP-adres niet hetzelfde is als het IP-adres waar mee ingelogd is (tijdens dezelfde sessie kan/mag de gebruiker niet van IP adres veranderen), wordt de gebruiker automatisch uitgelogd.
Voor het geval dat men de login wil opslaan in cookies zou ik het volgende doen. Als men een cookie opslaat, wordt een hash gemaakt van allerlei gegevens, en opgeslagen in de database in de rij van de gebruiker. Dezelfde hash wordt opgeslagen in de cookie. Met andere woorden heeft de gebruiker een passphrase en de database heeft er een om deze mee te vergelijken.
Natuurlijk ben ik geen veiligheidexpert, dus er zijn zeker verbeteringen mogelijk aan dit script. Bijvoorbeeld: de paswoorden laten hashen (MD5, Sha-1) met Javascript op de computer van de client, om zo de verbinding zo veilig mogelijk te maken, dat er geen paswoorden doorgegeven worden op een onveilige verbinding. Verbeteringen mag je dan ook steeds posten in een comment!
Ach, misschien moet ik maar ineens een RSA methode gaan uitvinden voor weblogins. Bij registreren krijg je dan enkel een deel van de sleutel, en het andere deel van de sleutel zit in de database. Daar ga ik mijn eindwerk nog eens wat research naar doen (na de examens).
Recent Comments