Symfony2 beta1 – Notes

Maintenant que Symfony 2 est disponible en beta 1, je n’ai pas pu résister, il fallait que je fasse quelques tests.
J’ai joué avec Doctrine2 ORM, les formulaires, les formats (_format json ou html), la gestions des erreurs (404, 500). J’ai aussi utilisé backbone.js (YESS!!! Me like!!!) et Aloha Editor, peut-être que j’En parlerai un jour…

La seule chose qui n’a pas fonctionnée (et il m’a fallu moins d’une minute pour trouver la solutions – merci Google!): la version courte du tag Twig « trans » n’est plus supportée.
Dans tous les cas, il faut garder un oeil sur la liste des updates qui brise la compatibilité: https://github.com/symfony/symfony/blob/master/UPDATE.md
Wow!

Notes intéressantes

Autoload et Bundle Registration

Plus de magie: il faut déclarer toutes les librairies que vous utiliser dans autoload.php. En espérant que la librairie que vous voulez utiliser utilise la convention PSR-0 ou PEAR (qui voudrait inclure une librairie non-PSR-0 anyway ;)).

En fait, j’aime ça: on sait ce qui est utilisé dans le projet.

AdminBundle

Ça fait 2 fois que j’essaie d’installer ce Bundle (remplace l’admin-generator de symfony1), mais encore une fois sans succès… En espérant que maintenant que Symfony 2 est en beta, les développeurs vont updater ce Bundle (oui, je sais, j’aurais pu essayer de le fixer, au moins un peu… Pas le temps!)

Doctrine 2

Toute en douceur, même si je n’ai pas fait des choses intensives (2 tables simples simples simples…). J’ai aimé le fait que la classe du modèle soit uniquement responsable de ce qu’elle doit être responsable (au revoir active record, bonjour Data Mapper).

Par contre, les behaviours de Doctrine 2 étaient vraiment pratique. Même si il y a quelques plugins qui existent (pas eu le temps de les tester, comme ça), il va falloir attendre les traits (php 5.4?) pour avoir quelque chose de facile à utiliser. Ca va nous forcer à monter des solides hiérarchies de classes probablement (une bonne chose), ou à utiliser les events…

Ah, aussi, l’article sur les fixtures Doctrine dans le cookbook fonctionne bien. Du php pur, pas de yaml… Ok avec ça, sauf pour les gens de QA… Donc ca va être su deéveloppeur de se monter quelque chose… ou le Bundle pour les fixtures va être améliorer (mais problème de naming convention: avec les setters et getters des modèles vs les attributs  qui devraient normalement être private ou au moins protected si vous avez du « coeur », quoique le Form Component demande de suivre des « naming convention » – lorsqu’on passe un objet à un formulaire…).

Ajout par rapport à Doctrine (2011-05-07):

Après quelques tests un peu plus poussés (mais pas trop…), je me suis demandé s’il y  avait un mécanisme similaire aux classes XxxxTable.class.php de Doctrine 1.2. Et oui!! Cela existe heureusement, et cela s’appelle un Repository. Merci à Richard McIntyre pour son article. Voir aussi la documentation Doctrine officielle correspondante (un peu caché et un peu court, non?).

error template

