L'API ActiveRecord du framework WdCore

Eléphant du PHP | 121 Messages

02 févr. 2011, 17:07

Adoptant ce que propose le framework Rails pour le langage de programmation Ruby, le framework WdCore offre une API permettant de manipuler les enregistrements en base de données comme de simples objets. On peut ainsi créer des tables, ajouter des enregistrements, les modifier, les supprimer sans jamais avoir à saisir la moindre commande SQL. Cet article a pour but de présenter les méthodes permettant de récupérer un objet, ou une collection d'objets, depuis une base de données, mais aussi de spécifier l'ordre dans lequel les objets sont récupérés, comment les grouper, ou encore comment ne récupérer que certains champs.

Si vous êtes intéressé par une approche totalement objet de la gestion de données, peut-être que mon article Récupérer des données depuis une base en utilisant l'API ActiveRecord du framework WdCore vous donnera des idées. Voici quelques exemples très courts, montrant ce que l'API proposée par le framework WdCore permet de faire :

Obtenir des objets :
$record = $model[10];
# ou
$record = $model->find(10);

$records = $model->find(10, 15, 19);
# ou
$records = $model->find(array(10, 15, 19));
Conditions :
$model->where('is_online = ?', true);
$model->where(array('is_online' => true, 'is_home_excluded' => false));
$model->where('siteid = 0 OR siteid = ?', 1)->where('language = '' OR language = ?', "fr");

# Sous-ensembles

