Blog d'un développeur multi-support

[DIM] pour les intimes :)

Bonjour,

Je travaille sur plus de 8 heures par jour notamment sur du 1.4 (bouhouhou) mais aussi en me basant sur apostrophe Now (re bouhouhou) du coup j’aurais des milliers de trucs à raconter dessus notamment qu’apostrophe now c’est pas bien (très constructif n’est ce pas ?) mais si vous voulez de la lecture un peu plus constructive, je vous conseille plutot d’aller sur http://www.elao.org :)

Je n’ai malheureusement pas trop le temps de progresser sur Symfony 2, je m’arrête en général à faire un bundle avec une entité ou 2 puis reprend mon chemin de croix avec apostrophe mais sinon y a des articles sympa à lire sur http://benjamin.leveque.me quand Benji poste un peu.

Aucun tag pour cet article.

Symfony & Doctrine & schema.yml

J’espère que vous utilisé Doctrine car ce mini article pourrait vous plaire ! Quand vous débutez un projet, la partie conception BDD et création du fichier yml prennent du temps et on aimerait pouvoir faire tout d’un coup.

Personnellement je fais ma conception sur Workbench puis je repart « from scratch » pour faire mon (mes) fichier(s) yml. (Oui oui on peut en avoir plusieurs de yml :p).

Quand j’étais sur Propel J’avais perdu quelque cheveux quand j’avais essayé l’autre méthode (cad de générer le fichier SQL, l’insérer en base, et laisser faire pour du reverse engineirng). Le souci du reverse c’est que ça produisait trop de code inutile (sur les foreign key par exemple) et au final repasser derrière pour arranger le model m’avait fait perdre pas mal de temps.

Hors ce soir j’ai trouvé, je ne sais comment, un plugin pour Workbench pour écrire le fichier yml directement à partir de celui ci, adieu les étapes « insertion bdd, reverse ». Et en plus sur les (mini) tests que j’ai fait tout à l’air propre, les conventions doctrines sont respectés, tout est bien indiqué. Il suffit de suivre la marche à suivre suivante : http://code.google.com/p/mysql-workbench-doctrine-plugin/wiki/WorkbenchPreparationForDoctrinePlugin

Bref, en un mot c’est bon plugin Workbench bien utile :p

Tags : , ,

Symfony 1.2, behavior doctrine en actions

J’ai (re)découvert un truc vraiment sympathique au boulot c’est le système de behavior doctrine intégré à .

Hein ? Mais à quoi ça sert ?

Ce que j’en retiens c’est que cela peut permettre d’automatiser certaines actions (répétitives) à l’enregistrement en base, et donc d’enrichir son modèle et deux coup de cuillère à pot.

Prenons un exemple, vous devez faire un site basé sur la créations de contenus par vos utilisateurs. Ils peuvent écrire des billets, commenter, s’envoyer des messages privés, gérer un annuaire .. bref un site où l’on doit quasiment tout relié à un utilisateur. Chaques tables auraient donc au moins un « user_id » comme clée étrangère ce qui implique dans vos actions d’associer l’utilisateur courant à l’objet pour le sauvegarder .. et ce pour chaque table … lourd non ?

Hé bien grâce aux behaviors vous pouvez sortir ce comportement générique dans des classes et avec seulement de la configuration au niveau de votre schéma, vous pouvez associer ce comportement à n’importe quel table. L’exemple que j’ai pris est tiré du behavior « Signable » du plugin sfDoctrineActAsSignablePlugin.

Configuration

