Introduction

Base de données des exemples

Pour nos exemples, nous utiliserons une base de données contenant 3 tables SQL que voici :

Table "users"

idnamepseudoagelast_actionalive
1PaulPolo342016-01-141
2MarcelMamar752012-04-240
3JacquesJack222014-08-041
4JulieGrenouille322015-10-281
5HenriRiton302015-09-221

Table "items"

idrefFK_user_IDFK_comment_IDdate_creationcontent
1itemFlask12015-02-28["a","bit","of","json"]
2itemBall322015-07-29{"parts":22,"type":"leather","hardness":5.314,"filled":true}
3itemFlow42015-07-06[]
4itemNiuk312015-01-14{"leski":"mow","gniuk":"gniuk"}
5itemZaa532015-12-05[7,356,20,16]

Table "comments"

iddateFK_user_IDFK_item_IDtext
12015-11-2114What a nice comment, gniuk gniuk!
22015-12-0432I'm writing something about balls.
32015-12-2355Wazzaaaaa!

Configuration pour les exemples

Avant d'utiliser les outils, il faut définir les constantes et les variables de configuration. Nous utiliserons donc la configuration suivante :

/**
 * Configuration (Les globales qui sont requises par Altitude)
 */
define("HOST", "localhost");
define("USER", "username");
define("PASS", "********");
define("BASE", "database");
define("DSN",  "mysql:dbname=".BASE.";host=".HOST);

define("FOREIGNKEYS_PREFIX", "FK_");
$RELATIONS = Array(
    "FK_user_ID"	=> Array('table' => "users",	'alias' => "user"),
    "FK_item_ID"	=> Array('table' => "items",	'alias' => "item"),
    "FK_comment_ID"	=> Array('table' => "comments",	'alias' => "comment")
);
define("DATE_CREATION", "date_creation");
define("LAST_UPDATE", "last_action");
$DATE_FIELDS = Array("date", "last_action", "date_creation");

/**
 * Inclusion des fichiers de classes
 */
require("classes/Listing.class.php");
require("classes/Infos.class.php");
				

Avec notamment :

  • La constante FOREIGNKEYS_PREFIX permet aux outils d'effectuer les jointures automatiquement. Cette constante est le préfixe utilisé pour les noms de colonnes qui contiennent les ID des relations à chercher.
  • Ces jointures sont décrites dans la variable $RELATIONS : Un tableau associatif qui décrit les relations entre les colonnes préfixées avec "FK_" et les autres tables. Chaque entrée du tableau contient le nom de la colonne source associé à un tableau, dont la clé "table" est le nom de la table de destination, et la clé "alias", le nom que prendra cette destination. Veillez à ce que l'alias soit différent du nom de la colonne source.
  • Les deux constantes DATE_CREATION et LAST_UPDATE servent à utiliser la mise à jour automatique des dates de création et de dernière modification. Enfin, la variable $DATE_FIELDS est une liste des colonnes qui contiennent des dates au format SQL, susceptibles d'être reformatées au format ISO 8601.


Listing

Utilisation la plus simple

Voici la plus simple façon d'utiliser l'objet "Listing" :

$l = new Listing();
$users = $l->getList("users");

print_r($users);

Ceci retournera toutes les entrées de la table "users", comme cela :

Array (
    [0] => Array (
        [id] => 1
        [name] => Paul
        [pseudo] => Polo
        [age] => 34
        [last_action] => 2016-01-14T00:00:00+01:00
        [alive] => 1
    )
    [1] => Array ( .... )
    [2] => Array ( .... )
    [3] => Array ( .... )
    [4] => Array (
        [id] => 5
        [name] => Henri
        [pseudo] => Riton
        [age] => 30
        [last_action] => 2015-09-22T00:00:00+02:00
        [alive] => 1
    )
)

C'est une simple liste de toutes les entrées de la table, non triée. Chaque ligne de cette liste contient toutes les infos de chaque entrée sous forme de tableau associatif.

