Utiliser les modèles de RedBean avec un namespace PHP

RedBean est un ORM PHP dont le principal atout est la concision de la syntaxe ; en effet, l'usage générique ne requiert que l'appel à des méthodes de la classe frontale R, ce qui permet d'effectuer toutes sortes d'opérations en base de données en un minimum de caractères. Ceci à un point tel que l'utilisation de modèles pour représenter de manière plus concrète les objets manipulés est un point qui arrive étonnamment tard dans la documentation de l'outil.

De son propre aveu, l'auteur n'est pas un fan des namespaces introduits dans PHP 5.3 ; en toute objectivité, cette vision peut devenir un frein considérable à l'apogée de Composer et de PSR-0, à l'image du petit challenge que je me propose de vous aider à résoudre aujourd'hui.

En effet, RedBean propose une liaison automatique entre les "beans" (les objets de base obtenus lors des requêtes en lecture) et les éventuels modèles plus complexes que vous pouvez être amené à créer selon vos besoins, le tout reposant sur FUSE. Là où le bât blesse, c'est que ce dernier ne sera pas capable de trouver vos classes si celles-ci sont écrites sous un namespace donné. Il est heureusement possible de surcharger le comportement par défaut de l'ORM en la matière, mais le manque de documentation précise à ce sujet peut vous mener droit vers quelques heures de serrage de dents et d'arrachage de cheveux (c'est du vécu). Voici un exemple de solution !

Tout d'abord, nous allons surcharger la classe concernée de RedBean, et plus précisément sa méthode chargée de trouver le modèle correspondant à un "bean" donné :

<?php

namespace MyNamespace;

class MyBeanHelper extends \RedBean_BeanHelper_Facade
{
public function getModelForBean(\RedBean_OODBBean $bean)
{
$modelName = 'MyNamespace\\Model\\'.ucfirst($bean->getMeta('type'));

if (! class_exists($modelName)) {
return null;
}

$obj = \RedBean_ModelHelper::factory($modelName);
$obj->loadBean($bean);
return $obj;
}
}

Notez que pour l'exemple, je me contente d'un copier-coller de la fonction d'origine où j'ajoute mon namespace "en dur" devant le nom de modèle généré par défaut (tout en optimisant un peu l'ensemble). Que cela ne vous empêche pas de mettre à profit le fait de devoir créer une classe dans l'unique but de faire entendre raison à RedBean, afin d'en faire quelque chose d'un peu plus maniable (par exemple, en générant le namespace selon le type de "bean" auquel vous êtes confronté... tout dépend de la structure de votre code).

Achevons le travail en remplaçant l'instance de la classe d'origine par une de la nôtre :

// Faisons en sorte de conserver le petit nom de la classe façade de l'ORM
use \RedBean_Facade as R;

R::$toolbox->getRedBean()->setBeanHelper(new MyNamespace\MyBeanHelper());

C'est tout ! Je n'ai pas trouvé de solution vraiment universelle pour pallier ce type de situation ; si vous vous en sortez mieux, n'hésitez surtout pas...