$model->where(array('order_count' => array(1, 2, 3)); # IN
$model->where(array('!order_count' => array(1, 2, 3)); # NOT IN

# Filtres dynamiques

$model->find_by_nid(1);
$model->find_by_siteid_and_language(1, 'fr');

# Portées

$model->visible;
Grouper, ordonner :
$model->group('date(created)')->order('created');
$model->group('date(created)')->having('created > ?', date('Y-m-d', strtotime('-1 month')))->order('created');
Limites et décalage :
$model->where('is_online = 1')->limit(10); // retourne les 10 premiers enregistrements
$model->where('is_online = 1')->limit(5, 10); // retourne les enregistrements 6 à 16

$model->where('is_online = 1')->offset(5); // retourne les enregistrements de 6 jusqu'au dernier
$model->where('is_online = 1')->offset(5)->limit(10);
Sélection de champs :
$model->select('nid, created, title');
$model->select('nid, created, CONCAT_WS(":", title, language)');
Jointures :
$model->joins('INNER JOIN contents USING(nid)');
$model->joins(':contents');
Récupérer les données :
$model->all;
$model->order('created DESC')->all(PDO::FETCH_ASSOC);
$model->order('created DESC')->mode(PDO::FETCH_ASSOC)->all;
$model->order('created DESC')->one;
$model->select('nid, title')->pairs;
$model->select('title')->rc;
Tester l'existence d'objets :
$model->exists;
$model->exists(1, 2, 3);
$model->exists(array(1, 2, 3));
$model->where('author = ?', 'madonna')->exists;
Fonctions de calcul :
$model->count;
$model->count('is_online');
$model->average('score');
$model->minimum('age');
$model->maximum('age');
$model->sum('comments_count');
Bref, de quoi faire, puisqu'en on peut tout mélanger dans n'importe quel sens :
$model->select('nid, title')->joins(':user.users')->where('is_online = 1 AND (site = 0 OR site = ?) AND (language = "" OR language = ?)', 1, 'fr')->group('YEAR(created)')->order('user.last_connection, title')->limit(10, 20)->pairs;
Pour en savoir plus, merci de consulter mon article : Récupérer des données depuis une base en utilisant l'API ActiveRecord du framework WdCore.

Avatar du membre
ViPHP
xTG
ViPHP | 7331 Messages

02 févr. 2011, 18:10

Justement ce que je recherchais. J'étais partit dans l'idée d'en coder une mais pourquoi réinventer la roue. ^^
Merci bien.

Avatar du membre
ViPHP
xTG
ViPHP | 7331 Messages

03 févr. 2011, 16:02

En fait des fois il est peut être plus profitable de réinventer la roue...
Le code de WdCore est certes propre mais... Les commentaires ils sont où ?
Il y a 5-10 lignes de commentaires sur des fonction n'en nécessitant que peu et aucun commentaires sur des fonctions en nécessitant moultes !
Et comme il n'y a aucune documentation...

PS: la personne qui a posté un commentaire sur ton blog indiquant que c'était très bien documenté a pas du regarder tous les fichiers...

Bref je persévère pour le moment mais c'est un sacré bordel pour quelqu'un qui n'a pas déjà utilisé une telle technologie.
Je n'imagine même pas comment font les utilisateurs de ton CMS si c'est pareil...

Eléphant du PHP | 121 Messages

03 févr. 2011, 23:57

Salut xTG,

Effectivement il n'y a pratiquement pas de documentation à l'heure actuelle, alors j'essaie de la construire petit à petit au travers de mes articles, ce qui n'est pas simple avec le peu de temps que je peux y consacrer. Mais, comme on dit, petit à petit l'oiseau fait son nid.

En espérant répondre à tes questions, j'ai commencé un nouvel article traitant des connexions, des modèles et bien sur des enregistrements actifs. J'espère le terminer ce weekend. En attendant, peux être qu'un petit exemple te permettra d'y voir plus clair :
<?php

$path = dirname(__FILE__);

#
# Emplacement de la classe WdCore, qui nous permet d'instancier l'objet `core`, coeur du framework.
# Il ne servira pas à grand chose, mais au moins le framework sera basiquement configuré, notamment
# l'autoloader.
#

require_once dirname($path) . '/wdcore/wdcore.php';

$core = new WdCore();

#
# Il s'agit de la classe utilisée pour instancier les enregistrements que nous récupérerons plus
# tard depuis notre modèle.
#

class my_WdActiveRecord extends WdActiveRecord
{
	protected function __get_reversed_number()
	{
		return strrev((string) $this->number);
	}
}

#
# On ouvre une connexion à la base de donnée "models-and-records.sq3" en utilisant le driver
# SQLite. On utilise SQLite parce que la base ne demandera aucun effort à mettre en place. Il faut
# tout de même vérifier les permissions d'écriture.
#

$connection = new WdDatabase("sqlite:$path/models-and-records.sq3");

#
# Définition et instanciation de notre modèle.
#

$model = new WdModel
(
	array
	(
		WdModel::T_ACTIVERECORD_CLASS => 'my_WdActiveRecord',
		WdModel::T_CONNECTION => $connection,
		WdModel::T_NAME => 'node',
		WdModel::T_SCHEMA => array
		(
			'fields' => array
			(
				'id' => 'serial',
				'title' => array('varchar', 80),
				'number' => array('integer', 'unsigned' => true)
			)
		)
	)
);

#
# Nous installons le modèle, s'il n'est pas déjà installé (création de la table correspondante).
#

if (!$model->isInstalled())
{
	$model->install();
}

#
# On le peuple de quelques enregistrements
#

$i = 10;

while ($i--)
{
	$number = uniqid();

	$model->save
	(
		array
		(
			'title' => "title-$i-" . md5($number),
			'number' => $number
		)
	);
}

#
# On récupère tous les enregistrements du modèle et pour chacun d'entre eux on affiche la valeur
# de la clé primaire et un nombre renversé, utilisant un magnifique getter.
#

foreach ($model->all as $record)
{
	echo "record #{$record->id}, reversed number: {$record->reversed_number}<br />";
}
En espérant pouvoir en dire plus très vite.

Avatar du membre
ViPHP
xTG
ViPHP | 7331 Messages

04 févr. 2011, 00:28

Les classes sont bien utiles, j'ai donc pris deux bons jours dessus pour découvrir le minimum.
Il est fort dommage que cela ne soit pas très accessible pour le moment du fait du manque de commentaires. On est obligé de décortiquer le fonctionnement des fonctions pour savoir quoi leur passer en paramètres. :/
Voilà pourquoi il faut toujours commenter une fonction en même temps qu'on la code (certains la commente même avant de la coder).
Une documentation n'est pas forcement utile quand le code est commenté. Certes les commentaires ne fournissent pas d'exemple mais donnent une marche à suivre et on s'y retrouve au final.
Et puis des documentations on peut même en générer à partir des commentaires. ^^

Mais dans l'ensemble c'est du très bon boulot. :)
Bonne continuation.