mar
06
2012

par Paul

J’utilise pas mal Symfony premier du nom et je me suis dis tiens y a la v2 je vais m’y mettre.

J’attendais beaucoup et ben je suis super super déçu.
Tout me semble plus compliqué avec la v2.

Par défaut avec la v1 j’avais:

  • Tout le schema de l’application dans schema.yml
  • Les données initiales avec data/fixtures/

En quelques commandes console, j’avais une base de données crées, les données initiales chargées et les models associés créés.

Maintenant il faut que je crée (par défaut), les models à la main avec le principe de notations:

< ?php

namespace Wayr\SecurityBundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;

/**
 * Wayr\SecurityBundle\Entity\User
 *
 * @ORM\Table(name="w_users")
 * @ORM\Entity(repositoryClass="Wayr\SecurityBundle\Entity\UserRepository")
 */
class User implements AdvancedUserInterface
{

    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(name="username", type="string", length=25, unique=true)
     */
    private $username;

    /**
     * @ORM\Column(name="salt", type="string", length=40)
     */
    private $salt;

    /**
     * @ORM\Column(name="password", type="string", length=40)
     */
    private $password;

    /**
     * @ORM\Column(name="email", type="string", length=60, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(name="is_active", type="boolean")
     */
    private $isActive;

    /**
     * @ORM\ManyToMany(targetEntity="Group", inversedBy="users", cascade={"remove"})
     * @ORM\JoinTable(name="w_users_groups")
     */
    private $groups;
[...]
}

Ce qui veux dire que j'ai pas mal de fichiers à crée, à nommer et à écrire juste pour avoir un schema de base de données.

Et je ne parle même pas des données initiales ... ou avant seul un simple fixtures.yml suffisait.

sfGuardPermission:
  backend:
    name: 'backend'
    description: 'Can use backend'
sfGuardGroup:
  superAdmin:
    name: 'Super Admin'
    description: 'Dieu.'
    Permissions: [ '< ?php echo implode("','", $superAdmin); ?>']
  backendUser:
    name: 'Backend User'
    description: 'Can use backend'
    Permissions: [backend]

Maintenant il faut faire je cite:

[doctrine-fixtures]
    git=http://github.com/doctrine/data-fixtures.git

[DoctrineFixturesBundle]
    git=http://github.com/symfony/DoctrineFixturesBundle.git
    target=/bundles/Symfony/Bundle/DoctrineFixturesBundle

Update the vendor libraries:
$ php bin/vendors install

If everything worked, the doctrine-fixtures library can now be found at vendor/doctrine-fixtures.
Register the Doctrine\Common\DataFixtures namespace in app/autoload.php.

// ...
$loader->registerNamespaces(array(
    // ...
    'Doctrine\\Common\\DataFixtures' => __DIR__.'/../vendor/doctrine-fixtures/lib',
    'Doctrine\\Common' => __DIR__.'/../vendor/doctrine-common/lib',
    // ...
));

Finally, register the Bundle DoctrineFixturesBundle in app/AppKernel.php.

// ...
public function registerBundles()
{
    $bundles = array(
        // ...
        new Symfony\Bundle\DoctrineFixturesBundle\DoctrineFixturesBundle(),
        // ...
    );
    // ...
}

Doctrine2 fixtures are PHP classes where you can create objects and persist them to the database. Like all classes in Symfony2, fixtures should live inside one of your application bundles.
For a bundle located at src/Acme/HelloBundle, the fixture classes should live inside src/Acme/HelloBundle/DataFixtures/ORM or src/Acme/HelloBundle/DataFixtures/MongoDB respectively for the ORM and ODM, This tutorial assumes that you are using the ORM – but fixtures can be added just as easily if you’re using the ODM.
Imagine that you have a User class, and you’d like to load one User entry:

// src/Acme/HelloBundle/DataFixtures/ORM/LoadUserData.php
namespace Acme\HelloBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Acme\HelloBundle\Entity\User;

class LoadUserData implements FixtureInterface
{
    public function load($manager)
    {
        $userAdmin = new User();
        $userAdmin->setUsername('admin');
        $userAdmin->setPassword('test');

        $manager->persist($userAdmin);
        $manager->flush();
    }
}

In Doctrine2, fixtures are just objects where you load data by interacting with your entities as you normally do. This allows you to create the exact fixtures you need for your application.
The most serious limitation is that you cannot share objects between fixtures. Later, you’ll see how to overcome this limitation.

Ca c’est de l’évolution…

Ma dernière frustration c’est le plugin sfDoctrineGuardPlugin, qui marchait très bien, très fonctionnel, personnalisable, facile d’installation qui bien sur n’existe pas, à la place on a une documentation certes complète mais qui nous fait écrire et écrire du code pour au final quelque chose de moins bien.

A notre époque, il me semblait que le but c’était d’écrire moins de code « trivial », de réutiliser un maximum pour se concentrer que sur la logique pur et dur de l’application, avec Symfony2 non, on s’arrache les cheveux avant même de commencer…

