flosy.info | Développement Web, Open source …

CAT | symfony

Le déploiement d’un projet est toujours une étape fastidieuse et parfois complexe.
Pour automatiser cela nous pouvons utiliser un outil comme Fabric qui va nous permettre de scripter notre déploiement.
J’ai découvert cet outil dans la présentation Adopt Devops philosophy on your Symfony projects de Fabrice Bernhard lors de la conférence symfony live 2011.

Fabric est un outil écrit en Python et disponible sur le site suivant : http://docs.fabfile.org/en/latest/index.html.

Installation

Il est recommandé de passer par pip pour installer Fabric. Pip n’est pas installé de base sur la Fedora. Il est cependant disponible sous forme de package.

  # yum install python-pip

Pip va nous permettre d’installer Fabric grâce à la commande suivante :

  # pip-python install fabric

Note : Dans mon cas cela n’a pas fonctionné directement. En effet Fabric a comme dépendance la bibliothèque PyCrypto qui va être compilée par pip. Il m’a fallu installer le package python-devel.

Utilisation

À titre d’exemple nous allons créer un fichier fabric qui va nous permettre de créer un projet symfony et de lui associer un dépôt GIT.

Nous créons le fichier fabfile.py dans le dossier parent du futur projet (dans mon cas /var/www/symfony2).

from fabric.api import *
 
version_symfony = 'Symfony_Standard_2.0.12.tgz'
url_symfony = 'http://symfony.com/download?v=' + version_symfony
 
def install_symfony(project_name):
  local("wget " + url_symfony)
  local("tar xzvf " + version_symfony)
  local("rm " + version_symfony)
  local("mv Symfony " + project_name)
  local("cp %s/app/config/parameters.ini %s/app/config/parameters.ini.dist " % (project_name, project_name))
 
def create_repository(project_name):
  local('touch ./%s/.gitignore' % project_name)
  ignore_file = open('./%s/.gitignore' % project_name, 'w')
  ignore_file.write("""/web/bundles/
/app/bootstrap*
/app/cache/*
/app/logs/*
/vendor/
/app/config/parameters.ini""")
  with lcd(project_name):	# Context managers lcd pour local, cd pour remote (run).
    local('git init ')
    local('git add .')
    local('git commit -m  "Initial commit"')
 
def install_vendors(project_name):
  with lcd(project_name):
    local('php bin/vendors install')
 
def install(project_name):
  install_symfony(project_name)
  create_repository(project_name)
  install_vendors(project_name)

Le fichier décompose l’installation en 3 fonctions :

install_symfony
Installe une version donnée de symfony sans les vendors.
create_repository
Gère toutes les opérations nécessaires à la création du dépôt GIT.
install_vendors
Installe les vendors.

La fonction install nous sert de facade.

Nous pouvons donc les appeler successivement ou utiliser la facade.

  $ fab install_symfony:symfabric
  $ fab create_repository:symfabric
  $ fab install_vendors:symfabric

ou

  $ fab install:symfabric

Vous noterez l’utilisation du context manager lcd qui permet de spécifier un dossier de travail pour un groupe d’instructions.
Dans le cas d’un accès distant il convient d’utiliser le context manager cd.

Connexion sur un hôte distant

Nous allons utiliser une connexion ssh par clé. Pour cela nous allons ajouter sur l’hôte distant, la clé publique dans le fichier .ssh/authorized_keys.
Attention à donner les bons droits au fichier :

  $ chmod 600 .ssh/authorized_keys

Pour l’exemple je vous renvoie vers le très bon exemple de la présentation de Fabrice Bernhard disponible sur GitHub.

Related Posts:

  • No Related Posts

No tags

À ma grande surprise après avoir lancé la commande pour désactiver mon projet le site reste actif.

$ symfony project:disable prod
>> file+     /var/www/symfony/flosy/data/frontend_prod.lck
>> enable    frontend [prod] has been DISABLED

Pour que le verrouillage d’une application soit pris en compte, il faut le paramétrer au niveau de chaque application. Éditez le fichier settings.yml de l’application et ajoutez le paramètre check_lock.

all:
  .settings:
    # Enable project locking
    check_lock:             on

Comme vous l’aurez deviné ce paramètre est par défaut à off (cf. documentation).

Related Posts:

·

Après avoir mis en place le plugin sfDoctrineGuard, je souhaitais disposer d’attributs complémentaires sur les utilisateurs.
Le plugin sfGuard pour symfony 1.0, disposait pour cela d’une classe liée Profile. Hors dans la version avec Doctrine ce n’est pas le cas.

Une première solution à ce problème aurait été d’utiliser la notion d’héritage proposée par Doctrine. Dans mon cas cela ne m’a pas paru utile car une seule classe dériverait de sfGuardUser.

La seconde solution est expliqué sur cette page http://www.symfony-project.org/gentle-introduction/1_4/en/17-Extending-Symfony dans le paragraphe Customizing the plug-in schema.
Nous allons tout simplement compléter (surcharger) le schéma de sfGuardUser (défini par dans le plugin) avec le schéma de notre projet. Ceci n’aura donc aucune influence sur le plugin en cas de mise à jour.