Vous pouvez utiliser une colonne en tant qu'index du tableau (tableau associatif). Veillez cependant à ce que cette colonne soit un index Unique de la table, afin de ne pas écraser des lignes. Pour utiliser la colonne "name" en tant qu'index du tableau, il suffit d'utiliser la méthode simplyList(), de cette manière :

$l = new Listing();
$l->getList("users");

$users = $l->reindexList("users");

print_r($users);

Ce qui retournera :

Array (
    [Paul] => Array (
        [id] => 1
        [name] => Paul
        [pseudo] => Polo
        [age] => 34
        [last_action] => 2016-01-14T00:00:00+01:00
        [alive] => 1
    )
    [Marcel]  => Array ( .... )
    [Jacques] => Array ( .... )
    [Julie]   => Array ( .... )
    [Henri]   => Array (
        [id] => 5
        [name] => Henri
        [pseudo] => Riton
        [age] => 30
        [last_action] => 2015-09-22T00:00:00+02:00
        [alive] => 1
    )
)

Pour ne récupérer que certaines colonnes, il faut utiliser le 2eme paramètre de la méthode getList(), à savoir $want. Par exemple, pour ne récupérer que le nom et le pseudo des utilisateurs, nous ferons :

$l = new Listing();
$users = $l->getList("users", "name,pseudo");

print_r($users);

Ce qui nous donnera :

Array(
    [0] => Array (
        [name] => Paul
        [pseudo] => Polo
    )
    [1] => Array (
        [name] => Marcel
        [pseudo] => Mamar
    )
    [2] => Array (
        [name] => Jacques
        [pseudo] => Jack
    )
    [3] => Array (
        [name] => Julie
        [pseudo] => Grenouille
    )
    [4] => Array (
        [name] => Henri
        [pseudo] => Riton
    )
)

Pour récupérer toutes les colonnes, il suffit d'omettre $want, ou bien de lui passer la chaîne "*" (c'est le comportement par défaut).

Le tri des données

Voyons maintenant l'utilisation du tri. Pour trier les données, il suffit d'ajouter les paramètres $sortBy et $order. Ici nous allons trier la liste des utilisateurs selon leur âge, du plus vieux au plus jeune :

$l = new Listing();
$users = $l->getList("users", "*", "age", "desc");

print_r($users);

Ce qui nous donnera :

Array (
    [0] => Array (
        [id] => 2
        [name] => Marcel
        [pseudo] => Mamar
        [age] => 75
        [last_action] => 2012-04-24T00:00:00+02:00
        [alive] => 0
    )
    [1] => Array ( ... /* Paul, age => 34 */ ... )
    [2] => Array ( ... /* Julie, age => 32 */ ... )
    [3] => Array ( ... /* Henri, age => 30 */ ... )
    [4] => Array (
        [id] => 3
        [name] => Jacques
        [pseudo] => Jack
        [age] => 22
        [last_action] => 2014-10-28T00:00:00+01:00
        [alive] => 1
    )
)

Notez que par défaut, l'ordre du tri est "asc" (ascendant). Il suffit alors d'ignorer $order, ou bien de lui passer la chaîne "asc".

Le filtrage des données

Pour filtrer les données, nous utiliserons les trois paramètres suivants : $filter_key, $filter_comp, et $filter_val de la méthode getList().
Ainsi, pour ne récupérer rapidement que les utilisateurs dont l'âge est supérieur ou égal à 34 ans, nous pouvons faire :

$l = new Listing();
$users = $l->getList("users", "*", "last_action", "desc", "age", ">=", 34);

print_r($users);

Il en résultera :

Array (
    [0] => Array (
        [id] => 1
        [name] => Paul
        [pseudo] => Polo
        [age] => 34
        [last_action] => 2016-01-14T00:00:00+01:00
        [alive] => 1
    )
    [1] => Array (
        [id] => 2
        [name] => Marcel
        [pseudo] => Mamar
        [age] => 75
        [last_action] => 2012-04-24T00:00:00+02:00
        [alive] => 0
    )
)

