Accès aux données
-
Préambule
Le framework propose plusieurs méthodes pour accéder aux données.
La première est de partir de vos objets métier, et d’utiliser simplement leurs propriétés, qui relient les objets métiers les uns aux autres. L’accès aux données stockées, dans votre base de données par exemple, se fera alors implicitement par l’ORM du Framework, sans aucune nécessité de programmation pour lire vos données.
Sinon, quand le besoin s’en fait vraiment sentir, vous pouvez toujours accéder directement à vos données en utilisant les liens aux données à travers les méthodes de la classe Dao si vous utilisez votre connexion principale, ou de votre objet Data link pour les connexions secondaires.
Dans les deux cas vous devrez avant tout décrire vos classes métier, traduction directe de votre diagramme de classes.
Dans les deux cas il est inutile de décrire le lien entre vos objets métier et votre base de données relationnelle. Le Framework se chargera seul de créer la structure de données correspondant à vos objets. Le nommage de vos classes métier et de leurs propriétés est très important, choisissez les avec soin, en privilégiant leur lisibilité et leur sens.
Par exemple si l’on considère la classe métier User (simplifiée pour l’exemple) du Framework :
namespace ITRocks\Framework; class User { /** * @var string */ public $login; /** * @password sha1 * @var string */ public $password; }
Dès que vous accéderez à votre liste d’utilisateurs, rendue accessible par un menu dans votre fichier de configuration par exemple :
$config['Author/Application'] = [ Configuration::EXTENDS_APP => 'ITRocks/Framework', Priority::NORMAL => [ Menu::class => [ 'Administration' => [ '/ITRocks/Framework/Users' => 'Users' ] ] ] );
Le framework se chargera de créer la structure de base de données nécessaire : à savoir une table users avec trois champs : un identifiant unique id – invisible pour le développeur -, les champs chaînes de caractères login et password. Cette mise à jour automatique de la structure de la base de données utilise le plugin Mysql_Maintainer, actif dans la configuration standard du framework.
Les classes métier
Application de base
Vos classes métier sont le pilier de votre application : ils conditionnent tout le reste. Une bonne organisation des données est une composante essentielle pour un logiciel réussi.
Aussi les classes métier sont la seule composante du modèle MVC que vous devez obligatoirement développer. Le framework peut s’occuper du reste, pour les comportements standard du moins.Tant que vous avez correctement programmé vos classes métier, l’accès aux données fait partie des choses implicites.
Ainsi considérez l’application suivante My_Books développée par son auteur Tickleman :Fichier de configuration my_books.php :
$config['Tickleman/My_Books'] = [ Configuration::APP => Application::class, Configuration::EXTENDS_APP => 'ITRocks/Framework', Priority::NORMAL => [ Dao::class => [ Link::DATABASE => 'my_books', Link::LOGIN => 'my_books', Link::PASSWORD => $pwd['my_books'] ], Menu::class => [ Menu::TITLE => [SL, 'Home', '#main'], 'Library' => [ '/Tickleman/My_Books/Books' => 'My books' ] ] ] ];
Votre classe métier dans le fichier tickleman/my_books/Book.php :
namespace Tickleman\My_Books; class Book { /** * @var string */ public $title; /** * @var string * @max_length 60000 */ public $summary; }
Connectez vous simplement à votre application : vous avez le menu que vous avez paramétré dans votre fichier de configuration à gauche, et vous pouvez naviguer dans vos livres et utilisateurs stockés en base de données. Remarquez que si vous utilisez le bouton Ajouter, vous créez bien de nouveaux enregistrements dans les tables correspondantes de votre base de données, que vous pouvez consulter en liste, en vue simple ou en formulaire.
Mise en place de relations
Admettons qu’on veuille maintenant gérer pour chaque livre la liste des utilisateurs qui l’ont lu. On ajoute cette propriété à la classe
Book
:
/** * @link Map * @var ITRocks\Framework\User[] */ public $users;
L’application est à jour et vous verrez dans vos vues standard apparaître la gestion des utilisateurs associés à chaque livre.
Si maintenant vous développez un processus particulier sur un livre, donc recevant un
Book
en paramètre, vous pouvez simplement consulter la liste des utilisateurs qui l’ont lu en parcourant l’objet, sans vous préoccuper de savoir comment aller chercher ces données en base.
namespace Tickleman\My_Books; class Book_Informer { /** * @param $book Book * @return string[] */ public function inform(Book $book) { $users_names = []; foreach ($book->users as $user) { $users_names[] = $user->name; } return $users_names; } }
Mécanique interne
Vous avez ici l’impression de parcourir un objet pré-renseigné d’avance, rien d’extraordinaire donc. Détrompez-vous : sans le savoir, vous avez utilisé l’ORM du framework, qui s’est chargé pour vous d’aller lire la liste des données dont vous avez eu besoin, quand vous en avez eu besoin. En effet il ne serait pas raisonnable à la lecture d’un objet de charger l’intégralité des contenu des propriétés, et des propriétés des objets qui seraient stockés dans ces propriétés, etc. L’ORM charge donc le minimum vital, uniquement lorsqu’on a besoin des données, et uniquement la première fois qu’on doit y accéder.
Lorsque vous déclenchez le contrôleur qui va appeler
Book_Informer::inform($book)
, le contrôleur reçoit en paramètre leBook
considéré, que le framework s’est chargé de lire depuis la table books. Mais la table books ne comporte que les champs title et summary. La propriété$users
est restéenull
, car elle ne sera lue depuis la base de données que lorsque le programme en aura besoin.C’est ce qui arrive dans
L’annotation @link est donc essentielle et doit être renseignée pour toute propriété qui pointe sur un objet ou une agrégation d’objets. Utilisez :Book_Informer::inform()
: le programme parcourt la propriété$users
, demandant ainsi à y accéder. L’annotation @link indique au framework le type de relation que votre classeBook
entretient avec la classe User par le biais de cette propriété, en l’occurence Map indique que plusieurs utilisateurs peuvent être associés à chaque livre, et vice-versa. Le framework déclare implicitement le getter nécessaire pour qu’à la première demande de consultation de la propriété$users
l’ORM puisse être utilisé pour aller chercher en bases de données les utilisateurs qui ont eu le livre entre les mains.- @link Object si votre propriété est un objet simple : dans notre exemple nous pourrions avoir une propriété
$owner
de type User pour déclarer à quel utilisateur appartient le livre par exemple, - @link Map si votre propriété représente une agrégation d’objets : plusieurs objets tiers peuvent être liés à votre objet et vice-versa, comme dans l’exemple,
- @link Collection si votre propriété représente une composition d’objets : plusieurs objets tiers dépendant directement de votre objet : des lignes de commandes pour une commande, par exemple, n’ont pas d’existence propre en dehors d’une commande et feront l’objet de ce type de relation.
Conclusions
Ainsi simplement par le biais des propriétés de vos classes métiers, vous devriez pouvoir parcourir les données sans avoir besoin d’effectuer des appels implicités à l’ORM.
Toutefois l’accès via les propriétés des objets métier ne permet que de lire des données, jamais de les enregistrer. Si vous modifiez les valeurs des propriétés de vos objets, il faudra explicitement demander à l’ORM de les stocker.
L’accès via le Dao
Pour certains traitements, où la déclaration de propriétés dans des objets métiers ne serait pas justifiée, vous allez avoir besoin d’accéder directement aux données stockées, pour en extraire des objets.
La classe Dao du framework permet cela.
La classe propose des méthodes statiques pour accéder au lien de données (ou Data_Link) par défaut de l’environnement applicatif. Vous pouvez également récupérer ce lien de données pour l’utiliser directement, ou appeler ces mêmes méthodes depuis les objets Data_Link de vos liens de données secondaires.
Les méthodes standard proposées sont (toutes sont résumées plus en détail dans Dao) :
- @link Object si votre propriété est un objet simple : dans notre exemple nous pourrions avoir une propriété