#Project schema,  config/doctrine/schema.yml
sfGuardUser:
  columns:
    phone:   varchar(30)
    fax:     varchar(30)
  relations:
    Companies:
      class: Company
      local: user_id
      foreign: company_id
      refClass: UserCompany

Vous noterez dans cet exemple qu’il est même possible d’ajouter de nouvelles relations.

Related Posts:

·

Pour un projet je souhaite pouvoir me connecter à 2 bases de données différentes. Voyons comment faire cela avec Doctrine.

Configuration des bases de données

Nous définissons une connexion pour chacune des bases dans le fichier /config/databases.yml.

all:
  main:
    class: sfDoctrineDatabase
    param:
      dsn: 'mysql:host=localhost;dbname=base_main'
      username: user
      password: password

  subsidiary:
    class: sfDoctrineDatabase
    param:
      dsn: 'mysql:host=localhost;dbname=base_subsidiary'
      username: user
      password: password

Définition du modèle

Nous créons ensuite notre schéma en précisant pour chaque classe du modèle la connexion à utiliser. Voici un exemple de schéma :

Utilisateur:
  connection: main
  columns:
    id:         { type: integer, primary: true, autoincrement: true }
    nom:        { type: string(255) }
    
Groupe:
  connection: subsidiary
  columns:
    id:         { type: integer, primary: true, autoincrement: true }
    nom:        { type: string(255) }

La commande de création du modèle va ajouter les tables dans leur base respective.

$ symfony doctrine:build --all

Vous noterez dans les classes de base du modèle la référence à la connexion.

1
2
3
< ?php
  // Connection Component Binding
  Doctrine_Manager::getInstance()->bindComponent('Groupe', 'subsidiary');

À partir de maintenant les données seront enregistrées dans les 2 bases de données.

Related Posts:

·

mar/11

10

Lancement du site Symfony 2

Depuis quelques jours le nouveau site dédié à Symfony 2 est en ligne. Il comporte déjà une documentation très complète sur le sujet.
Pour ceux qui l’aurait raté voici la nouvelle url où trouver le projet http://symfony.com.

Related Posts:

Je suis à la recherche d’une bibliothèque PHP qui me permette de créer des documents PDF. Commençons par une recherche des plugins PDF existants.

Une recherche dans la base de symfony remonte les plugins suivants :

  • sfTCPDFPlugin utilisé par 85 personnes
  • pmPDFKitPlugin utilisé par 2 personnes

Le choix de la bibliothèque sera conditionné par les attentes suivantes :

  1. les fonctionnalités proposées (au moins la gestion des images, des listes et des tableaux),
  2. la simplicité d’utilisation,
  3. la rapidité de mise en œuvre.

sfTCPDFPlugin

Le plugin est dans une version stable (1.6.2) et il repose sur la bibliothèque TCPDF.

Installation et configuration

Le plugin s’installe classiquement avec la commande « symfony plugin:install ».

Attention le plugin ne fournit pas TCPDF et vous devez le récupérer sur sourceforge. La version 5.9.044 est utlisée pour ce test.

La configuration est faite au travers d’un fichier pdf_config.yml à placer dans le répertoire config de l’application.

Pour effectuer rapidement un test de la bibliothèque, un module est fourni avec 2 exemples. Nous allons activer ce module pour réaliser les tests. Nous éditons pour cela le fichier settings.yml.

all:
  .settings:
    # Default modules  
    enabled_modules: [default, sfTCPDF]

Lors de mes essais quelque soit l’exemple j’obtenais une erreur fatale.

Fatal error: Maximum execution time of 30 seconds exceeded

Après quelques recherches la solution au problème tient au paramétrage de l’option « font subset » (Vous trouverez d’autres conseils d’optimisation dans le forum : http://sourceforge.net/projects/tcpdf/forums/forum/435311/topic/3785743).

Pour mettre en place la correction, après avoir instancié la classe sfTCPDF, utilisez la méthode setFontSubsetting.

<?php
  //create new PDF document (document units are set by default to millimeters)
  $pdf = new sfTCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true);
 
  $pdf->setFontSubsetting(false);
  ...
?>

Fonctionnalités

TCPDF est particulièrement complète parmi toutes les fonctionnalités disponibles voici celles qui m’ont paru utiles.

  • Gestion des entêtes et pieds de page.
  • Gestion des tableaux.
  • Transformation HTML vers PDF
  • Gestion des graphiques
  • Gestion des tables des matières
  • Gestion des images

pmPDFKitPlugin

Le plugin est en version stable (1.0.0) et il repose sur la bibliothèque wkhtmltopdf.

Installation et configuration

Le plugin s’installe classiquement avec la commande « symfony plugin:install ».

Il faut là aussi télécharger la bibliothèque tierce à cette adresse : http://code.google.com/p/wkhtmltopdf/downloads/list.

Ensuite nous activons le filtre du plugin dans le fichier filters.yml de l’application.

