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

CAT | Doctrine

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:

·

Je souhaitais utiliser la méthode copy de Doctrine_Record pour dupliquer un objet et les objets auxquels il est associé.
Pour cela il suffit de placer le paramètre $deep de la méthode copy à true, du moins c’est ce que je pensais.
Pour que cela fonctionne il faut charger au préalable les relations qui nous intéressent. (C’est très bien expliqué dans cet article http://david-gueye.fr/2010/02/02/dupliquer-ou-cloner-un-objet-doctrine-record/).

Voici un petit exemple :

  $groupe = Doctrine_Core::getTable("Groupe")->find(1);
  $groupe->loadReference("Utilisateurs");
  $copieGroupe = $groupe->copy(true);
  $copieGroupe->save();

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:

· ·

Theme Design by devolux.nh2.me