Digital Fashion

Rien de grand ne se fit jamais sans enthousiasme.

To content | To menu | To search

How I use the Zend Framework

Having started a few applications using the Zend Framework, I came out with a few practices that I tend to use over and over. In this post I'll quickly expose some of them and explain why I do things the way I do them. As you'll notice, most of them are already widely known and used over the ZF developer's community. Please remember that these practices are just what I do, and come with no garanty at all to be best practices.

Continue reading...

Plugin "related by tags" pour dotclear 2

update: nouvelle version disponible

Allez hop, j'ai codouillé rapidement aujourd'hui un plugin dotclear 2 pour afficher une liste des billets ayant le ou les mêmes tags que le billet en cours de lecture par l'internaute. Il est téléchargeable dès maintenant sous forme d'archive tar gzipée ou directement de package dotclear. Pour l'utiliser, rien de plus simple, il suffit d'ajouter le tag suivant dans votre template, à l'endroit où vous souhaitez afficher la liste des billets:

{{tpl:include src="_related_by_tags.html"}}

Et voilà c'est tout :-)

Bon par contre, il faut faire gaffe a comment on tag ses billets (genre pour celui là j'ai preferré ne pas le taguer php histoire d'avoir des résultats plus pertinents).

ps: si quelqu'un connait un moyen d'éviter d'avoir a rajouter un bout de code au template je suis preneur (mais j'ai la flemme de chercher là tout de suite).

PDO not throwing an exception when it should

Today I ran into an issue that I already ran into a few weeks ago when I did not have time to dig up, but today I had this time (this plus it's a really annoying issue as you'll see). The main symptom is that PDO does not throws exceptions when you'd expect it to. It's very annoying. The reason, in my case, seems to be that I am querying an old mysql (3.23.x in my case but any 4.x will do according to this bug report). I was not able to find any info from google, so I'm posting this here so that people know :-)

New home for pagination component documentation

For those caring, I just posted some quick documentation for the pagination component at my assembla space. More docs will follow (including extensive phpdoc docblocks I hope).

Zend Framework 1.0.2 PEAR package is available

A PEAR package for the 1.0.2 version of the Zend Framework is now available from the PEAR PHPMafia channel. As usual, to install just issue the following:

pear channel-discover pear.phpmafia.net
pear install phpmafia/Zend

Bugfixes release of Zend Framework pagination component

I just released on riskle's assembla space a new version of my pagination component for the Zend Framework which you can download right now:

Riskle Paginate r122

This release fixes a nasty bug in Riskle_Db_Table::fetchCols which prevented from retrieving the right count of cols involved in the query.

The table component has also been slightly rewritten following Erik's suggestion to move the parent mapping into _fetch. The parent mapping itself has been improved to allow "multi level" table joining. This will be best explained with an example:

Say you have three table, Foo, Bar and Quux, and you would like to execute the following query:

SELECT * FROM Foo JOIN Bar ON Foo.bar_id = Bar.id JOIN Quux ON Bar.quux_id = Quux.id

This is now possible with the following mapping (in Foo's class of course):

array(
    'Bar' => array('local' => 'bar_id', 'remote' => 'id'),
    'Quux' => array('local' => 'quux_id', 'remote' => 'Quux.id'),
);

Easy heh ?

As usual, any comments are appreciated, and please note that this code is released under the same license as the ZF itself, the new-bsd license.

Of controller plugins and directory layout

When anyone on #zftalk ask about where controller plugins should be kept, we usually responds something like have your own library namesapce alongside Zend/ and put it in it like YourNamespace/Controller/Plugin/YourPlugin.php. But what about application specific controllers ? There's a time where you have to write a plugin that relies on the application at such a level that using it elsewhere would make no sense. In that case, where can we store this plugin ? The question arised this morning, and we ended up to the fact that having a controller-level plugin directory would not hurt, after all. So one could have the following directory layout (simplified on purpose):

/application/modules/default
    /controllers
    /library/Plugin
        MyPlugin.php

The drawback is that in order to use autoload you would have to have each modules Plugin dir in the include path, which is a bit of a hassle. Instead, we could have the much more simple folloing layout:

/application
    library/Controller/Plugin
        MyPlugin.php

Which is simpler but does not allow for modules specific plugins. Anyway, the former layout would require a bit more logic in the bootstrap in order to extract every modules path as plugins are registered pre-dispatch.

Hope it helps with directory layout organization :-)

UPDATE

What I've finally decided to do is the following:

/application
    library/App/Controller/Plugin
        MyPlugin.php

So that application specific code gets prefixed with the App_ namespace.

Zend Framework Pagination, third strike

UPDATE: new version (r105) available.