rendering: ~
security:  ~
 
# insert your own filters here
pm_pdfkit:
  class: pmPDFKitFilter
 
cache:     ~
execution: ~

Pour le paramétrage de l’application nous modifions la taille de la page pour qu’elle soit au format A4.

all:
  pm_pdfkit:
    page-size: A4

Enfin il faut modifier le fichier routing.yml de l’application pour prendre en compte les formats.

default_index:
  url:   /:module.:sf_format
  param: { action: index, sf_format: html }
 
default:
  url:   /:module/:action.:sf_format/*
  param: { sf_format: html }

Ceci permet de déclencher la génération PDF d’une action, à l’utilisation de du format pdf. Par exemple http://flosy.info/default/index.pdf.

Fonctionnalités

Le plugin transforme tout simplement une action en document PDF. Le plugin semble avoir un bug au niveau des CSS et des images.

Autres bibliothèques

En plus de ces 2 plugins et de leur bibliothèque respective, il sera intéressant de tester le composant Zend_Pdf du Zend Framework.

Related Posts:

· · · · ·

Symfony fournit au travers de la ligne de commande différentes opérations d’administration pour son projet. Elles utilisent les couleurs pour faciliter la lecture. Mais car il y a un mais, la configuration par défaut de la Fedora 14 ne restitue pas les couleurs.
Pour que cela fonctionne il faut installer le paquet suivant :

# yum install php-process

Related Posts:

· ·

L’une des classes de mon modèle dispose d’un attribut default. Voici un extrait du schéma qui montre l’élément en question.

Group:
  columns:
    id:        { type: integer, primary: true, autoincrement: true }
    name:      { type: string(255) }
    default:    { type: boolean }

Lors de la création du modèle l’erreur suivante apparaît :

$ symfony doctrine:build --all
...
>> doctrine  generating sql for models
>> doctrine  Generated SQL successfully for models
>> doctrine  creating tables
 
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'default TINYINT(1), PRIMARY KEY(id)) ENGINE =
INNODB' at line 1. Failing Query: "CREATE TABLE group (id BIGINT AUTO_INCREMENT, name VARCHAR(255), default 
TINYINT(1), PRIMARY KEY(id)) ENGINE = INNODB". Failing Query: CREATE TABLE group (id BIGINT AUTO_INCREMENT, 
name VARCHAR(255), default TINYINT(1), PRIMARY KEY(id)) ENGINE = INNODB

Si nous observons le script SQL produit dans data/sql/schema.sql nous trouvons :

CREATE TABLE GROUP (id BIGINT AUTO_INCREMENT, name VARCHAR(255), DEFAULT TINYINT(1), PRIMARY KEY(id)) ENGINE = INNODB;

DEFAULT est un mot clé réservé aussi pour l’utiliser il nous faut échapper le nom du champ avec des backquotes.

Un ticket sur le trac du projet symfony explique ce problème (le ticket en question).

Nous utilisons la méthode configureDoctrine de ProjectConfiguration pour paramétrer doctrine.

class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    $this->enablePlugins('sfDoctrinePlugin');
  }
 
  public function configureDoctrine(Doctrine_Manager $manager)
  {
    $manager->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, true);
  }
}

Cette fois le script SQL échappe les noms de champ.

CREATE TABLE `group` (`id` BIGINT AUTO_INCREMENT, `name` VARCHAR(255), `default` TINYINT(1), PRIMARY KEY(`id`)) ENGINE = INNODB;

Update

Dans le cas d’un nom de BDD avec un tiret, cette astuce est nécessaire (par exemple ma-bdd).

Related Posts:

· ·

Dans un formulaire de création de compte je souhaite effectuer un double contrôle sur le champ login. Pour cela il suffit d’utiliser le validateur sfValidatorAnd qui permet d’associer plusieurs validateurs à un même champ.

Voici un exemple de code :

class MyForm extends sfForm {
  /**
   * Configures the current form.
   * 
   * @return void
   * @access public
   */
   public function configure() {
     $this->setWidgets(
       array(
         "login" => new sfWidgetFormInputText(),
         "password" => new sfWidgetFormInputPassword(),
         "password_confirmation" => new sfWidgetFormInputPassword(),
       )
     );
 
     $this->setValidators(
       array(
         "login" => new sfValidatorAnd(
	   array(
	     new sfValidatorString() ,
	     new sfValidatorDoctrineUnique(
	       array(
	         "model" => "User", 
	         'column'=>'login'
	       )
	     ),
	   )
	 ),											
...
      )
   );
...
  }
}

Related Posts:

· ·

La version 1.4 de symfony avec Doctrine fournit des méthodes pour utiliser la classe DateTime dans le model.
La classe DateTime ainsi que DateTimeZone sont disponibles depuis PHP 5.2.0.
Elles permettent de fournir un support Objet pour les dates, heures et fuseaux horaires.
Attention tout de même la méthode DateTime::diff fait appel à l’objet DateInterval disponible seulement depuis la version PHP 5.3.0.

Related Posts:

· ·

Theme Design by devolux.nh2.me