Symfony2 se rapproche plus pour moi de la barre de fer que de la vraie boite à outil. Car je vais d’abors devoir me construire mon marteau, mon clou, ma regle, juste pour accrocher un cadre.
Alors que Symfony1 était la vrai boite à outils, quasiment complète dès le départs.

mar
27
2011

par Paul
chat

Une petite modification mineur du source a rendu possible d’insérer le chat dans d’autre page web:

<iframe src="http://wayr.org/LeNomDuSalon?display=embedded"></iframe>


Je suis entrain de réécrire le code avec le Framework Symfony
Pourquoi ?

  • Pour voir si c’était possible
  • Une fois avoir tout réécrit avec Symfony, passer de MongoDB à MySQL.

Et pourquoi passer de MongoDB à MySQL? Juste pour comparer les performances.

Symfony ne gérant pas les bases de données NoSQL (ici MongoDB), je dois aussi écrire la partie qui stocke en BD.
Ce n’est pas super compliqué vu que j’ai préféré ne pas crée un « vrai » ODM, mais je fais juste hériter mes modeles d’une classe qui se charge des ajouts/modifications/suppressions.

Ce qui donne du genre:
WhispsMessage hérite de MongoMessage qui hérite de Message

  • WhispsMessage ne sert qu’à « typer » les objects dans le code, que ce soit avec MongoDB ou MySQL.
  • MongoMessage qui gère l’implémentation spécifique à MongoDB.
  • Message est une classe abstraite qui rassemble les méthodes commune aux différentes BD.

J’avoue que ce point est encore un peu flou dans ma tête.

Le plus gros problèmes que je rencontre, c’est écrire les modeles de tel façon à ce que le changement de MongoDB à *SQL soit très simple.
Du coup la réutilisation des classes/objets/fonctions qui n’interagissent pas avec la BD est plus complexe, car j’avais un peu fait ça comme un porc.

En effet, j’avais l’habitude de faire:

$monDocument->champsDuDocument = 'foo';

Ce qui ne pose aucun problème si on change de BD, sauf quand il s’agit de liaison entre les tables.
Avec MongoDB, les relations entre les « collections » je les gérais directement dans le document.

Pour simplifier je faisais du genre:

//$document1 dans la collection1
//$document2 dans la collection2
$document1->$collection2 = array($document2->id);
$document2->$collection1 = array($document1->id);

Je n’ai pas changé ma façon de gérer les relations (vu que le but c’est de refaire à l’identique dans un premier temps).
Par contre, j’ai crée des méthodes spécifique pour les gérer.

$document1->linkWith($document2);
$document1->linkWith($document3);
$document1->unlinkWith($document2);

$documents = $document1->getAllLinks();
//$documents[0] == $document3

Au final ça ne change rien si ce n’est que lors du passage à MySQL, je n’aurais que ces méthodes à réécrire (à priori).


En écrivant ces lignes je me rends compte que ce n’est pas très clair donc ça ne doit pas être la meilleure solution.
Mais le but ultime est vraiment de passer à MySQL et donc d’utiliser les fonctionnalités de l’ORM Doctrine.

mar
03
2011

par Paul
chat

J’en avais marre de devoir lancé un client lourd pour pouvoir chatter avec mes amis, surtout que la plus part ne pouvaient pas car IRC était filtrer par le proxy de leur entreprise. J’ai donc développé mon propre chat pour le Web en utilisant les technos :

Continue reading ‘Whisps : Le chat 2.0 …’ »

mar
02
2011

par Paul
php_squad

Je viens de tomber sur: phpreboot

En regardant rapidement, ça a l’air sympathique:

  • Support de l’unicode
  • JSON literal
  • a SQL compatible syntax
  • a dynamic language with duck typing and a gradual type system

Continue reading ‘PHP Reboot, mais pourquoi tant de haine ?’ »

mar
02
2011

par Paul
resident_evil_viruss_display

Cela fait plusieurs mois que je me suis mis au framework PHP Symfony

Afin de ne pas perdre plusieurs heures à rechercher les solutions aux problèmes que je rencontre, je vais les recenser ici.

Les relations dans les fixtures

schema.yml

User:
  columns:
    id: {type: integer, primary: true, autoincrement: true}
    name: {type: string(255), notnull: true}

PhoneNumber:
  columns:
    id: {type integer, primary: true, autoincrement: true}
    user_id: {type integer, notnull: true}
    phone: {type: string(10), notnull: true}
  relations:
    User:
      local: user_id
      foreign: id
      foreignAlias: PhoneNumber

Je faisais :

fixtures.yml

User:
  user1:
    id: 1
    name: foo

PhoneNumber:
  ph1:
    id: 1
    user_id: 1
    phone: "0101010101"

Ce qui me sortait un superbe message d’erreur :

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails

Après avoir cherché pas mal de temps j’ai trouvé qu’il fallait faire :

fixtures.yml

User:
  user1:
    id: 1
    name: foo

PhoneNumber:
  ph1:
    id: 1
    User: user1
    phone: "0101010101"

\o/