Nous avons donc seulement les deux utilisateurs dont l'âge est supérieur ou égal à 34 ans, triés selon la date de leur dernière activité ('last_action'). Notez qu'on a utilisé l'opérateur ">=". Cet opérateur correspond à celui utilisé en SQL. Il est donc aussi possible d'utiliser "<=", "<", ">", "=", "!=", "LIKE", "BETWEEN", etc.

Maintenant, comment faire si nous voulons seulement les utilisateurs agés d'au moins 30 ans mais qui sont toujours en vie ?
C'est là qu'entre en scène le filtrage multiple ! Pour cela nous allons utiliser la méthode addFilter(). Cette méthode peut être utilisée autant de fois que l'on veut, avant l'appel à getList(). Une fois qu'on a défini un filtre avec cette méthode, il n'est plus nécessaire d'utiliser le filtrage interne à getList().
Reprenons notre exemple :

$l = new Listing();

$l->addFilter("age",   ">", 30);
$l->addFilter("alive", "=",  1);

$users = $l->getList("users", "*", "last_action", "desc");
print_r($users);

Ce qui nous retournera :

Array (
    [0] => Array (
        [id] => 1
        [name] => Paul
        [pseudo] => Polo
        [age] => 34
        [last_action] => 2016-01-14T00:00:00+01:00
        [alive] => 1
    )
    [1] => Array (
        [id] => 4
        [name] => Julie
        [pseudo] => Grenouille
        [age] => 32
        [last_action] => 2015-10-28T00:00:00+01:00
        [alive] => 1
    )
)

Ensuite, si pour une raison ou une autre, vous devez enlever ou modifier les filtres, il suffit d'utiliser la méthode resetFilter().
Exemple d'utilisation :

$l = new Listing();

$l->addFilter("age",   ">", 30);
$l->addFilter("alive", "=",  1);
$older_users = $l->getList("users");

$l->resetFilter();

$l->addFilter("age",   "<=", 30);
$youger_users = $l->getList("users");

Ainsi la variable $older_users contiendra un tableau avec les utilisateurs dont l'âge est supérieur à 30 ans, mais qui sont toujours en vie, et la variable $youger_users contiendra ceux dont l'âge est inférieur ou égal à 30 ans.

Il est bien entendu possible de modifier le comportement d'ajout des filtres. Par défaut, l'opérande utilisée entre chaque filtre est "AND". Vous pouvez spécifier n'importe quelle opérande avec le 4eme paramètre, $logic ('OR', 'NAND', 'NOR'...).

Enfin, si vous avez besoin d'utiliser une fonction SQL dans le filtrage, vous avez la possibilité d'utiliser la méthode setFilterSQL().
Voici un exemple :

$l = new Listing();

$l->setFilterSQL("`age` >= 30 AND `last_action` <= DATE_ADD(NOW(), INTERVAL -6 MONTH)");
$users = $l->getList("users");

Ce qui nous donnera la liste des utilisateurs agés de plus de 30 ans, et dont l'activité la plus récente date d'au moins 6 mois.
Cependant, utilisez cette méthode avec prudence, surtout si vous incluez des variables dans le paramètre $filtre, car cela ouvre des possibilités d'injection SQL. Assurez-vous au préalable que les variables sont saines.

Les jointures

Pour illustrer les jointures, prenons la table comments. Cette table dispose de deux colonnes préfixées avec la chaine "FK_". Ce préfixe a été renseigné dans la constante FOREIGNKEYS_PREFIX. Les deux colonnes qui nous intéressent sont donc "FK_user_ID" et "FK_item_ID". Ces deux colonnes sont présentent dans le tableau $RELATIONS, ce qui permet à Altitude d'établir la relation entre ces colonnes et les tables associées. Si ce tableau n'existe pas, les jointures seront ignorées et les colonnes retournées ne contiendront que les ID.
Rappel du tableau écrit lors de la configuration :

$RELATIONS = Array(
    "FK_user_ID"	=> Array('table' => "users",	'alias' => "user"),
    "FK_item_ID"	=> Array('table' => "items",	'alias' => "item"),
    "FK_comment_ID"	=> Array('table' => "comments",	'alias' => "comment")
);

