Implémenter belongs_to
en quelques lignesgrâce à Prototype

L'implémentation d'ActiveRecord dans ICanBoogie permet de faire beaucoup de choses, notamment en terme de construction de requêtes, malheureusement la partie association péchait un peu. Aujourd'hui, la situation s'arrange quelque peu avec l'implémentation de la relation appartient à (belongs to), et comme vous allez le voir cela a été très simple à mettre en œuvre grâce aux fonctionnalités de Prototype.

Définir une relation d'appartenance

L'attribut BELONGS_TO permet de définir une relation d'appartenance. Considérons un modèle « guests » définit comme suit :

<?php

use ICanBoogie\ActiveRecord\Model;

$guests_attributes = array
(
    Model::BELONGS_TO => 'events',
    Model::SCHEMA => array
    (
        'fields' => array
        (
            'event_id' => array('foreign''primary' => true),
            'email' => array('varchar''primary' => true),
            // …
        )
    )
);

Ici, l'attribut BELONGS_TO définit que les enregistrements du modèle « guests » appartiennent à des enregistrements du modèle « events ». Il s'agit d'une relation simple, établie à partir du champ event_id, qui est aussi la clé primaire du modèle « events » :

<?php

use ICanBoogie\ActiveRecord\Model;

$events_attributes = array
(
    Model::SCHEMA => array
    (
        'fields' => array
        (
            'event_id' => 'serial',
            // …
        )
    )
);

Ajout automatique du getter correspondant

Lorsque l'attribut est défini, un getter est automatiquement ajouté au prototype des enregistrements du modèle. Par exemple, pour le modèle « events » le getter get_event sera ajouté, ce qui permettra d'obtenir l'objet évènement auquel appartient un invité par la propriété magique event.

<?php

$guest = $core->models['guest']->one;

var_dump($guest->event);

Voici le code qui a était ajouté à la classe Model :

<?php

namespace ICanBoogie\ActiveRecord;

use ICanBoogie\ActiveRecord;

class Model extends Table implements \ArrayAccess
{
    // …

    public function belongs_to($belongs_to)
    {
        $activerecord_class = $this->activerecord_class;
        $getter_name = 'get_' . \ICanBoogie\singularize($belongs_to);

        if ($activerecord_class == 'ICanBoogie\ActiveRecord')
        {
            throw new ActiveRecordException('The Active Record class cannot be <code>ICanBoogie\ActiveRecord</code> for a <em>belongs to</em> relationship.');
        }

        $prototype = \ICanBoogie\Prototype::get($activerecord_class);

        $prototype[$getter_name] = function(ActiveRecord $ar) use($belongs_to)
        {
            $model = get_model($belongs_to);
            $primary = $model->primary;
            $key = $ar->$primary;

            return $key ? $model[$key] : null;
        };
    }

    // …
}

Avec cette dizaine de lignes, les active record n'auront plus à définir de getter pour leurs relations d'appartenance. Pratique.

Laisser un commentaire

Pas de commentaire