– les templates 404 et 500 supporte les templates Twig (symfony 1 offrait la possibilité d’avoir une page 500 mais elle n’était pas prise en charge par le framework (ce qui se comprend bien… ) et peuvent hériter d’un autre template. Mais attention: trop de logique et de code peut générer une autre erreur. Et là, vous n’obtiendrai qu’une page toute blanche…

– c’est le même template (error.html.twig pour la version html) qui est utilisé pour les 404 et 500 – c’est au développeur de mettre en place une logique « switch » sur le status_code s’il veut avoir différentes pages 404 et 500. Mais peut-être qu’il y a une autre manière de gérer la page 404 dans le routing, à la Sinatra par exemple? Histoire à suivre… Update (probablement disponible en beta2): C’est maintenant possible: Il suffit d’avoir un template errorXXX.html.twig par exemple, ou XXX est le status code http (404, 500, 403…). Si ce template n’existe pas, alors error.html.twig sera utilisé.

« app.yml is gone »

Je n’ai pas trouvé de recommendation dans le « book » pour conserver les settings et paramètres d’une application, par environnement. J’imagine que « import » dans config.yml et le Yaml component permettent de faire ça très facilement.

Dans le même ordre d’idée, je n’ai pas trouvé de détails sur config.yml dans le profiler…

Conclusion

Bon, en un mot, j’ai bien hâte de l’utiliser sur un vrai projet! Je vous en reparlerai à ce moment-là… Histoire à suivre donc…

Symfony 2 et AsseticBundle – tips

Je suis vraiment impressionné par Assetic, la librairie PHP écrite par Kris Wallsmith.

Elle permet pour tout projet PHP de gérer les « assets » javascript et css, en utilisant des techniques modernes tel que: less, sass, coffeescript…

La documentation étant encore un peu sommaire, notamment pour l’Intégration avec Symfony 2, voici quelques notes afin de ne pas oublier comment faire (pour la prochaine fois hein…)

Less

Config.yml

# Assetic Configuration
assetic:
    debug:          %kernel.debug%
    use_controller: %kernel.debug%
    read_from:      %kernel.root_dir%/../web/bundles
    write_to:       %kernel.root_dir%/../web/assets
    filters:
        cssrewrite: ~
        less: ~
#...
parameters:
  assetic.node.bin: /usr/local/bin/node
  #ca m'a pris longtemps pour trouver la config
  #  pour loader les packages npm par exemple
  assetic.node.paths:
    - /usr/local/lib/node

Puis dans routing_dev.yml (nécessaire là où use_controller est true), j’ai ajouté la route:

_assetic:
    resource: .
    type: assetic

Puis il suffit d’inclure dans le template (Twig):

{% stylesheets
		filter='less'
		output='css/all.css'
		'@SaadTestBundle/Resources/public/less/main.less'
%}
<link href="{{asset_url}}" rel="stylesheet"/>
{% endstylesheets %}

Cela produira:

<link href="/app_dev.php/css/all_main1.css" rel="stylesheet"/> 

Node.js, express.js et autres découvertes

J’ai « commis » un mini-projet de test, afin de découvrir node.js et plus spécifiquement express (ou express.js), un mico-framework qui s’appuie sur node.js.

J’en ai profité pour jeter un coup d’oeil à mongoDB, et un ORM node.js de mongoDB qui s’appelle mongoose.

Voici le lien github.

J’aime

  • tout est évènement, rien n’est bloquant. Le language Javascript v8 est ultra-rapide, donc si on ajoute le fait que rien n’est bloquant, alors wooooww!!
  • Un seul language client-side et server-side, et des librairies qui parfois fonctionnent des 2 côtés (le même fichier!!!).

J’aime un peu moins

  • un léger bémol sur la documentation de express: la doc est là, mais j’ai du googler de nombreuses chose, ou pire, aller voir le source (non, je sais il n’y a rien de grave, au contraire…)
  • C’est une technologie (encore trop?) récente: les numéros de versions (de node.js, expess, …) évoluent rapidement, et les différents packages ne sont pas forcément compatible.
  • (lié au point précédent) Il y a des milliers de packages « qui font la même chose »: impossible de compter combien de « template engines » existent, ou de client mySQL (taper « nodejs mysql » dans google pour voir…)
  • Ça m’a fait réalisé que je ne maitrise pas toutes les subtilités du Javascript. Mais là, je ne peux blamer que moi-même.

J’aime pas

Rien, j’aime tout.

Pour conclure

J’adore! J’aime! … mais j’attends un peu encore pour l’utiliser en production. Quoique, pour utiliser les webSockets et Socket.io: trop fort!

Il est temps de se mettre sérieusement, très sérieusement au Javscript.

Très prometteur…

Update (2010-03-05)

mongodb

Attention, dans mon code, si le serveur mongodb (c’est à dire « mongob ») n’est pas démarré avant de démarrer le serveur node, aucune requête ne sera servie (loade à l’infini)… Vous êtes prévenus maintenant…

Lesscss

Pour ajouter le support de lesscss, il suffit d’ajouter la ligne suivante dans app.configure():

app.configure(function(){
    //...
    //activate less compiler
    app.use(express.compiler({ src: pub, enable: ['less'] }));
    //...
});

Ensuite, il vous suffit de mettre dans public/ vos fichiers less (exemple: main.less). Dans vos templates, il faut continuer à mettre des fichiers css (exemple: main.css), express (ou node) va les compiler automatiquement et créer une version statique css dans public/.

Par contre, il faut 2 requêtes avant que le fichier less soit compilé en css: la première retourne un 404, la 2ème est ok. Donc attention lors du développement.

Capitales – mini-projet

Toujours afin de tester de nouvelles technologies et de m’exercer avec le framework Symfony2 et les librairies javascript pour mobile, j’ai décidé de faire un mini-projet qui liste les pays du monde et leurs capitales. Le résultat final se trouve ici.

Après avoir chercher une base de données qui comprend les pays et leurs capitales, j’ai finalement décider d’utiliser Wikipedia et parser le html. Je voulais pouvoir refaire l’import si nécessaire. Donc il me fallait le faire programmatiquement, en utilisant PHP.

Notes

  • Même si la table HTML de Wikipedia semble uniforme, il m’a fallu traiter les différences de DOM
  • Utilisation de SplFileObject au lieu de fread: Utiliser les classes de la Standard PHP Librairy, c’est louable. Mais comment lire le fichier d' »une shot », l’équivalent de:
    contents = fread($handle, filesize($filename));
  • J’ai essayé d’utiliser la classe Crawler de Symfony2, normelement utilisée pour les tests fonctionnelles: cette classes n’est pas fait pour parser du XML, même si j’ai bien aimé la classe qui convertit un selecteur css en selecteur XPath.
  • En utilisant DOMDocument: mmm, trop « verbose », pas facile de parcourir le document je trouve, les attributs nodeValue et textContent retourne le contenu « strippé », donc il faut utiliser la méthode saveXML() uniquement utilisable depuis DOMDocument, donc si on a un DOMNode, il faut faire un
    $myDOMNode->ownerDocumnent->saveXML($myDOMNode);

    Pas très élégant, non?

  • Donc retour à SimpleXML, mais la méthode XPath de SimpleXML semble très limité (peut-être à cause des namespace ou du fait que ce soit du html?). Donc l’essentiel est en SimpleXML, mais j’ai du utilisé la méthode DocDocument::getElementById() et convertir en SimpleXMLElement en utilisant la fonction simplexml_import_dom.
  • Plus d’info sur les limitations que j’ai rencontré avec la méthode SimpleXMLElement::xpath() (mais c’est peut-être juste moi):
    • incapable de loader le html… Peut-être est-ce à cause des namespaces?
    • incapable d’utiliser les selector XPath de type attribut:
      root/node[@id='my-id']
  • Quelques problème d’encoding avec DomDocument: il a fallu qu’en loadant le string XML, j’ajoute le « tag » xml  
    $domDoc->loadHTML('<?xml encoding="UTF-8">' . $content);

Aussi, j’ai toujours une des problèmes de performance avec jQuery, lorsque le DOM est trop important…

jQuery mobile, Symfony2, Doctrine 2 et autres tests…

Bonne année!!

Et oui, après de longs mois de silence, les bonnes résolutions de 2011: comme je suis curieux, j’ai voulu faire quelques tests avec Symfony2 et jQuery mobile.

Et comme ma blonde a une « passion » pour les départements français (donner un numéro de département, et deviner le nom du département – difficile à comprendre quand on n’est pas de France j’imagine), j’ai fait un mini-site qui liste les départements français (liste de tous les départements ou par région).

Testez-le ici.

Mise à jour (2011-01-09)

J’ai aussi réaliser quelque chose de similaire pour les capitales des pays. Voir ici. Cela m’a permis de jouer avec les classes php SimpleXMLElement, DOMDocument et la famille PHP DOM, mais aucune ne m’a complètement convaincue. Voir ici pour des commentaires additionnels.

J’ai utilisé…

  • le framework Symfony2 PR4: j’ai utilisé le fichier tarball pour être rapidement « efficace ». Simple à installer, mais je pense qu’il manque quelques commandes Symfony pour générer des Bundles par exemple (j’ai pas trop chercher, peut-être que ça existe)
  • jQuery mobile 1.0 ALPHA 2:
    • les listView: encore quelques améliorations sont nécessaire (notamment pour les count bubbles des nested list), mais ça promet,
    • les liens (remplacés en call ajax) et le back automatique: cool, mais parfois pas très fluide et très lent, et je pense que c’est encore lent si le lien est dans une liste de 100+ items (DOM trop complexe)
    • parfois lorsque la page se loade sur le iphone, le css ne semble pas appliqué. Le problème se résout lorsqu’on raffraichit la page: problème de latence réseau, problème de webKit, problème de DOM trop long, ou de performance iPhone? Je ne sais pas, mais problème il y a… Pour répliquer à tout coup le problème, allez sur votre iphone à http://departements.fruitsoftware.com/index2.html. Dans la dernière version (http://departements.fruitsoftware.com), j’ai séparé les listes imbriquées en 2 pages: chaque nested list est dans une page séparée.
    • d’une manière générale, il reste encore (un peu (?), beaucoup (?)) de travail à faire. Mais très prometteur et utilisable si on accepte les limitations actuels.
  • une base de donnée mySQL et l’ORM Doctrine 2 avec les docBlock annotations (Doctrine 2: excellent!!). Sauf que je n’ai pas trouvé de façon d’initialiser la connexion à UTF8 via la configuration de Symfony2. Pour m’en sortir, j’ai créé une petite méthode dans l’unique controleur de l’application (probablement une meilleure manière de faire, notamment via les postConnect events de la DBAL de Doctine):
        public function fixUtf8() {
            $conn = $this->get('database_connection');
            $statement = $conn->prepare('SET NAMES \'utf8\';');
            $statement->execute();
        }
    
  • Twig pour les views de Symfony2: je n’ai pas trouvé de limitations pour l’instant, il faut s’habituer je pense à la syntaxe (et à l’IDE qui ne « highlight » pas et ne formate pas correctement – tabs…)

Reste à tester…

  • le HTTP cache de Symfony2: je trouve le principe excellent, je me garde juste ça pour plus tard…
  • comment jQuery mobile se comporte avec Google Analytics, notamment avec le remplacement automatique des liens par des calls Ajax [EDIT] J’ai trouvé ce lien qui semble répondre à cette question: http://www.jongales.com/blog/2011/01/10/google-analytics-and-jquery-mobile/
  • les formulaire jQuery mobile et leur intégration avec Symfony2
  • les formulaires Symfony2 en général
  • PhoneGap (lire cet article)

Quelques remarques

  • s’il vous plait, pas de commentaires sur les régions qui ne sont pas des régions, …. J’ai pris mes données de wikipédia, alors, bon, hein…
  • Le framework Symfony2 semble avoir gagner en robustesse par rapport à la version 1, mais aussi plus exigeant: code plus long à taper. Rien de bien grave là, surtout si on gagne en clarté, performance, fonctionalité, beauté (oui oui, Symfony2, c’est beau!!), règles de l’art…
  • Pour tester: Chrome et firefox l’affaire (en redimensionnant la fenêtre), mais j’ai aussi utilisé le iPhone Simulator qui vient avec xcode (sur Mac uniquement)
  • j’ai utilisé Apache et mySQL installé via macPorts: fini pour moi MAMP, j’ai plus de contrôle avec MacPorts, notamment pour installer des extensions php.

eZ Publish, Cache and Performance

eZ Publish is not the fastest CMS I’ve seen. It is flexible (you can define your own classes (type of content), and the fields that define your class. But it seems like « more flexible != fast ». Just take a look at the number of queries on a page that has object relations fields, and you will understand why: it can reach more than 100 queries on a page!

If your eZ Publish is slow (actually even if it’s not slow!!), you should activate eZ Publish caching mechanism. I was looking for some info about eZ Publish, and here is what I found.

Links and notes about Ez Publish caching

  1. http://share.ez.no/articles/ez-publish/ez-publish-performance-optimization-part-3-of-3-practical-cache-and-template-solutions/%28page%29/2
    • This article explains the different cache mechanism (template cache, view cache, preview cache), and the {cache-block} template function
  2. http://ez.no/doc/ez_publish/technical_manual/4_x/features/view_caching/configuring_the_view_cache
    • It explains how to deactivate the view cache on specific pages, by adding the following code at the beginning of the related template:
      {set-block scope=global variable=cache_ttl}0{/set-block}
    • This tip is really useful when you have user session related pages, like a profile page, a cart page…

deactivate eZ Publish cache on ou development environment

These are the settings I usually add to the frontend siteaccesses to deactivate the cache mechanism. Remember to remov them on your staging/test and live environments.

[ContentSettings]
#...(other settings in that section)
#dev only
ViewCaching=disabled
#dev only
PreViewCache=disabled

[TemplateSettings]
#... (other settings in that section)
#dev only
TemplateCache=enabled

[OverrideSettings]
#... (other settings in that section)
#dev only
Cache=disabled

Oh, and also deactivate template caching (in TemplateSettings), your integrators will hate you if you don’t: they would have to clear eZ Publish cache everytime they change a template – using the following command:

php bin/php/ezcache --clear-all --purge

Notes: Apache, MAMP

Because I don’t want to loose time with those things the next time I setup MAMP, I decided to write it down. I hope it will help you too!

mod_rewrite doesn’t work?

Make sure mod_rewrite is enabled:

LoadModule rewrite_module modules/mod_rewrite.so

Check you httpd.conf (or apache.conf) settings, specially the following setting: AllowOverride

AllowOverride All

You can put inside a Directory block, in a virtual host for example:

<VirtualHost *:8888>
ServerName local.mysite.com
DocumentRoot /path/to/web/root
<Directory "/path/to/web/root">
AllowOverride All
</Directory>
#...

This is valid for any Apache bundle (MAMP, WAMP, XAMP, or Apache itself)

MAMP mySQL – connection problem?

If you’re having trouble connecting to MySQL (using PDO for example), try the following tip:

edit startMySQL.sh in /Applications/MAMP/bin and add the following line at the end:

ln -s /Applications/MAMP/tmp/mysql/mysql.sock /tmp/mysql.sock &

quelques notes sur le développement d’applications iPhone

Voici quelques notes prises lors de mon auto-apprentissage sur le développement d’applications iphone.

En effet, étant du genre « c’est quoi déjà? », j’ai regroupé quelques informations dans cet article afin de pouvoir centraliser certaines informations que j’ai trouvées pertinentes… En espérant que cela puisse vous aider aussi.

L’essentiel des informations étant en anglais, j’ai donc laissé l’information dans la langue originale.

Some Objective-C stuff

  • When declaring a method, « -«  is fr instance methods, « + » is for Class methods.
  • If you message nil, it returns zero.
  • with NSString inValue returns 0 if it’s not an integer. If it starts with an integer but followed by « crap » (9873ikdi) it will return the integer (9873). Same thing with floatValue, doubleValue…
  • If you overwite the -(id) init method, always return the result of [super init].
  • when release method is called, the retain count is decreased, if it’s zero then the dealloc s called
  • never call -(void)dealloc directly, except if you overwite the -(void)dealloc method, you should call [super dealloc].
  • if your method returns an object that you created in the method:
    • use the [newObject autorelease] or
    • prefix your method name with « alloc », « copy » or « new » to inform the developer that he will have to release it
  • balance the number of retain and release
  • If you use autorelease, the object will be put in the autorelease pull. At the end of the event handling cycle,  the autorelease pull will call the release method on the objects in the pull, and if the retain count hits 0, the object is deallocated)
  • « attribute.property = value » will call the setter, but « property = value » will access the property directly
  • you can overwite -(void) awakeFromNib method in your AppDelegate to initialize values

From « iPhone Application Programming Guide« 

  • When your application quits, you should save out information about your application’s current state in addition to any unsaved data. At launch time, you should look for this state information and use it to restore your application to the state it was in when it was last used.
applicationDidFinishLaunching: Use this method to restore the application to the state it was in during the previous session. You can also use this method to perform any custom initialization to your application data structures and user interface.
applicationWillTerminate: Use this method to save any unsaved data or key application state to disk. You can also use this method to perform additional cleanup operations, such as deleting temporary files.
  • All applications should respond to this notification and do their part to help relieve the memory pressure. For information on how to handle such notifications in your application, see “Observing Low-Memory Warnings.”
  • Icon.png is mandatory
  • an application can be interrupted by an incoming phone call, an SMS message, a calendar alert, or by the user pressing the Sleep button on a device.(…) If the user decides to take a call or reply to an SMS message, however, the system does proceed to terminate your application.
  • A keychain is a secure, encrypted container for passwords and other secrets. The keychain data for an application is stored outside of the application sandbox.
  • Avoid writing cache files to disk. The only exception to this rule is when your application quits and you need to write state information that can be used to put your application back into the same state when it is next launched.
  • Unlike most desktop applications, where the user manually chooses when to save files to disk, your application should save changes automatically at key points in your workflow. Exactly when you save data is up to you, but there are two potential options. Either you can save each change immediately as the user makes it, or you can batch changes on the same page together and save them when the page is dismissed, a new page is displayed, or the application quits. Under no circumstances should you let the user navigate to a new page of content without saving the data on the previous page.
  • If your application accesses the network using the Wi-Fi radios, you must notify the system of that fact by including the UIRequiresPersistentWiFi key in the application’s Info.plist file. The inclusion of this key lets the system know that it should display the network selection panel if it detects any active Wi-Fi hot spots. It also lets the system know that it should not attempt to shut down the Wi-Fi hardware while your application is running.
  • UIView:

View class hierarchy

NSFetchedResultsController: A « helper » controller between TableViewController and Core Data.

  • Load data lazily
  • multiple NIBs so you don’t load everything at the same time
  • Every controllers can receive didReceiveMemoryWarning… By default, it will unload all the views that are not on screen… So ViewDidLoad can be called more than once (at te beginning and after a memory Warning when the view needs to be reloaded)

More to come from the « iPhone Human Interface Guide« …

Sources:

http://developer.apple.com/iphone/index.action

http://deimos3.apple.com/WebObjects/Core.woa/Browse/itunes.stanford.edu.3124430053.03124430055

Ma première application iphone

Première application iphone

Et oui, il faut bien commencer un jour, je viens de finir ma première application iphone…

Pas très créatif (une simple calculatrice), pas de quoi être fier (de nombreuses améliorations sont possibles, notamment cacher le clavier une fois terminé…), mais tout de même… Pour une première application pour tester et apprendre objective-C, XCode, c’est pas pire, non?

Il me reste encore beaucoup de lecture à faire, notamment le « iPhone Human Interface Guideline« …

Un souvenir, histoire de rire de moi si je fais mieux dans quelques semaines ou quelques mois…