Bien. Maintenant, disons que nous voulons récupérer la liste des commentaires, mais nous voulons dans le même temps récupérer toutes les informations de l'utilisateur qui l'a écrit, ainsi que les informations de l'item sur lequel il a été écrit. Pour cela, rien de plus simple :

$l = new Listing();

$comments = $l->getList("comments");
print_r($comments);

Nous obtiendrons :

Array (
    [0] => Array (
            [id] => 1
            [date] => 2015-11-21T00:00:00+01:00
            [FK_user_ID] => 1
            [FK_item_ID] => 4
            [text] => What a nice comment, gniuk gniuk!
            [user] => Array
                (
                    [id] => 1
                    [name] => Paul
                    [pseudo] => Polo
                    [age] => 34
                    [last_action] => 2016-01-14
                    [alive] => 1
                )

            [item] => Array
                (
                    [id] => 4
                    [ref] => itemNiuk
                    [FK_user_ID] => 3
                    [FK_comment_ID] => 1
                    [date_creation] => 2015-01-14
                    [content] => {"leski":"mow","gniuk":"gniuk"}
                )
        )
    [1] => Array (...
    [2] => Array (...
    ... etc.

En gros, il n'y a rien à faire, les jointures sont automatiquement récupérées. Notez que les colonnes "FK_user_ID" et "FK_item_ID" sont présentes, mais que le tableau contient deux lignes supplémentaires : "user", et "item". Ces noms de clés correspondent à la valeur "alias" du tableau des correspondances $RELATIONS.

Si, pour une raison ou une autre, vous ne souhaitez pas récupérer les jointures, il suffit de mettre le paramètre $withFK (9eme position) à FALSE.



Infos

Récupérer une entrée

Pour récupérer les informations d'une entrée particulière d'une table de la base de données, il faut avant tout en connaître un identifiant unique, comme par exemple son 'id', ou bien le nom ou l'email d'un utilisateur, ou encore la référence d'un item. En effet, si l'objet "Infos" trouve plusieurs entrées avec l'identifiant donné, il renvoie une erreur.

Dans notre exemple nous utiliserons l'identifiant unique de la colonne "id". Voici comment procéder pour charger une entrée de la base de données en mémoire :

$i = new Infos("users");

$i->loadInfos("id", "3");
$user = $i->getManyInfos();

print_r($user);

Il en résultera le tableau suivant :

Array (
    [id] => 3
    [name] => Jacques
    [pseudo] => Jack
    [age] => 22
    [last_action] => 2014-10-28T00:00:00+01:00
    [alive] => 1
)

Utiliser la méthode getManyInfos() sans paramètre permet d'avoir toutes les colonnes. C'est le comportement par défaut. Cependant, il est possible de ne récupérer qu'une seule colonne, grâce au paramètre $column, comme ceci :

$i = new Infos("users");
$i->loadInfos("id", 3);

$userPseudo = $i->getManyInfos("pseudo");

print_r($userPseudo);

Ce qui donnera :

Jack

... Tellement simple. Mais qu'en est-il des jointures ? De la même manière que l'objet "Listing", les jointures se font automatiquement. Ainsi, au moment de l'appel à la méthode loadInfos(), les jointures sont résolues directement, et sont disponibles en mémoire. Pour vous le montrer, utilisons le même appel que précédemment sur la table "comments" :

$i = new Infos("comments");
$i->loadInfos("id", 3);

$comment = $i->getManyInfos();

print_r($comment);

Ce qui donne :

Array (
    [id] => 3
    [date] => 2015-12-23T00:00:00+01:00
    [FK_user_ID] => 5
    [FK_item_ID] => 5
    [text] => Wazzaaaaa!
    [user] => Array (
        [id] => 5
        [name] => Henri
        [pseudo] => Riton
        [age] => 30
        [last_action] => 2015-09-22
        [alive] => 1
    )

    [item] => Array (
        [id] => 5
        [ref] => itemZaa
        [FK_user_ID] => 5
        [FK_comment_ID] => 3
        [date_creation] => 2015-12-05
        [content] => [7,356,20,16]
    )
)

Magnifique. Cela veut dire que plus tard dans le code, nous pourrons aussi faire :

$i->getManyInfos("user")

Qui nous retournera un seul tableau contenant toutes les informations de l'utilisateur qui a écrit le commentaire !

Modifier une entrée

Nous allons modifier le pseudo de l'utilisateur dont le nom est "Marcel". Pour cela il faut d'abord le charger en mémoire, puis modifier son pseudo, et enfin sauvegarder la modification dans la base de données. Voici comment procéder :

$i = new Infos("users");
$i->loadInfos("id", 2);

$i->setInfo("pseudo", "Marcello");
$i->save();

La méthode setInfo() permet d'ajouter ou de modifier une colonne de l'entrée chargée en mémoire. Notez que si vous mettez le nom d'une colonne qui n'existe pas comme premier paramètre, elle sera automatiquement ajoutée à la structure de la table.
La méthode save() est celle qui va enregistrer la modification de l'entrée dans la base. Une fois que cette méthode a été éxécutée, il est impossible de revenir en arrière.
Si vous voulez empêcher la création automatique de colonne (dans le cas où le paramètre $key de setInfo() est le nom d'une colonne inexistante), il vous suffit de mettre le 3eme paramètre ($autoAddCol) de save() à FALSE.

Il est aussi possible de modifier toutes les colonnes d'un seul coup, grâce à la méthode setManyInfos(). Le paramètre $newInfos doit être un tableau associatif, la clé étant le nom de la colonne. Par exemple :

$i = new Infos("users");
$i->loadInfos("id", 2);

$newInfos = Array(
    "name" => "Marcelle",
    "pseudo" => "Marcie",
    "age" => 69
);
$i->setManyInfos($newInfos);
$i->save();

Comme pour setInfo(), il faut sauvegarder les changements pour qu'ils soient pris en compte dans la base avec save(). Une fois sauvegardé, on ne peut plus revenir en arrière.

Créer une entrée

Pour ajouter une entrée dans une table de la base de données, il suffit de faire comme précédemment, mais sans utiliser la méthode loadInfos(). Par exemple, ajoutons un utilisateur "Alex" dans la table "users" :

$i = new Infos("users");

$newInfos = Array(
    "name" => "Alex",
    "pseudo" => "AK",
    "age" => 29
);
$i->setManyInfos($newInfos);
$i->save();

$user = $i->getManyInfos();
print_r($user);

Il en résultera l'entrée suivante :

Array (
    [id] => 6
    [name] => Alex
    [pseudo] => AK
    [age] => 29
    [last_action] => 0000-00-00T00:00:00+00:00
    [alive] => 0
)

Vous vous serez aperçu que les deux colonnes que nous n'avons pas renseigné ont pris les valeurs par défaut de la table SQL.

Supprimer une entrée

Pour supprimer une entrée, nous utiliserons la méthode delete(). Cependant attention ! Cette action est irréversible. Pour notre exemple, supprimons l'entrée que nous venons de créer au paragraphe précédent :

$i = new Infos("users");
$i->loadInfos("id", 6);

$i->delete();

Et voilà, notre entrée a disparu de la base de données. Vous pouvez aussi utiliser cette fonction de la manière suivante :

$i = new Infos("users");
$i->delete("id", 6);

Cela aura le même effet que précédemment, mais nous avons spécifié la clé et la valeur de l'entrée à supprimer directement dans la méthode delete(), sans utiliser loadInfos(). Ce filtrage basique peut etre utile pour supprimer plusieurs entrées d'un seul coup, en spécifiant par exemple :

$i = new Infos("users");
$i->delete("alive", 0);

Ce qui supprimera tous les utilisateurs dont la colonne "alive" est à 0.
L'utilisation de la méthode loadInfos() est donc facultative, mais elle permet d'éviter les erreurs et d'être certain de n'éffacer qu'une seule entrée.