Cette section expliquera rapidement aux débutants le fonctionnement du frontend Typo3, ce que sont les gabarits, les “content objects”, une maquette HTML. Si vous connaissez bien ces bases, vous pouvez sauter cette section et aller directement à la suivante : “Intégration d'une maquette HTML”. Cependant vous devrez le dummy-package et y créer quelques pages. Ceci est expliqué dans cette section.
Niveau et pré requis :
Public: Tous les développeurs débutant en Typo3 indépendamment de leurs compétences dans d'autres domaines.
Certaines parties font référence à des technologies comme SQL, HTML, CSS et PHP. Le contenu est généralement un peu technique puisqu'il traitera de l'installation du dummy-package et expliquera les bases du moteur de templates de Typo3.
Afin de débuter rapidement, nous allons installer une structure vide et une base de données pour Typo3. La meilleur façon de procéder est d'utiliser le “dummy-package”. Un “package” contient les sources générales de Typo3 plus des fichiers pour un site local et éventuellement un contenu de base de données, l'ensemble forme un site web Typo3 complet destiné à une utilisation particulière. Dans le cas du “dummy-package”, le site web sera vide, cependant il sera particulièrement utile pour débuter un nouveau projet.
Donc, prenez le dummy-package et installez-le sur votre serveur. Après l'avoir dézippé, ouvrez la page index.php dans un navigateur et vous laissez vous guidez par les différentes étapes de l'assistant d'installation.
Entrez les information concernant la base de données :
Créer une nouvelle base de données :
Importer la dummy database, "database.sql":
Aller sur le backend (interface d'administration):
Afin de suivre ces étapes, il est indispensable que le serveur Web puisse écrire dans le fichier localconf.php (vous serez avertis si tel n'est pas le cas) et devez disposer du nom de l'utilisateur et de son mot de passe pour la base de données.
La première chose à faire maintenant est de créer l'arborescence des pages (la structure du site) que nous allons utiliser dans ce tutoriel. Une bonne structure de page doit avoir au moins 2 niveaux. Néanmoins, nous devons dans touts les cas commencer par une page racine :
Entrez un titre de page, démasquer la page (décochez “Hide Page”) et enregistrez la :
Vous pourriez procéder de cette manière pour créer l'ensemble de vos pages, cependant il existe un assistant qui vous facilitera la tâche. Allez dans le module “Functions”, sélectionnez les assistants (menu déroulant à droite : “wizards”) puis l'assistant “Create Multiple Pages”. Entrez plusieurs titres de pages puis validez avec le bouton “Create Page”.
Attention, l'assistant “Create Multiple Pages” impose que l'extension “wizard_crpages” soit installée et activée !
Vous devriez maintenant disposer d'une arborescence de pages comme suit :
Maintenant créez quelques pages supplémentaires afin d'obtenir ceci :
Cliquez sur une icône de page et sélectionner “Show” :
Le résultat de la visualisation (“Show”) de la page “Licensing” sera un écran ressemblant à ceci :
La page “Licensing” a l'identifiant (uid=5) et est visualisé en ajoutant le paramètre “id=5” à l'appel de la page index.php dans le Frontend.
Le message affiché est “No template found”. Ceci signifie que le moteur de frontend n'a pu trouver aucune maquette dans la rootline (la chaîne de page de la page actuelle (id=5) à la page racine du site). Ceci demande quelques explications. Typo3 est un CMS multi-site. Cela signifie que vous pouvez avoir plusieurs sites hébergés dans une même arborescence (une même structure) de pages. Chaque site dans cette arborescence doit avoir une page racine (root page). La caractéristique de root page est positionné dans la maquette de la page racine en cochant la case «Rootlevel ». Lorsque la valeur Rootlevel est vraie pour une page, cela signifie «A partir d'ici et en dessous, commence un nouveau site Web » .
L'expression root line est parfois appelé le chemin de la page. Supposons que la page "Licence A" dans mon arborescence à le chemin suivant : " TYPO3 > Root page > Licensing > License A ". Si nous envoyons l'id de la page "Licence A"au script index.php, le moteur de template cherchera dans le chemin (rootline) depuis la page "licence A" jusqu'à la page racine (Root Page) pour un contenu de type Gabarit. C'est ce gabarit qui décidera comment toute cette branche de l'arborescence sera affichée.
Créer un garariat
Nous allons maintenant créer un contenu de type Gabarit dans la page "Root page". Le plus simple est d'utiliser le module "Template".
L'écran suivant nous montre un vue du module "Template". Vous utiliserez cet écran pour modifier le gabarit par la suite :
Regardez maintenant la page "Root page" en utilisant le module "List" :
Vous voyez qu'un contenu de type "Template" ("Gabariat dans l'interface FR") a été créé dans la page "Root page".
Ce gabarit contient des informations de base pour le moteur de front end comme le rendu à effectuer pour le site web commençant sur cette page, quelles fonctionnalités sont activées, avec quels paramètres ... Un gabarit est toujours nécessaire pour commencer un site Typo3. Vous pourrez par la suite décider ce que le gabarit contrôlera dans votre site. Vous pourriez parfaitement programmer l'ensemble de votre site depuis le gabarit, vous pourriez également demander à la maquette d'appeler immédiatement un script PHP personnel qui chercherait et afficherait l'ensemble du contenu de la page (en utilisant par exemple du XML /XSLT, d'autres bases de données ... à votre convenance). Vous pourriez également mélanger les 2 approches afin de tirer le meilleur des 2 solutions. C'est cette approche qui sera utilisée dans ce tutoriel.
En examinant le contenu de la maquette, on remarque plusieurs champs intéressants.
Le champs "Template title" est simplement le titre de la template. Il n'est affiché nulle part.
Le champ "Website title" sera le préfixe utilisé devant le titre de la page et affiché entre les tags <title>.Par exemple, si le titre du site est "Mon site", la page "Ma page" aura pour titre (affiché dans la barre de navigation et dans le tag HTML <title> : "Mon site :: Ma page") .
Dans le champ Setup, vous entrerez les instructions de configuration du moteur de front-end. Ces instructions sont décrites dans une structure hiérarchique définie en utilisant la syntaxe TypoScript. C'est pour cette raison que les gabarit sont souvent appelés "TypoScript templates".
Les cases "Clear constants" et "Clear setup" signifient que le TypoScript ne sera pas hérité des pages parentes (situées au dessus, plus près de la racine). Ces cases devraient être systématiquement cochées pour les gabarit servant de maquette principales pour un nouveau site web (Rootlevel).
La case "Rootlevel" signifie simplement : "Débutes un nouveau site web à partir de cette page".
Revenons à la page "Licensing":
Différentes choses sont apparaues. Voici ce qu'il s'est passé :
Appelle la page avec l'uid "5" (étape #1)
Sélectionne le premier gabarit contenu dans cette page (pid=5); Pas de gabarit dans cette page = pas de résultat !
Comme il n'y a pas de gabarit dans la page d'uid "5", vérifie la page précédente dans la root line.... (#2)
La page précédente (parente de uid=5) est la page "Root Page" (uid=1). Dans cette page trouve le premier gabarit. Un gabarit (au moins) est présent !
Puisque nous avons un gabarit dans la page uid=1, vérifie que la case "Rootlevel" de ce gabarit est coché
La case "Rootlevel" est effectivement cochée, le gabarit signale un début de site donc :
Analyse la configuration Typoscript décrite dans le champ Setup.
Commence l'exécution des instructions du champ Setup.
Au sein d'un gabarit, le principal point d'intérêt est le champ "Setup". Dans ce champ on trouvera un ensemble d'instructions qui détermineront ce qui se passera lorsque nous visualiserons cette page dans le front-end.
Le meilleur moyen d'éditer ce champ est par le module Template et utilisant la vue Info/Modifiy :
Cliquez sur l'icône "edit" :
Quelques explications :
L'objet PAGE (#1)
Nous commençons par définir un objet de premier niveau [appelé Toplevel Object" (TLO)]. Le type d'objet est "PAGE" (vous pouvez également définir un objet de type "FRAMESET" -cf le manuel de référence de TypoScript : TSRef-). A lieu de "page" pour nommer d'objet, il est possible d'utiliser un autre nom à l'exception des mots réservés aux TLO (voir TSRef). Comme propriété de notre objet page nous définissons la propriété obligatoire "typeNum" en lui affectant la valeur 0 (zéro).
Cela signifie que l'objet de premier niveau "page" sera maintenant l'objet par défaut acceptant les requête pour l'ensemble des pages et sous-pages de l'arborescence dont notre gabarit signale le début d'un nouveau site.
Nous allons maintenant donner à notre objet page des instructions sur ce qu'il doit faire. Nous allons pour cela consulter l'ensemble des propriétés possibles pour un objet de type "PAGE". Certaines de ces propriétés sont des méta-propriétés comme "config" ou "includeLibs", d'autres sont des propriétés indiquant quel code HTML l'objet page doit produire.
L'ensemble des propriétés les plus significatives des objets PAGE est représenté par l'ensemble des content objects (cObjects). Chacun de ces cObjects peut produire une chaîne HTML dont l'assemblage produira le corps de la page web (entre <body> et </body>). Ces cObjects sont regroupés dans un tableau numérique hiérarchisé.
L'objet Content (#2)
Dans l'exemple ci-dessus, un objet très simple est défini -de type TEXT-. Il porte l'index "10" dans le tableau hiérarchique des objets de contenu (ie. dans l'arborescence des cOjects de page). Ce cObject a sa propriété "value" positionnée à "HELLO WORLD !". Cela a pour conséquence que le contenu généré par cet objet sera "HELLO WORLD !" et le code HTML de la page générée sera :
Vous trouverez l'ensemble des propriétés du cObject TEXT ici.
Cette section présentera quelques exemples supplémentaires sur les PAGE et cObjects de manière à vous aider à comprendre le concept pleinement. La compréhension de ce point vous permettra de comprendre les "TypoScript templates" aux structures plus complexes.
Deux cObjects?
Que se passe-t-il si nous ajoutons un autre cObjetc ?
# Default PAGE object:
page = PAGE
page.typeNum = 0
# Content object one:
page.10 = TEXT
page.10.value = HELLO WORLD!
# Content object two:
page.20 = TEXT
page.20.value = HELLO UNIVERSE!
(Notez que les lignes débutant par "#" ou "/" sont des commentaires.)
Sortie :
<body bgcolor="#FFFFFF">
HELLO WORLD!HELLO UNIVERSE!
</body>
Donc logiquement, les objets peuvent être concaténés, additionnés les uns aux autres.
Changer l'ordre ?
Que se passe-t-il si l'ordre des définitions est modifié ?
# Default PAGE object:
page = PAGE
page.typeNum = 0
# Content object two:
page.20 = TEXT
page.20.value = HELLO UNIVERSE!
# Content object one:
page.10 = TEXT
page.10.value = HELLO WORLD!
Sortie :
<body bgcolor="#FFFFFF">
HELLO WORLD!HELLO UNIVERSE!
</body>
Le résultat est le même. L'ordre de génération dépend en fait de l'index dans le tableau des cObjects (10,20,30 ...).
Contenu dynamique ?
Comment insérer un cObject TEXT renvoyant le titre de la page ?
Il faut consulter le "Typoscript Reference" (TSRef) afin de savoir si le cObject TEXT peut accepter une propriété permettant d'afficher cette information. Outre la propriété "value", il existe au même niveau les propriétés "stdWrap" qui peuvent être utilisées pour récupérer des données et les traiter automatiquement.
Puisque le rendu du cObjet TEXT est effectué au sein de l'objet PAGE, le current record (l'enregistrement courant, celui dont les données seront analysées) sera l'enregistrement de la page courante (table pages de la base de données). En spécifiant un champ au moyen de la propriété "field" de stdWrap, on récupérera son contenu pour la page courante. Par exemple, le champ "title" contient le nom de la page. Bien évidemment ceci suppose de savoir quels sont les champs contenus dans la table page !
Exemple :
# Default PAGE object:
page = PAGE
page.typeNum = 0
# Content object outputting current page title:
page.10 = TEXT
page.10.field = title
Sortie HTML :
<body bgcolor="#FFFFFF">
Licensing
</body>
Comme nous sommes sur la page "Licensing", c'est ce titre qui sera affiché (objet page.10)
Propriétés stdWrap :
Maintenant que nous savons utiliser la propriété "stdWrap", nous allons allons voir comment l'encapsuler , lui appliquer divers traitements ...
# Default PAGE object:
page = PAGE
page.typeNum = 0
# Content object outputting current page title:
page.10 = TEXT
page.10 {field = title
crop = 8 | ...
case = upper
wrap = This is the truncated page title: <b> | </b>
}
(Notez le changement de formatage du TypoScript afin que les propriétés soient incluses dans des accolades. Cette syntaxe permet d'affecter plus facilement des plusieurs propriétés au même objet ou niveau. Le résultat final est le même qu'en préfixant toutes les propriétés par le chemin complet de l'objet : "page.10.").
Résultat :
<body bgcolor="#FFFFFF">
This is the truncated page title: <b>LICENSIN...</b>
</body>
Notez que la chaîne d'encapsulation (wrap = This is the truncated page title: <b> | </b>) a été ajoutée de chaque coté du titre et que celui-ci est passé en majuscules (uppercase) et à été tronqué à 8 lettres en ajoutant "..." à la fin !
Nous aurions pu obtenir le même résultat en utilisant un autre cObjetc : "HTML". L'unique différence est que toutes les propriétés stdWrap de ce type d'objet sont des sous propriétés de "value" et non des propriétés de l'objet lui même :
# Default PAGE object:
page = PAGE
page.typeNum = 0
# Content object outputting current page title:
page.10 = HTML
page.10.value {field = title
crop = 8 | ...
case = upper
wrap = This is the truncated page title: <b> | </b>
}
Le choix entre l'utilisation de cObjects HTML ou TEXT est une question de goûts personnels.
Contenus depuis des scripts PHP
Vous pouvez aisément insérer des scripts PHP si vous le souhaitez. En fait c'est même recommandé si vous souhaitez obtenir des résultats conditionnels dont les clauses dépassent les limites du TypoScript. Les cObjects et leurs propriétés ne disposent pas de "programmation procédurale", ce sont justes des objets préprogrammés réagissant à des conditions spécifiques.
Dans les cas complexe, vous aurez besoin du cObject USER.
Tout d'abord, il faut créer le fichier PHP (dans fileadmin/userfunctions.php pour cet exemple) :
<?php
class user_functions {/**
* Multiplies the current page ID with $conf["factor"]
*/
function multiplyTest($content,$conf){$currentPageUid = $GLOBALS['TSFE']->id;
$factor = intval($conf['factor']);
return $currentPageUid * $factor;
}
}
?>
Ensuite, il faut configurer un cObjet de type USER afin d'appeler la fonction avec son unique paramètre : "factor" :
# Default PAGE object:
page = PAGE
page.typeNum = 0
page.includeLibs.some_random_id_string = fileadmin/userfunctions.php
page.config.admPanel = 1
# Content object outputting current page title:
page.10 = HTML
page.10.value = The page ID, {field:uid}, multiplied with 15 is:page.10.value.insertData = 1
page.10.value.wrap = <b> |</b> <br />
page.20 = USER
page.20.userFunc = user_functions->multiplyTest
page.20.factor = 15
Le résultat obtenu sera :
Comme vous le constatez, nous avons défini quelques "méta-propriétés" qui ne sont pas directement liées au contenu obtenu.
page.includeLibs.some_random_id_string = fileadmin/userfunctions.php
page.config.admPanel = 1
"includeLibs" est une propriété vous permettant de spécifier une liste de fichiers PHP (des bibliothèques de classes et de fonctions) à inclure AVANT la génération de la page. "config" correspond à de nombreuses options de configuration du comportement général de l'objet PAGE. Dans le cas présent, il ajoute un panneau d'administration en bas de page.
Prenez quelques minutes pour analyser attentivement l'exemple. Notez comment la propriété "factor" de l'objet USER est disponible dans la fonction PHP. Notez également comment la fonction PHP récupère l'ID de la page et comment l'"admin panel" est inclus. Cet exemple est assez instructif et vous devriez l'étudier jusqu'à en posséder une bonne maîtrise.
Le navigateur d'objets (Object Browser)
Le navigateur d'objets dans le module Template (gabarit en français) est un outil indispensable pour analyser la structure de vos maquettes :
Comme vous le voyez, le TypoScript est analysé en une arborescence d'objets très structuré. Cet outil vous permet de vérifiez que chaque propriété que vous avez saisie est correctement placée, voire d'éditer ces propriétés si la case "Enable object links" est cochée :
En revenant dans "Info/Modify" vous constatez que le champ Setup de la maquette a été modifié :
Le navigateur d'objets n'est cependant pas suffisamment intelligent pour retrouver et changer la ligne "page.20.factor = 15". Il insère simplement une nouvelle ligne à la fin du Setup qui écrasera les valeurs spécifiées auparavant. Vous pourrez supprimer la valeur inutile manuellement. Le navigateur d'objet fournit une manière sûre de spécifier les valeurs de propriétés puisque la totalité l'objet est reprise.
Poser ses conditions ?
Nous pourrions utiliser ce cas de figure pour illustrer les "conditions". Une condition très simple vérifiant le type du navigateur utilisé par le visiteur :
# Default PAGE object:
page = PAGE
page.typeNum = 0
page.includeLibs.some_random_id_string = fileadmin/userfunctions.php
page.config.admPanel = 1
# Content object outputting current page title:
page.10 = HTML
page.10.value = The page ID, {field:uid}, multiplied with 15 is:page.10.value.insertData = 1
page.10.value.wrap = <b> |</b> <br />
page.20 = USER
page.20.userFunc = user_functions->multiplyTest
page.20.factor = 15
[browser = msie]
page.20.factor = 30
page.10.value = The page ID, {field:uid}, multiplied with 30 is:
[global]
Dans Microsoft Internet Explorer la page ressemblera à ceci :
Dans les autres navigateurs (ici Mozilla) on obtiendra :
Le but n'est pas de vous donner un cours complet sur la manière de réaliser des maquettes en se fondant uniquement sur les cObjects. Ce manuel ne fait qu'utiliser les cObjects TEMPLATE, USER et HMENU cObjects en les combinant avec du TypoScript et des maquettes statiques afin d'arriver à nos fins. L'ouvrage de référence pour le TypoScript, les objets et leurs propriétés est TSref et si vous souhaitez plus d'exemples pratiques sur l'utilisation des différents types d'objets veuillez vous reporter au manuel TypoScript by Example.
Cependant je souhaiterais conclure sur deux points :
La signification de "&type="
Dans cet exemple, il n'y a pas qu'une seule page de définie. L'objet de premier niveau (TLO) "another_page" a également été définie comme un objet PAGE mais avec un "typeNum" à "1". Ceci signifie que l'objet "page" de type PAGE représente la page par défaut de tandis que l'objet PAGE "another_page" recevra les requêtes où le paramètre "&type=1" sera présent en plus du paramètre id.
page = PAGE
page.typeNum = 0
page.10 = TEXT
page.10.value = HELLO WORLD!
another_page = PAGE
another_page.typeNum = 1
another_page.10 = TEXT
another_page.10.value = HELLO UNIVERSE
Le résultat sera :
et l'arborescence d'objets :
Copier des objets
Il devient rapidement pratique de diviser son code TypoScript en blocs puis de les assembler à la fin de la maquette en les copiant aux positions adéquates. Cela peut même aller jusqu'à la séparation des blocs dans une hiérarchie de sous-maquettes (par inclusion) ou de maquettes statiques permettant la réutilisation du TypoScript (nous en reparlerons plus loin).
Cette possibilité repose sur une fonctionnalité de Typoscript permettant de copier une branche de l'arborescence d'objets dans une autre branche :
# Make temporary version of the first cObject:
temp.world = TEXT
temp.world.value = HELLO WORLD!
# Make temporary version of the second cObject:
temp.universe = TEXT
temp.universe.value = HELLO UNIVERSE!
# Default PAGE object:
page = PAGE
page.typeNum = 0
page.10 < temp.world
page.20 < temp.universe
Le résultat sera bien évidemment le suivant :
<body bgcolor="#FFFFFF">
HELLO WORLD!HELLO UNIVERSE!
</body>
Si vous regardez dans le navigateur d'objets, vous verrez que les objets "temp..." ont été copiés dans les branches "page.10" et "page.20". Cependant, nous aurions pu nous attendre à voir les TLO "temp..." dans l'arborescence. Ce n'est pas le cas. En effet, les TLO "temp." et "styles." sont retirés après l'analyse du TypoScript. Ils sont réservés à des objets temporaires disponibles pendant l'analyse du TypoScript mais pas après.
Si nous souhaitons conserver ces objets dans l'arborescence, il nous faut utiliser d'autres TLO :
# Make temporary version of the first cObject:
MY_TLO.world = TEXT
MY_TLO.world.value = HELLO WORLD!
# Make temporary version of the second cObject:
MY_TLO.universe = TEXT
MY_TLO.universe.value = HELLO UNIVERSE!
# Default PAGE object:
page = PAGE
page.typeNum = 0
page.10 < MY_TLO.world
page.20 < MY_TLO.universe
... et le TLO MY_TLO est correctement conservé :
Des Références et non plus des copies
Cela signifie également que nous pouvons créer une référence aux objets de MY_TLO. Établir des références à des cObjets suppose que ceux-ci existent dans la structure de la page après que l'analyse du TypoScript ai été effectuée (contrairement aux TLO "temp." et "style."). Nous pouvons donc réécrire le script comme suit :
# Make temporary version of the first cObject:
MY_TLO.world = TEXT
MY_TLO.world.value = HELLO WORLD!
# Make temporary version of the second cObject:
MY_TLO.universe = TEXT
MY_TLO.universe.value = HELLO UNIVERSE!
# Default PAGE object:
page = PAGE
page.typeNum = 0
page.10 =< MY_TLO.world
page.20 =< MY_TLO.universe
Le changement a l'air minime mais l'impact est très important puisque les objets ne sont plus copiés mais référencés :
Il y a plusieurs conséquences pratiques et des inconvénients à cette méthode. Cependant, l'avantage des référence est que le cObject défini à un point de l'arborescence peut être utilisé plusieurs fois par référence au sein de la structure de page, sans être dupliqué en mémoire. Il devient aisé également de modifier les propriétés de cet objet puisqu'il n'est pas nécessaire de retrouver tous les duplicata. Un exemple de ce problème est disponible à la fin de la partie 2 de ce tutoriel.
Note: Ce type de références n'est pas en soi une syntaxe TypoScript. C'est une fonctionnalité interne des cObjets. Par voie de conséquence, ces références ne peuvent être utilisées qu'en faisant référence à des cObjets à l'exclusion de tout type d'objets ou propriétés (sauf précisions).
Vider le Cache
Enfin vous devez vous rappeler que lorsque vous effectuez une modification via le module Template, la totalité du cache est vidé. Ceci est nécessaire puisque lorsque Typo3 analyse une maquette, la structure obtenue est stockée dans le cache afin de la rappeler plus rapidement lorsque la page sera rappelée. Ceci signifie également que les modifications effectuées directement dans l'enregistrement de la maquette en utilisant le module "List" ne vident pas le cache. Il est alors nécessaire de le faire en utilisant le lien en bas du menu gauche ou le menu déroulant en haut du formulaire de la maquette.
D'une manière générale, avant d'annoncer un bug face à un comportement inattendu, veuillez vider les caches !!