Jusqu’à présent, nous ne traitions que du contenu directement associé à une page, mais souvent, les pages sont composées de contenu stocké en dehors de la page et simplement importées dans la page par le biais d’une relation de données. Nous avons vu un peu de cela dans la leçon n ° 7 lorsque nous avons créé des $has_onerelations avec des Fileobjets. Toutes les informations sur le fichier sont stockées dans sa propre table et la page en fait simplement référence. Nous allons approfondir un peu les données relationnelles dans cette leçon en introduisant des relations plurielles avec $has_many.
Ce que nous allons couvrir
Création d’un objet de données générique
Mise en place d’une $has_manyrelation
Introduction au champ de grille
Travailler avec des données relationnelles sur le modèle
Création d’un objet de données générique
Un lien de téléchargement vers un nouveau modèle statique avec lequel nous allons travailler est joint à cette leçon regions-page.html. Notre concepteur a une fois de plus dépouillé tout le chrome et ne nous a laissé que la $Layoutsection. Nous allons donc, avant d’aller plus loin, télécharger ce fichier et migrer la page dans un modèle SilverStripe.
Copiez le contenu regions-page.htmldans un nouveau fichier, app/templates/SilverStripe/Lessons/Layout/RegionsPage.ss.
Ensuite, créez un nouveau type de page pour aller avec.
Exécutez a dev/build?flushet accédez au CMS. Modifiez la Regionspage à taper RegionsPage(sous l’onglet Paramètres). Retournez maintenant sur votre site Web et cliquez sur “Régions”. Vous devriez voir la nouvelle mise en page.
Bien entendu, tout cela est du contenu statique et nous devons commencer à le scinder en un élément modifiable dans le système de gestion de contenu. L’une des caractéristiques les plus apparentes de ce contenu est qu’il appartient clairement à une boucle. Nous voyons les régions Nord – Est , Sud – Est , etc., toutes avec la même structure et les mêmes données. Chacun contient un titre, une photo et une brève description.
Nous pourrions confier cela à l’éditeur de texte enrichi et créer tout ce contenu dans le $Contentbloc, mais ce serait plutôt moche. Notre éditeur de contenu devrait veiller à créer un balisage très spécifique, ce qui repousserait les limites de l’utilitaire WYSIWYG. Nous devons rendre chacune de ces régions modifiable en données structurées.
Commençons par créer le Regiontype de données. Comme nous l’avons vu dans la leçon précédente, les types de contenu génériques ne contenant pas de page devraient être des sous-classes SilverStripe\ORM\DataObject.
Comme décrit dans un didacticiel précédent, le $ownstableau est utilisé pour garantir que, lorsque les régions sont enregistrées, leurs images associées sont également publiées. Les fichiers et les images sont, par défaut, brouillons jusqu’à ce qu’ils soient explicitement publiés. Cela garantit qu’ils seront implicitement publiés avec la page qui les utilise.
Vous avez peut-être remarqué que notre getCMSFields()fonction est un peu différente. C’est parce que nous n’allons pas utiliser l’interface d’édition de page typique pour cet objet, nous n’allons donc pas avoir les onglets fournis avec les objets Page. Nous pourrions très facilement en créer un, mais comme ce type de données est si simple, nous le laisserons sous la forme d’une simple liste de champs et ajouterons tous les champs de formulaire au constructeur.
Mise en place d’une relation $has_many
Maintenant que nous avons notre Regionobjet autonome , nous devons le relier à notre RegionsPage. Notre conception nous a appris que la page peut contenir un nombre quelconque de régions. Nous utiliserons donc cette $has_manyrelation pour cela.
Cela suit la même convention que celle $has_oneutilisée dans une leçon précédente. La clé “Régions” est le nom arbitraire que nous allons donner à la relation. C’est la méthode que nous allons utiliser pour obtenir une liste de toutes les régions liées. La valeur est le nom de la classe liée.
Exécutez a dev/buildet voyez si vous obtenez des modifications de base de données. Si vous n’en voyez pas, c’est le résultat attendu! Pourquoi? Eh bien, nous n’avons pas encore terminé.
Réciproquant le $ has_many
$has_manyles relations sont un cas particulier, car elles doivent être réciproquement partagées par la classe associée. Alors que tous les RegionsPagea beaucoup Regions, il est vrai aussi que tout Regiona unRegionPage qui le contient. Les régions ne peuvent pas appartenir à plus d’une page de région.
Ceci est important, car la mutation de la base de données se produit au $has_oneniveau, pas le $has_many. Ce qui liera réellement ces deux objets, c’est un Regionobjet fournissant un, et un seul RegionsPageID. Faisons cette mise à jour maintenant.
En règle générale, une réciprocité has_onecomme celle-ci peut simplement être nommée d’après la classe parente.
Maintenant exécutons a dev/buildet voyons que nous obtenons un nouveau RegionsPageIDchamp.
Introduction à GridField
Notre $has_manyrelation est définie, avec un $has_onecôté opposé, et nous sommes prêts à commencer à la peupler avec des données. Pour cela, nous aurons besoin de l’un des chevaux de travail de l’interface CMS – GridField.
GridField est un champ de formulaire hautement configurable qui vous permet de gérer une table de données arbitraire. Dans son sens le plus primitif, vous pouvez considérer cela comme une abstraction d’une table de base de données, mais vous pouvez faire beaucoup plus avec cela. Pour gérer nos Regionobjets, nous souhaitons un onglet sur le site RegionsPagenous permettant de créer, lire, éditer et supprimer des Regionenregistrements associés .
Faisons la mise à jour suivante pour notre RegionsPageobjet.
//...useSilverStripe\Forms\GridField\GridField;useSilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;classRegionsPageextendsPage{privatestatic $has_many =['Regions'=>Region::class,];publicfunction getCMSFields(){
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Regions',GridField::create('Regions','Regions on this page',
$this->Regions(),GridFieldConfig_RecordEditor::create()));return $fields;}}
Le constructeur GridField
Jetons un coup d’oeil à la signature de l’argument pour GridField:
‘Régions’ : Nom obligatoire et arbitraire du champ GridField. Vous en aurez besoin si vous souhaitez effectuer des mises à jour de votre GridField après l’avoir ajouté à FieldList.
‘Régions sur cette page’ : Titre du champ GridField. Devrait être convivial.
$ this-> Regions () : il s’agit du composant le plus important de votre GridField. Il remplit la grille avec des données. Dans ce cas, nous utilisons la méthode magique créée par notre $has_manyrelation pour remplir la grille avec tous les enregistrements actuellement associés à la page.
GridFieldConfig_RecordEditor :: create () : C’est un peu plus complexe. Il crée un objet contenant un certain nombre d’ GridFieldComponentobjets, qui fournissent divers outils d’interface utilisateur à la grille, tels que la pagination, un bouton “ajouter”, des boutons de suppression / modification, etc. Ces GridFieldConfigobjets peuvent être configurés avec toute une variété de composants que vous aimez. , mais SilverStripe est livré avec quelques configurations courantes qui sont souvent utilisées. GridFieldConfig_RecordEditorest une excellente solution, car elle fournit toute l’interface utilisateur de base que vous attendez pour la gestion des données.
Ajout de versioning
À l’heure actuelle, toutes les modifications que nous apportons aux régions seront immédiatement consultées sur le site actif, car ils n’ont pas d’état publié / en projet. Commençons par ajouter un contrôle de version à ces enregistrements.
Tout d’abord, nous appliquons le DataExtension Versioned . Nous parlerons davantage des extensions dans un prochain tutoriel, mais pour l’instant, il suffit de comprendre que cette extension intègre des fonctionnalités dans la classe pour qu’elle prenne en charge le contrôle de version.
Exécutez a dev/build?flushet nous devrions voir de nouvelles tables créées.
Enfin, nous devons déclarer la propriété entre RegionsPageet Regionafin que les modifications apportées à la publication se répercutent d’un parent à l’autre et inversement.
Notez que nous n’avons pas besoin d’utiliser le nom de classe complet Region::class, dans la $ownsdéclaration. C’est parce que nous faisons référence à la relation, pas à la classe. La relation est déclarée comme Regionsdans le has_manytableau. Les entrées dans $ownspourraient tout aussi bien être des noms de méthodes, si vous vouliez déclarer la propriété dans un getter personnalisé.
Retournons dans le CMS et modifions notre page “Régions”. Voir que nous avons maintenant un onglet qui contient une grille. Essayez-le et ajoutez des enregistrements de test.
Configuration du GridField
Comme indiqué précédemment, GridFieldest hautement configurable. L’une des personnalisations les plus courantes que vous voudrez apporter à votre grille concerne les colonnes affichées. Dans ce cas, il y a seulement une poignée de champs, donc ne montrer que Title et ce Descriptionn’est pas si grave, mais vous pouvez imaginer que si le DataObject avait 10 champs distincts, nous voudrions probablement le resserrer un peu.
Dans notre cas, apportons une amélioration mineure et ajoutons simplement le Photochamp à notre liste. Par défaut, seuls les champs du $dbtableau sont inclus. Depuis Photoest dans le $has_one, nous devons l’inclure spécifiquement.
Définissons une $summary_fieldsvariable sur notre Regionobjet.
//...classRegionextendsDataObject{//... privatestatic $summary_fields =['Photo'=>'','Title'=>'Title of region','Description'=>'Short description'];//...}
Ce tableau mappe le nom du champ sur le nom de colonne lisible par l’homme. Nous allons laisser la photo parler d’elle-même et laisser son en-tête de colonne vide.
Comme nous avons modifié une variable statique privée, nous devons exécuter? Flush pour voir la mise à jour de la grille. De quoi ça a l’air? Assez mal, non? La photo n’est pas redimensionnée pour s’adapter à la grille.
Utiliser un getter personnalisé
Heureusement, $summary_fieldsaccepte plus que des noms de champs. Nous pouvons fournir n’importe quelle méthode publique sur notre DataObject en tant que valeur de colonne. Créons une méthode qui renvoie une photo redimensionnée.
Exécuter à ?flush nouveau et voir que notre grille a l’air beaucoup plus propre maintenant.
Nous aurions pu gagner beaucoup de temps en utilisant une méthode fournie Image par défaut par SilverStripe à tous les objets – CMSThumbnail(). Photo.CMSThumbnail aurait abouti à un résultat très similaire, sans le texte de repli (pas d’image) .
Champs traversants
Une autre fonctionnalité intéressante $summary_fields est que vous pouvez traverser des relations pour obtenir des champs étrangers, en utilisant une syntaxe séparée par des points. Supposons que nous voulions afficher le Filename champ sur la photo:
Ce type de syntaxe devient particulièrement utile lorsque vous formatez des dates ou que vous obtenez le titre d’un document associé $has_oneplutôt que de simplement afficher son ID numérique.
Ajout de versioning à GridField
Pour le moment, GridField ne nous offre rien en termes de publication. Tout ce que nous avons sont les boutons “Enregistrer” et “Supprimer”. Pour obtenir la gamme complète des actions de publication (“Enregistrer”, “Publier”, “Archiver”, etc.), nous devrons indiquer explicitement que l’ Region objet doit utiliser les extensions GridField versionnées. Pour l’activer, définissez versioned_gridfield_extensions sur true.
Travailler avec des données relationnelles sur le modèle
Maintenant que toutes nos données relationnelles sont en place, il est temps de les afficher sur le modèle. Cela devrait être assez simple. Commençons avecRegionsPage.ss
app / templates / Layout / RegionsPage.ss, ligne 9
<divclass="grid-style1 clearfix"><% loop $Regions %>
<divclass="item col-md-12"><!-- Set width to 4 columns for grid view mode only --><divclass="image image-large"><ahref="#"><spanclass="btn btn-default"><iclass="fa fa-file-o"></i> Read More</span></a>
$Photo.Fit(720,255)
</div><divclass="info-blog"><h3><ahref="#">$Title</a></h3><p>$Description</p></div></div><% end_loop %>
</div>
Notez que nous sautons les liens. Nous aborderons cela dans une prochaine leçon.
Dépôt de code à télécharger
Jusqu’à présent, nous ne traitions que du contenu directement associé à une page, mais souvent, les pages sont composées de contenu stocké en dehors de la page et simplement importées dans la page par le biais d’une relation de données. Nous avons vu un peu de cela dans la leçon n ° 7 lorsque nous avons créé des
$has_one
relations avec desFile
objets. Toutes les informations sur le fichier sont stockées dans sa propre table et la page en fait simplement référence. Nous allons approfondir un peu les données relationnelles dans cette leçon en introduisant des relations plurielles avec$has_many
.Ce que nous allons couvrir
$has_many
relationCréation d’un objet de données générique
Un lien de téléchargement vers un nouveau modèle statique avec lequel nous allons travailler est joint à cette leçon
regions-page.html
. Notre concepteur a une fois de plus dépouillé tout le chrome et ne nous a laissé que la$Layout
section. Nous allons donc, avant d’aller plus loin, télécharger ce fichier et migrer la page dans un modèle SilverStripe.Copiez le contenu
regions-page.html
dans un nouveau fichier,app/templates/SilverStripe/Lessons/Layout/RegionsPage.ss
.Ensuite, créez un nouveau type de page pour aller avec.
app / src / RegionsPage.php
app / src / RegionsPageController.php
Exécutez a
dev/build?flush
et accédez au CMS. Modifiez laRegions
page à taperRegionsPage
(sous l’onglet Paramètres). Retournez maintenant sur votre site Web et cliquez sur “Régions”. Vous devriez voir la nouvelle mise en page.Bien entendu, tout cela est du contenu statique et nous devons commencer à le scinder en un élément modifiable dans le système de gestion de contenu. L’une des caractéristiques les plus apparentes de ce contenu est qu’il appartient clairement à une boucle. Nous voyons les régions Nord – Est , Sud – Est , etc., toutes avec la même structure et les mêmes données. Chacun contient un titre, une photo et une brève description.
Nous pourrions confier cela à l’éditeur de texte enrichi et créer tout ce contenu dans le
$Content
bloc, mais ce serait plutôt moche. Notre éditeur de contenu devrait veiller à créer un balisage très spécifique, ce qui repousserait les limites de l’utilitaire WYSIWYG. Nous devons rendre chacune de ces régions modifiable en données structurées.Commençons par créer le
Region
type de données. Comme nous l’avons vu dans la leçon précédente, les types de contenu génériques ne contenant pas de page devraient être des sous-classesSilverStripe\ORM\DataObject
.app / src / Region.php
Comme décrit dans un didacticiel précédent, le
$owns
tableau est utilisé pour garantir que, lorsque les régions sont enregistrées, leurs images associées sont également publiées. Les fichiers et les images sont, par défaut, brouillons jusqu’à ce qu’ils soient explicitement publiés. Cela garantit qu’ils seront implicitement publiés avec la page qui les utilise.Vous avez peut-être remarqué que notre
getCMSFields()
fonction est un peu différente. C’est parce que nous n’allons pas utiliser l’interface d’édition de page typique pour cet objet, nous n’allons donc pas avoir les onglets fournis avec les objets Page. Nous pourrions très facilement en créer un, mais comme ce type de données est si simple, nous le laisserons sous la forme d’une simple liste de champs et ajouterons tous les champs de formulaire au constructeur.Mise en place d’une relation $has_many
Maintenant que nous avons notre
Region
objet autonome , nous devons le relier à notreRegionsPage
. Notre conception nous a appris que la page peut contenir un nombre quelconque de régions. Nous utiliserons donc cette$has_many
relation pour cela.app / src / RegionsPage.php
Cela suit la même convention que celle
$has_one
utilisée dans une leçon précédente. La clé “Régions” est le nom arbitraire que nous allons donner à la relation. C’est la méthode que nous allons utiliser pour obtenir une liste de toutes les régions liées. La valeur est le nom de la classe liée.Exécutez a
dev/build
et voyez si vous obtenez des modifications de base de données. Si vous n’en voyez pas, c’est le résultat attendu! Pourquoi? Eh bien, nous n’avons pas encore terminé.Réciproquant le $ has_many
$has_many
les relations sont un cas particulier, car elles doivent être réciproquement partagées par la classe associée. Alors que tous lesRegionsPage
a beaucoupRegions
, il est vrai aussi que toutRegion
a unRegionPage
qui le contient. Les régions ne peuvent pas appartenir à plus d’une page de région.Ceci est important, car la mutation de la base de données se produit au
$has_one
niveau, pas le$has_many
. Ce qui liera réellement ces deux objets, c’est unRegion
objet fournissant un, et un seulRegionsPageID
. Faisons cette mise à jour maintenant.app / src / Region.php
En règle générale, une réciprocité
has_one
comme celle-ci peut simplement être nommée d’après la classe parente.Maintenant exécutons a
dev/build
et voyons que nous obtenons un nouveauRegionsPageID
champ.Introduction à GridField
Notre
$has_many
relation est définie, avec un$has_one
côté opposé, et nous sommes prêts à commencer à la peupler avec des données. Pour cela, nous aurons besoin de l’un des chevaux de travail de l’interface CMS –GridField
.GridField est un champ de formulaire hautement configurable qui vous permet de gérer une table de données arbitraire. Dans son sens le plus primitif, vous pouvez considérer cela comme une abstraction d’une table de base de données, mais vous pouvez faire beaucoup plus avec cela. Pour gérer nos
Region
objets, nous souhaitons un onglet sur le siteRegionsPage
nous permettant de créer, lire, éditer et supprimer desRegion
enregistrements associés .Faisons la mise à jour suivante pour notre
RegionsPage
objet.Le constructeur GridField
Jetons un coup d’oeil à la signature de l’argument pour
GridField
:$has_many
relation pour remplir la grille avec tous les enregistrements actuellement associés à la page.GridFieldComponent
objets, qui fournissent divers outils d’interface utilisateur à la grille, tels que la pagination, un bouton “ajouter”, des boutons de suppression / modification, etc. CesGridFieldConfig
objets peuvent être configurés avec toute une variété de composants que vous aimez. , mais SilverStripe est livré avec quelques configurations courantes qui sont souvent utilisées.GridFieldConfig_RecordEditor
est une excellente solution, car elle fournit toute l’interface utilisateur de base que vous attendez pour la gestion des données.Ajout de versioning
À l’heure actuelle, toutes les modifications que nous apportons aux régions seront immédiatement consultées sur le site actif, car ils n’ont pas d’état publié / en projet. Commençons par ajouter un contrôle de version à ces enregistrements.
app / src /Region.php
Tout d’abord, nous appliquons le DataExtension
Versioned
. Nous parlerons davantage des extensions dans un prochain tutoriel, mais pour l’instant, il suffit de comprendre que cette extension intègre des fonctionnalités dans la classe pour qu’elle prenne en charge le contrôle de version.Exécutez a
dev/build?flush
et nous devrions voir de nouvelles tables créées.Enfin, nous devons déclarer la propriété entre
RegionsPage
etRegion
afin que les modifications apportées à la publication se répercutent d’un parent à l’autre et inversement.app / src / RegionsPage.php
Notez que nous n’avons pas besoin d’utiliser le nom de classe complet
Region::class
, dans la$owns
déclaration. C’est parce que nous faisons référence à la relation, pas à la classe. La relation est déclarée commeRegions
dans lehas_many
tableau. Les entrées dans$owns
pourraient tout aussi bien être des noms de méthodes, si vous vouliez déclarer la propriété dans un getter personnalisé.Retournons dans le CMS et modifions notre page “Régions”. Voir que nous avons maintenant un onglet qui contient une grille. Essayez-le et ajoutez des enregistrements de test.
Configuration du GridField
Comme indiqué précédemment,
GridField
est hautement configurable. L’une des personnalisations les plus courantes que vous voudrez apporter à votre grille concerne les colonnes affichées. Dans ce cas, il y a seulement une poignée de champs, donc ne montrer queTitle
et ceDescription
n’est pas si grave, mais vous pouvez imaginer que si le DataObject avait 10 champs distincts, nous voudrions probablement le resserrer un peu.Dans notre cas, apportons une amélioration mineure et ajoutons simplement le
Photo
champ à notre liste. Par défaut, seuls les champs du$db
tableau sont inclus. DepuisPhoto
est dans le$has_one
, nous devons l’inclure spécifiquement.Définissons une
$summary_fields
variable sur notreRegion
objet.Ce tableau mappe le nom du champ sur le nom de colonne lisible par l’homme. Nous allons laisser la photo parler d’elle-même et laisser son en-tête de colonne vide.
Comme nous avons modifié une variable statique privée, nous devons exécuter? Flush pour voir la mise à jour de la grille. De quoi ça a l’air? Assez mal, non? La photo n’est pas redimensionnée pour s’adapter à la grille.
Utiliser un getter personnalisé
Heureusement,
$summary_fields
accepte plus que des noms de champs. Nous pouvons fournir n’importe quelle méthode publique sur notre DataObject en tant que valeur de colonne. Créons une méthode qui renvoie une photo redimensionnée.Exécuter à
?flush
nouveau et voir que notre grille a l’air beaucoup plus propre maintenant.Nous aurions pu gagner beaucoup de temps en utilisant une méthode fournie
Image
par défaut par SilverStripe à tous les objets –CMSThumbnail()
.Photo.CMSThumbnail
aurait abouti à un résultat très similaire, sans le texte de repli (pas d’image) .Champs traversants
Une autre fonctionnalité intéressante
$summary_fields
est que vous pouvez traverser des relations pour obtenir des champs étrangers, en utilisant une syntaxe séparée par des points. Supposons que nous voulions afficher leFilename
champ sur la photo:Ce type de syntaxe devient particulièrement utile lorsque vous formatez des dates ou que vous obtenez le titre d’un document associé
$has_one
plutôt que de simplement afficher son ID numérique.Ajout de versioning à GridField
Pour le moment, GridField ne nous offre rien en termes de publication. Tout ce que nous avons sont les boutons “Enregistrer” et “Supprimer”. Pour obtenir la gamme complète des actions de publication (“Enregistrer”, “Publier”, “Archiver”, etc.), nous devrons indiquer explicitement que l’
Region
objet doit utiliser les extensions GridField versionnées. Pour l’activer, définissezversioned_gridfield_extensions
surtrue
.Travailler avec des données relationnelles sur le modèle
Maintenant que toutes nos données relationnelles sont en place, il est temps de les afficher sur le modèle. Cela devrait être assez simple. Commençons avec
RegionsPage.ss
app / templates / Layout / RegionsPage.ss, ligne 9
Notez que nous sautons les liens. Nous aborderons cela dans une prochaine leçon.