The component was given a little rewrite as expected, but maybe a little bit later than I would have wanted to :-) So it now has its own Rowclass proxy from which you can pull various infos such as current page, page range, next page, etc all exposed as getter methods (that is, getCurrentPage, getPageRange, getNextPage, etc), which you won't really have to worry about since the brand new view helper will take care of that for you. Usage has changed a little, bit, so let's first have a look at what's happening from the controller point of view:

$table = new Riskle_Db_Table_Paginate(new Table, $this->_getParam('page'));
$this->view->rowset = $table->fetchAll();

Not much changed here, except we don't need anymore to call getPaginationInfos(). Nice ! Now the big part, the view:

$this->paginate($this->rowset);
echo $this->paginate()->previous();
echo $this->paginate()->navigation();
echo $this->paginate()->next();

The view helper uses the neat composite helper trick from naneau - which is a really cool trick, great job naneau my fellow no-more-a-bunny. The first call inits the helper, feeding him the necessary rowset to work on, then you just have to call the methods you need to draw the navigation links. As you may expect, previous and next method will return nothing if no page is available (actually, they return their second argument, which defaults to an empty string).

Also, it's worth noting that the bundled Riskle_Db_Table features the patch from Erik, as well as a totally rewritten fetchCols method (now uses a straight Zend_Db_Select object instead of the ugly trick it used to use).

My code is no longer available on subversion, I moved the project to assembla. Instead ou can download this component from the riskle space's files board (direct download), the file contains all classes needed for the component to work, just unzip it in your include_path and you're set.

As usual, any comments are more than welcome.

Ubuntu est chez Dell

Je ne sais pas si c'est récent ou non, mais toujours est-il qu'hier j'ai remarqué sur le site de dell france la posibilité d'acheter un ordinateur dell équipé d'Ubuntu Linux. L'initiative est vraiment sympa, d'autant plus que le matériel proposé me semble tout à fait abordable: on arrive à une configuration desktop équipée d'un core duo et d'1 Go de ram plus un écran 19 pouces pour moins de 600 euros (livraison comprise). J'achète.

Riskle_Form, a quick wrapup

So well, I've been busy these days working on my own implementation of a form component in the ZF spirit. This post is to help me see where I'm at with this component, as well as planning future evolution. I'll try my best to describe what it does and does not, and what it could do in the future.

Of course, while this is more of a personnal pense-bete than anything else, any comments are welcome.

Continue reading...

Thibs, jte déteste

You can burn in hell dude !

see also

Quand ssh est mou

Juste pour mémoire: http://www.refreshinglyblue.com/200....

Quick php5 pre-migration check

If you're wondering how much of a hassle it would be to migrate your app / codebase to php5, try the following command line (after having installed the php5-cli package of course):

find . -name "*.php" -exec /usr/bin/php5 -l {} \; | grep -v 'No syntax errors'

It'll show you all the files with syntax errors in it.

findBy{$Field} with Zend_Db_Table

A quick post to show how one can easily implement a findByField wrapper in Zend_Db_Table:

/**
         * Implements a simple findByField wrapper
         */


        public function __call($method, $args) {
                if (preg_match('/^findBy([a-zA-Z0-9]+)$/', $method, $parts)) {
                        $field = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $parts[1]));
                        if (!in_array($field, $this->_cols)) {
                                throw new Zend_Db_Table_Exception(sprintf('\'%s\' field not in row', $field));
                        } else {
                                $db = $this->getAdapter();
                                $where = $db->quoteInto($db->quoteIdentifier($field).' = ?', $args[0]);
                                return $this->fetchAll($where);
                        }
                }
        }

What it does is basically trapping any non-existant method call and check if the corresponding field exists, after converting CamelCasing to underscore_notation (eg: FooBar becomes foo_bar).

Zend_Db_Table and tables relationships

When developping a database tied application, you eventually come to a point where you get (at least) two tables with a parent/child relationship, such as for example a User table referenced by, say, a Post table (each post belonging to a specific user). That's basically the point where you need Zend_Db_Table relationships mechanism. the drawback of this mechanism is that, as far as I know, it does not produce joined queries to retrieve the parent data, but fires a query for each parent row. Thus instead of just using Zend_Db Relationships, I developped a simple yet effective auto-join mechanism that I called, in great simplicity, parent mapping. It supports multiple joins from multiple tables, remote fields specification and prefixing.

It is included in my db table class and you can see the interesting part of the code below for your convenience (Ignore the 3 first lines of the function as it is used for something else in my version of the framework).

Continue reading...

Stripping the logic: the Transfer Object

Sometimes you have to pass an object data to another object, or to another layer of your application (who said controller/view ?), while ensuring that the receiving entity will not be able to run business code encapsulated in your class. In the Zend Framework, several objects provide a toArray method, but that is not always sufficient as sometimes you'd like to keep with the $object->varname syntax.