1
2
3
4
5
6
7
8
9
Item:
  actAs:
    Signable:
  columns:
    id:
      type:             integer
      primary:          true
      autoincrement:    true
    champ1:             string(255

Comment ça marche ?

Donc si on résume, il faut dire à Doctrineque l’on va rajouter des colonnes .. et que l’on veut être prévénu lors de l’insertion en base pour associé nos actions. Donc avec seulement 2 classes, une de définition et une d’écoute, on peut s’en sortir et crée notre behavior.

Lors de la configuration, en rajoutant « actAs : Signable », Doctrine va chercher une classe de définition qui ira  étendre une classe Doctrine_Template. Par convention il ira chercher une classe nommé Doctrine_Template_Signable. Le rôle de cette classe est de déclarer ses colonnes et de rajouter une écoute, un listener, vers l’autre classe d’actions.

Pour mon exemple, je vais volontairement raccourcir les classes du sfDoctrineActAsSignablePlugin et prendre pour acquis que vos utilisateurs sont gérés via sfGuardDoctrinePlugin.

Doctrine_Template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Doctrine_Template_Signable extends Doctrine_Template {
 
  // Définitions des relations
  public function setUp() {
  // Bim rajoute une clée étrangère sur sfGuard
  $this->hasOne('sfGuardUser as Author', array(
            'local' => 'created_by',
            'foreign' => 'id'
            )
            );
  }
 
 public function setTableDefinition() {
 
  // Bim une colonne en plus
  $this->hasColumn('created_by', 'integer', 4, array(
          'type' => 'integer',
          'length' => '4',
     ));
 
  // Lien avec notre 2eme classe .. on passe le nom de la colonnette rajouté
  $this->addListener(new Doctrine_Template_Listener_Signable('created_by));
  }
}

Là pour l’exemple aucune configuration au niveau du schéma n’est possible mais c’est facile à rajouter via d’un tableau d’options et le constructeur suivant :

1
2
3
  public function __construct(array $options = array()) {
    $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
  }

Doctrine_Template_Listener

Nous avons vu que notre Template rajoute un listener vers notre 2e classe en lui passant la colonne à surveiller (dans la vrai vie, un tableau d’options ..). Le rôle de notre listener de pouvoir agir avant/après l’insertion/édition d’un objet .. facile :

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
37
38
39
class Doctrine_Template_Listener_Signable extends Doctrine_Record_Listener {
 
  protected $_colonette = "created_by";
 
  public function __construct($colonne) {
    $this->_colonette = $colonne;
  }
 
  public function preInsert(Doctrine_Event $event) {
      $createdName = $this->_colonette;
 
      // recupère l'objet appellant :
      $objet = $event->getInvoker();
 
      // Affectation de valeur
       $objet->$createdName = $this->getUserId();
  }
 
  public function getUserId() {
     // Echappe le mode cli
     if (0 != strncasecmp(PHP_SAPI, 'cli', 3)) {
       // L'user courant
       return sfContext::getInstance()->getUser()->getAttribute('user_id', null, 'sfGuardSecurityUser');
     } else {
      return null;
     }
  }
 
  public function preUpdate(Doctrine_Event $event) {
  }
 
  public function postUpdate(Doctrine_Event $event) {
  }
 
  public function postInsert(Doctrine_Event $event) {
  }
 
  // A tester : public function Delete(Doctrine_Event $event) ..
}

Vous n’avez plus qu’a rebuilder votre model et magie ça doit marcher !!

Vu que l’on a fait une relation de type One-to-many sur sfGuard vous pouvez accéder à l’utilisateur sfGuard via la propriété Author sur n’importr quel table marqué comme « Signable »

1
  echo $objet->Author->id;

Voilà .. simple au final non ? Ah vous de créez le votre, :p

Comme on dirait au boulot « Amaaziiiing !! »

Tags : , , , ,

Symfony 1.2 & Personnalisation des pages 404 & 500

Voici un petit tips sorti tout droit de jobeet pour personnaliser ses pages 404 & 500 sur Symfony 1.2. C’est bête comme chou comme truc mais faut le savoir quoi.

Page 404 :

Pour la page 404 c’est dans le fichier settings de votre application
/apps/front/config/setting.yml

Il faut tout simplement rajouter ces deux directives

1
2
3
all:
  error_404_module: home
  error_404_action: error404

Du coup quand vous aurez une erreur 404 cela sera votre page qui sera affiché, vous pourrez donc dans votre action vous ajoutez une petite ligne pour vous envoyer un mail quand y a un souci. (Le plugin nahoMail est vraiment top d’ailleurs). Du monitoring pas cher quoi.

Page 500 :

Vous croyez qu’il aurait fallu mettre

1
2
3
all:   
   error_500_module: home 
   error_500_action: error500

Et bien ça ne marche pas du tout comme ça. Pour personnaliser cette page vous devez placer un fichier « error.html. » dans le répertoire « apps/front/config/error » (crée le au besoin). Et c’est tout.

Mais du coup voilà, nous ne sommes pas dans une action .. donc cette page n’est pas inclu dans votre layout, on ne peut non plus utiliser les classes .. et oui la page d’erreur 500 est complétement statique. Adieu le monitoring pour cette page.

Si vous connaissez un moyen de customiser cette page et de pouvoir profiter du en même temps je suis preneur :p

Sur ceux, à bientôt pour de nouvelles astuces Symfony

Tags : , ,