PHP Best Practices – part 1

Dans ces Gists l’idée est d’illustrer certains paradigmes de php fonctionnel et objet à travers un Parser , l’exemple ici est basique, les classes contiennent le minimum de code possible pour pouvoir tester et surtout pratiquer, d’ailleurs c’est le principe de cette catégorie.

Late Static Bindings

La méthode create() sert comme Factory pour créer nos objets à partir de nos classes qui vont étendre la classe MainObject.

Certains de vous ont remarqué que ici j’utilise static() à la place de self(). pour ne pas dupliquer ce qui est dit dans la documentation officielle je vous envoie vers ce lien pour découvrir cette notion introduite à partir de php 5.3.0

Notre classe Parser rien de compliqué, un constructeur pour injecter le nom de notre Parser, dans un autre cas ça peut être un objet ou autres paramètres qui seront nécessaires au bon fonctionnement de notre objet.

 

Enfin notre classe Document qui étend notre fameuse classe MainObject, pour créer notre objet Document. rappelez vous de la méthode create() (Factory).

via la méthode addParser() qui prend deux paramètres un Objet de type Parser et un numérique, l’idée ici c’est qu’on peut utiliser plusieurs Parser et selon le besoin(priority) ou autre on choisi un Parser donné qui correspond à un type de Document donné.

La méthode sortParsers() trie notre tableau de Parsers selon le paramètre priority, on peut surcharger cette méthode comme on veut selon notre logique métier.

il ne reste plus qu’à tester notre code via la méthode getParser() et vérifier que notre parser de priorité 100 a été sélectionné.

vous imaginez bien que ce n’est pas fini. que peut-on faire ?

  • Avant de continuer à écrire du code, ne pensez pas que c’est le moment pour commencer à écrire des tests unitaire.
  • Ajouter plus de code métier pour rendre le Parser fonctionnel
  • Autres

le but n’étant pas d’écrire une librairie ni de réinventer la roue ou de vous donner des leçons de programmation mais plutôt de partager avec vous un peu de mon WORKFLOW de développeur apprenti et de vous montrer comment je tente d’améliorer mon style de programmation via ce genre d’exercice.

Fork me on GitHub

SOLID (principes )

Avant d’écrire une entrée sur les motifs de conception (design pattern), j’ai trouvé primordial de commencer par un article autour des 5 principes de la programmation orienté objet.

Les principes SOLID c’est quoi ?

les 5 principes forment une série de bonnes pratiques de développement orientée objet, chaque lettre du mot S.O.L.I.D est à la tête de l’un de ces 5 principes :

  • Single Responsibility Principle
  • Open/Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

Single Responsibility Principle ?

Une classe doit remplir un rôle précis, une responsabilité unique, le développeur doit faire de sorte qu’un objet à une seule responsabilité et déléguer toutes autres responsabilités à d’autres objets.

Certains puriste étendent l’utilisation de ce principe au niveau des méthodes même. selon Steve McConnell dans son livre Code Complete « The goal is to have each routine do one thing well and not do anythingelse. ». ce qui veut dire clairement qu’une méthode ou une fonction ou un routine (loop ou autres) doit faire une seule chose à la fois et le faire bien. une pratique qui semble être facile à appliquer néanmoins reste difficile à mettre en oeuvre dans la vraie vie.

Article en cours de réalisation …

 

 

Passer proprement une variable Json à vos vues twig en évitant l’échappement

1
2
3
4
return $this->render(
                         $this->twigFile, array(
                        'data' => $data /* Json DATA */
            ));

Dans ce code, je passe à la vue une donnée data de type Json. Une fois que la variable data est utilisée dans la vue, le souci rencontré est que le Json perd sa validité à cause de l’échappement automatique géré par Twig.
Voici le code et son résultat avant:

1
  var data = {{data}};
1
var data = [{"label":"Orgueil","data":11.111111111111},{"label":"Argent","data":55.555555555556},{"label":"Securite","data":11.111111111111},{"label":"Nouveaute","data":11.111111111111},{"label":"Confort","data":11.111111111111}];

Voici le code et son résultat après:

1
2
3
{% autoescape false %}
  var data = {{data}};
{% endautoescape %}
1
var data = [{"label":"Orgueil","data":11.111111111111},{"label":"Argent","data":55.555555555556},{"label":"Securite","data":11.111111111111},{"label":"Nouveaute","data":11.111111111111},{"label":"Confort","data":11.111111111111}];

Comme vous l’avez compris, la solution que j’ai trouvée après une heure de blocage ;) c’était de désactiver l’échappement automatique via {% autoescape false %}.

Optimiser votre site symfony2 pour le référencement

Comme vous le savez sans référencement votre site web apparaîtra après ceux de vos concurrents.
Toujours dans une optique d’écrire un code modulaire et réutilisable et surtout maintenable j’utilise les variables globales Twig, l’une des possibilités que symfony2 à offertes pour pouvoir alimenter dynamiquement les fameuses balises :

1
2
3
<meta name="description" content="Free Web tutorials"/>
<meta name="keywords" content="HTML,CSS,XML,JavaScript"/>
<title>Titre de la page</title>

voici comment j’ai procédé

Définir nos variables globales Twig

je définis mes variables globales Twig dans une classe config, cette classe sert à stocker quelques paramètres de configuration tels que le mail ou autres.
vous pouvez procéder autrement en stockant ces variables directement dans vos contrôleurs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php

namespace ProjectName\Utils;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


/**
 * Description of Config
 *
 * @author abdel  lsroudi@gmail.com
 */

class Config {

    static $description = NULL;
    static $title = NULL;

    static function setDescription($description) {
        self::$description = $description;
    }

    static function getDescription() {
        return self::$description;
    }

    static function setTitle($title) {
        self::$title = $title;
    }

    static function getTtile() {
        return self::$title;
    }

}

Récupérer la totalité de vos données envoyées en POST

imaginant que vous avez besoin d’envoyer plusieurs variables en POST sans passer par un formulaire, un exemple est mieux que des milliers de mots :

1
2
3
4
5
6
7
8
9
10
11
$.ajax({
type: 'POST',
dataType: 'json',
data: content,
url: url,
success: function(msg) {
if (msg.error === true) {
alert(msg.message);
}
}
});

dans cet exemple j’envois des variables via ajax à un contrôleur donné (url). pour récupérer l’intégralité de nos variables envoyées en POST la solution que j’ai trouvée est illustrée dans ce morceau de code :

1
$this->get('request')->request->all();

C’est aussi simple que ça. L’astuce est d’ailleurs valable pour GET que pour POST.

Alléger vos contrôleurs en gérant vos entités via le service Container

Un service est un objet utilisé de façon global dans votre application, le fait d’utiliser les services pour gérer vos entités vous permet :

  • de tendre au maximum vers une architecture MVC .
  • d’avoir des contrôleurs lisible et facile à maintenir.

1 – Créer votre service

1
2
3
4
5
6
7
8
9
10
11
<!-- src/Lsroudi/TestBundle/Ressources/services.xml -->

<parameters>
<parameter key="article.manager.class">Lsroudi\TestBundle\ManagerEntity\ArticleManager</parameter>
</parameters>
<services>
<service id="article.manager" class="%article.manager.class%">
<argument type="service" id="doctrine.orm.entity_manager"></argument>
</service>

</services>