That is where the Transfer Object arrives. While the preceding definition is not exact (that's not the real purpose of the Transfert Object in the J2EE spirit), This is the most common use that PHP Developers can make of it nowadays I think. So I came up with a very light implementation of a concept which I hope can prove useful for any folks getting by there.

See also:

Un mars et ça repart

Hop je reviens d'une petite (5 jours) semaine de vacances à Le Blanc, où j'ai pu enchainer quelques 6 sauts (en parachute) à 1200 et 1600 mètres d'altitude. C'était assez éprouvant mais bordel ça fait un bien fou.

Zend Framework Pagination reloaded

UPDATE

A new version of this component is available.

I have a new version of my pagination component which solve the issue previously pointed out by Guy. This update comes along with a subclassed version of Zend_Db_Table which allows counting and specific columns selection respectively via the fetchCount() and fetchCols() methods. Btw, the fetchCols() method is very hackish at the moment, and I'll certainly end up with rewriting it using a plain Zend_Db_Select statement.

As always, any comment is appreciated. I'm thinking of subclassing the Rowset class to fill it with pagination info getters like getPageCount(), getNextPage(), etc, like in Symfony for those knowing, instead of relying on a getPaginationInfo() method. Future improvements will also include more view helper magic.

Also, I came up with a small new Riskle_Pattern namespace which I use to implement commonly used patterns, such as the Proxy Pattern. I'm not yet sure of the pertinence of this thing, so any comments are yet again very much appreciated on this topic :-)

Gimme the cube !

Ce matin, après les affres d'un réveil laborieux et d'un petit-déjeuner agréable au starbuck, j'ai eu le plaisir de faire profiter à mes yeux de pas loin de trois heures d'extravagances à l'américaine sur fond d\'Autobots et de Decepticons. Vous l'aurez compris, je parle bien évidemment du dernier né des studios hollywoodiens, le blockbuster qui concurrence Die Hard 4, la réminiscence de notre plus tendre jeunesse, je parle de Transformers.

Que dire ? J'avais oublié la teneur exacte du background de cette série, et franchement, même si c'en est touchant de naïveté, le prétexte n'est pas pire que celui de pas mal des bons films d'actions sortis ces derniers temps (je pense là encore à Die Hard, mais aussi à Spiderman (attention, je parle de la base du scénario du/des film(s), pas du background) par exemple). En gros donc, le scénario est bidon, ne nous leurrons pas, mais franchement, si on va voir Transformers: le film pour son scénario, c'est qu'on à rien compris. La débauche d'effets spéciaux est tellement ahurissante qu'il serait dommage d'en rater une miette à cause d'un scénario qu'on s'efforcerait de suivre. Dès le début du film on plonge en plein coeur du sujet, avec une entrée en matière plus que remarquable, suivie peu après d'une scène qui restera longtemps gravée dans ma mémoire cinématographique je pense (je fais allusion à la bataille contre le scorpion) de part son caractère absolument hum... comment dire ? mes instincts de petit garçon mâle jouant au Gi Joe se sont subitement réveillés dirons nous :-)

Le reste du film se déroule sans surprise, les scènes d'actions s'enchainent et ne se ressemblent pas, entrecoupées de fragments d'intrigues pour se reposer un peu les mirettes. Bref, bien que le film tire un peu en longueur sur la fin, vous aurez compris que je suis totalement conquis par cette production et que je la recommande à tout le monde modulo deux conditions: 1) le voir au cinéma (ça en jette mieux je pense) et 2) avoir bien ciblé ce qu'on va voir (pas trop dur après le court exposé que je viens de vous faire).

Le tourisme expérimental

Vu que je me fais un peu chier en ce moment, je pense de plus en plus a partir un peu à l'aventure, voyager, toussa. En farfouillant un peu sur le net, j'ai découvert le tourisme expérimental qui propose des règles d'organisation de voyage souvent rigolotes, et toujours originales. Je ne pouvais donc décemment pas ne pas vous faire partager cette découverte qui va conditionner je pense une bonne partie de mes prochaines vacances a venir.

D'ailleurs, tant que j'y suis, je cherche un ou des compères susceptibles de m'accompagner dans des expéditions de plus ou moins une semaine a faible ou moyen budget et pas trop organisées dans des pays comme la suède, le royaume uni (angleterre / écosse / irlande), la hollande, le danemark, et généralement les pays scandinaves et anglo-saxons. Partir avec quelqu'un(s) que je ne connais pas ou peu fait parti du trip (jeu de mot ahah), donc n'hésitez pas à me contacter (à geoffrey+trip@zubrowka.org) si ça vous tente.

- page 2 of 36 -