2010-07-29 5 views
1

J'ai une collection de classes PHP qui peuvent être instanciées traditionnellement en utilisant des constructeurs. Maintenant, je veux ajouter la possibilité d'instancier ces objets en utilisant des fichiers de configuration YAML.Comment créer au mieux des objets à partir de fichiers de configuration?

Voici un exemple d'un fichier de configuration décrivant un formulaire Web:

title: Contact 
fields: 
    message: 
     type: text 
     required: true 
    topic: 
     type: dropdown 
     options: ["HTML", "CSS", "PHP"] 

Cela devrait se traduire par un objet de forme avec deux objets de champ correspondant. En d'autres termes, les fichiers de configuration décrivent parfois des objets contenant d'autres objets.

Je ne veux pas simplement un mappage des paires clé/valeur YAML vers les propriétés PHP car je veux autoriser la syntaxe abrégée dans les fichiers de configuration. Par exemple, je veux abréger certains noms de propriété et être capable de taper quelque chose comme default: today, où "aujourd'hui" n'est pas interprété comme un littéral de chaîne mais plutôt transformé en l'horodatage actuel.

Étant donné que beaucoup de classes sont des sous-classes, je cherche une solution qui me permette en quelque sorte d '"hériter" de la logique de configuration de la superclasse.

Je veux éviter de modifier les classes existantes, mais je suis prêt à le faire si cela permet une solution plus simple. À la réflexion, je ne m'occupe pas vraiment de modifier les classes existantes; Je suis juste intéressé par la meilleure solution.

Comment créer au mieux des objets à partir de fichiers de configuration de cette manière?

Répondre

3

Vous pouvez prendre l'approche suivante:

Chacun de vos modèles de classes à population de la configuration fichier doit implémenter une interface avec, par exemple, une méthode fromArray($data). Au niveau supérieur, vous connaissez le type d'objet (un formulaire) que vous souhaitez créer. Cet objet est instancié et les données de votre fichier config sont passées à la méthode fromArray. L'objet parcourt ensuite les données de configuration et "sait" quoi faire avec chacune des entrées.

Pour chaque élément de la matrice 'fields', il peut ensuite transmettre les données aux objets enfants qui peuvent eux-mêmes traverser et gérer la configuration correctement (y compris des choses comme interpréter 'aujourd'hui' d'une manière spéciale pour tout champ qui accepte une date). Il suffit de séparer la responsabilité de créer un objet en méthodes spéciales qui savent comment gérer ce type d'objet.

+0

C'est en fait l'approche que j'ai utilisée jusqu'à présent, et ça marche mieux que je ne le pensais quand j'ai écrit la question. Je ne sais toujours pas comment gérer l'héritage avec, cependant: Disons que j'ai une classe 'Checkbox' qui étend la classe' Field' et je veux que 'Checkbox' soit lu de la même manière que' Field' sauf pour un peu de nouvelles propriétés (ou différentes). Puisque la méthode 'fromArray' de la superclasse retourne un objet de cette classe particulière (' Field'), je ne peux pas simplement appeler 'parent :: fromArray' dans la sous-classe. Des idées sur la façon de gérer l'héritage? – Jakob

+0

difficile - vous n'auriez pas ce problème si fromArray n'était pas une méthode statique. Dans ce cas, vous devez instancier l'objet (Case à cocher) et utiliser fromArray pour le laisser se configurer. –

1

La première chose que je ferais serait de voir si cette roue avait déjà été inventé par someone- qui pourrait consister à examiner quelques-unes des suggestions ORM proposées ici: Good PHP ORM Library?

Edit: Ou peut-être plus utilement ce cas en regardant YAML Symfony: http://components.symfony-project.org/yaml/ - cela vous permet également d'intégrer PHP dans votre fichier de configuration, ce qui devrait également contourner les noms des champs raccourcis. Je ne vais pas entrer dans les détails de la mise en œuvre des choses vous-même au-delà parce qu'il y a beaucoup de façons différentes de le faire et de ne pas les avoir mises en place moi-même je ne veux pas vous tromper, mais je vais suggérer que si vous utilisez une syntaxe abrégée comme ça, vous voulez un moyen de marquer qu'il s'agit d'une syntaxe abrégée - codage pour default: today est beaucoup plus susceptible d'être sujettes aux erreurs que default : %%today%% ou un autre balisage plus spécialisé.

+0

Les ORM ne sont-ils pas simplement utilisés pour mapper des tables dans des bases de données relationnelles vers des classes POO? – Jakob

+0

C'est là qu'ils ont commencé, certes, mais je suis à peu près sûr que les bibliothèques ORM plus courantes comme la famille Hibernate facilitent aussi la sérialisation xml des données d'objets. Vous me doutez moi maintenant, cependant. Peut-être que je vais juste devenir sénile. – glenatron

0

Écrivez votre configuration en PHP.

$ContactConfig=array(
    $title='Contact', 
    $fields=array(
    'message'=>array(
     'type'=>'text', 
     'required'=>true 
    ), 
    'topic'=>array(
     'type'=>'dropdown', 
     'options'=>array('HTML','CSS','PHP') 
    ) 
) 
); 
1

Je n'ai pas écrit moi-même beaucoup PHP, mais je pouvais voir quelque chose comme ce travail si vous rouliez votre propre avec l'aide de YAML de symfony. Vous pouvez utiliser la classe PHP Reflection pour obtenir toutes les propriétés d'un objet et de sous-objets, puis utiliser le code YAML Symfony pour mapper YAML à un tableau, puis mapper le tableau aux propriétés. Dans votre code qui mappe le tableau aux propriétés de vos objets PHP, vous pouvez rechercher vos objets spéciaux comme "aujourd'hui" et leur faire faire des choses spéciales.

Vous aurez peut-être besoin d'un moyen de marquer les propriétés pour réagir d'une certaine manière aux différentes entrées. Je ne sais pas si c'est possible en PHP, mais en .NET, vous pouvez marquer les propriétés avec une classe Attribute pour permettre aux propriétés de faire des choses spéciales.

0

Écrivez un générateur de code PHP qui convertit essentiellement la config YAML en code PHP. Quand vous le faites de cette façon, un cache d'opcode (APC, eAccelerator, XCache, etc.) rendra le script plus efficace à l'exécution, au lieu que PHP ait à interpréter le fichier YAML chaque fois qu'il est chargé.

Questions connexes