DEV SF2 RAPIDE 
AVEC UN FRAMEWORK DE 
CONTENU
VOTRE DÉVOUÉ 
Bertrand Dunogier (@bdunogier) 
Ingénieur lead extensibilité 
eZ Systems, 
eZ Publish, 
http://ez.no 
http://github.com/ezpublish-community
POURQUOI DU DEV 
RAPIDE ? 
ET POURQUOI LE WEB D'ABORD ?
"CONTENT IS KING" 
"Content is where I expect much of the real 
money will be made on the Internet, just as it was 
in broadcasting" 
Bill Gates, 1996
"640K ought to be enough for anybody" 
Bill Gates, jamais
ET LES CMS ?
LE WEB CHANGE...
HEUREUSEMENT QUE...
MAIS ET MON CMS ?
PHP AUSSI A CHANGÉ
FONDAMENTAUX 
LE CONTENU 
Versions - Sécurité - Modèle flexible - Sémantique - i18n
S'INTÉGRER 
ET NON 
S'IMPOSER 
composer create-project symfony/framework-standard-edition my_project 
cd my_project 
composer require ezsystems/ezpublish-kernel
INTÉGRER 
ET NON 
RÉINVENTER 
devenir un élément d'un ensemble et non une fin en soi. 
composer require white-october/pagerfanta-bundle 1.0.* 
composer require whiteoctober/breadcrumbs-bundle ~1.0.1 
...
DE CMS 
À 
CONTENT FRAMEWORK
DU CONCRET
EZ PUBLISH 
DOMAIN LANGUAGE
REPOSITORY
CONTENT TYPE 
Ensemble nommé de FIELD DEFINITION. 
article, communiqué de presse, image, film...
FIELD DEFINITION 
Champ nommé référençant un FIELD TYPE. 
titre, fichier, réalisateur, année de sortie, affiche, diamètre... 
Traduisible ou non, a ses options propres
FIELD TYPE 
Plus petite entité de stockage de données. A ses propres 
templates d'affichage et d'édition. 
ligne de texte, texte riche, relation, adresse email, localisation, case à 
cocher...
CONTENT 
Une instance d'un CONTENT TYPE. 
Composé de une ou plusieurs VERSION, dont 0..1 publiée.
VERSION 
Ensemble de FIELD correspondant aux DEFINITION du 
CONTENT TYPE. 
Peut avoir 1 à N langues
LOCATION 
Un emplacement d'un CONTENT dans l'arbre de contenu.
CONTEXTE D'EXÉCUTION 
LE SITEACCESS 
Niveau supplémentaire de paramétrage, contextuel aux 
requêtes. 
ezpublish: 
siteaccess: 
default_siteaccess: main_site 
list: 
- site_fr 
- site_en 
match: 
MapHost: 
site.com: site_en 
site.fr: site_fr 
# m.site.com: mobile_site_en
AFFICHER DU CONTENU
ROUTES DYNAMIQUES 
- Root location 
- Articles [dossier] 
- Technologie (fr) ou Technology (en) [catégorie] 
- Le contenu, simplement [article, location #123] 
http://site.fr/Articles/Technologie/Le-contenu-simplement 
http://site.com/Articles/Technology/Content-made-simple 
http://site.com/Articles/Technology/Kontentsu-o-kantan-ni 
seront dynamiquement routés vers 
controller( 
"ez_content:viewLocation", 
{"locationId": 123, "viewType": "full"} 
)
SUB-REQUEST 
{{ render( 
controller( 
"ez_content:viewLocation", 
{"locationId": 123, "viewType": "full"} 
) 
) }}
CHOIX AUTOMATIQUE 
DU TEMPLATE 
ezpublish: 
default: 
location_view: 
block: 
article: 
template: "AcmeBundle:full:article.html.twig" 
match: 
IdentifierContentType: [article]
OU DU CONTRÔLEUR 
ezpublish: 
mobile_site: 
content_view: 
full: 
article: 
template: "AcmeBundle:full:article.html.twig" 
match: 
IdentifierContentType: [article] 
controller: AcmeBundle:Default:viewLocation
FONCTIONS TWIG 
Nom d'un CONTENT dans la langue en cours 
{{ ez_content_name(content) }} 
Valeur du FIELD body en allemand 
{{ ez_field_value(content, 'body', 'ger-DE' ) }} 
Rendu HTML du FIELD titre, via son template 
{{ ez_render_field(content, 'titre') }} 
Tester si le FIELD titre est vide 
{{ ez_is_field_empty(content, 'titre') }}
API DU REPOSITORY
PHP 
SERVICES 
ContentService, LocationService, SectionService, UserService, 
SearchService... 
VALUE OBJECTS 
Content, ContentCreateStruct, User, UrlAlias, SearchHit...
// charger 
$contentService = $container->get( 'ezpublish.api.service.content' ); 
$content = $contentService->loadContent( 42 ); 
// créer 
$struct = $contentService->newContentCreateStruct( 
$contentTypeService->loadContentType( 'article' ) 
); 
$struct->fields['titre']['fre-FR'] = 'Le contenu, simplement'; 
$struct->fields['titre']['eng-GB'] = 'Content made simple'; 
$struct->fields['titre']['jpn-JP'] = 'コンテンツ、ちょうど'; 
$content = $contentService->createContent( $struct ); 
$contentService->publishVersion( $content, 1 );
REST 
HTTP/1.1 GET /api/ezp/v2/content/objects/64 
Host: site.com 
Accept: application/vnd.ez.api.Content+json 
HTTP/1.1 DELETE /api/ezp/v2/content/objects/64/versions/1 
Host: site.com
GESTION UTILISATEURS 
Multi-utilisateurs, basé sur des rôles, extensible 
(FOSUserBundle)
CONTENU RICHE 
Editeur XML, transformation XSLT, format de saisie extensible
CACHE HTTP 
CONTEXTUEL 
$response->headers->set( 'X-Location-Id', $locationId ); 
$response->setVary( 'X-User-Hash' );
INTEGRATION 
DBAL, PagerFanta, FOSUserBundle...
EXTENSIBILITÉ 
Field Types, storage engines
ET L'INTERFACE ?
ON Y TRAVAILLE 
(Avec YUI...)
FIN 
DES QUESTIONS ? 
@bdunogier http://github.com/bdunogier 
http://joind.in/talk/view/11958

Dev Symfony2 rapide avec un framework de contenu

  • 1.
    DEV SF2 RAPIDE AVEC UN FRAMEWORK DE CONTENU
  • 2.
    VOTRE DÉVOUÉ BertrandDunogier (@bdunogier) Ingénieur lead extensibilité eZ Systems, eZ Publish, http://ez.no http://github.com/ezpublish-community
  • 3.
    POURQUOI DU DEV RAPIDE ? ET POURQUOI LE WEB D'ABORD ?
  • 4.
    "CONTENT IS KING" "Content is where I expect much of the real money will be made on the Internet, just as it was in broadcasting" Bill Gates, 1996
  • 5.
    "640K ought tobe enough for anybody" Bill Gates, jamais
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
    PHP AUSSI ACHANGÉ
  • 11.
    FONDAMENTAUX LE CONTENU Versions - Sécurité - Modèle flexible - Sémantique - i18n
  • 12.
    S'INTÉGRER ET NON S'IMPOSER composer create-project symfony/framework-standard-edition my_project cd my_project composer require ezsystems/ezpublish-kernel
  • 13.
    INTÉGRER ET NON RÉINVENTER devenir un élément d'un ensemble et non une fin en soi. composer require white-october/pagerfanta-bundle 1.0.* composer require whiteoctober/breadcrumbs-bundle ~1.0.1 ...
  • 14.
    DE CMS À CONTENT FRAMEWORK
  • 15.
  • 16.
  • 17.
  • 18.
    CONTENT TYPE Ensemblenommé de FIELD DEFINITION. article, communiqué de presse, image, film...
  • 19.
    FIELD DEFINITION Champnommé référençant un FIELD TYPE. titre, fichier, réalisateur, année de sortie, affiche, diamètre... Traduisible ou non, a ses options propres
  • 20.
    FIELD TYPE Pluspetite entité de stockage de données. A ses propres templates d'affichage et d'édition. ligne de texte, texte riche, relation, adresse email, localisation, case à cocher...
  • 21.
    CONTENT Une instanced'un CONTENT TYPE. Composé de une ou plusieurs VERSION, dont 0..1 publiée.
  • 22.
    VERSION Ensemble deFIELD correspondant aux DEFINITION du CONTENT TYPE. Peut avoir 1 à N langues
  • 23.
    LOCATION Un emplacementd'un CONTENT dans l'arbre de contenu.
  • 24.
    CONTEXTE D'EXÉCUTION LESITEACCESS Niveau supplémentaire de paramétrage, contextuel aux requêtes. ezpublish: siteaccess: default_siteaccess: main_site list: - site_fr - site_en match: MapHost: site.com: site_en site.fr: site_fr # m.site.com: mobile_site_en
  • 25.
  • 26.
    ROUTES DYNAMIQUES -Root location - Articles [dossier] - Technologie (fr) ou Technology (en) [catégorie] - Le contenu, simplement [article, location #123] http://site.fr/Articles/Technologie/Le-contenu-simplement http://site.com/Articles/Technology/Content-made-simple http://site.com/Articles/Technology/Kontentsu-o-kantan-ni seront dynamiquement routés vers controller( "ez_content:viewLocation", {"locationId": 123, "viewType": "full"} )
  • 27.
    SUB-REQUEST {{ render( controller( "ez_content:viewLocation", {"locationId": 123, "viewType": "full"} ) ) }}
  • 28.
    CHOIX AUTOMATIQUE DUTEMPLATE ezpublish: default: location_view: block: article: template: "AcmeBundle:full:article.html.twig" match: IdentifierContentType: [article]
  • 29.
    OU DU CONTRÔLEUR ezpublish: mobile_site: content_view: full: article: template: "AcmeBundle:full:article.html.twig" match: IdentifierContentType: [article] controller: AcmeBundle:Default:viewLocation
  • 30.
    FONCTIONS TWIG Nomd'un CONTENT dans la langue en cours {{ ez_content_name(content) }} Valeur du FIELD body en allemand {{ ez_field_value(content, 'body', 'ger-DE' ) }} Rendu HTML du FIELD titre, via son template {{ ez_render_field(content, 'titre') }} Tester si le FIELD titre est vide {{ ez_is_field_empty(content, 'titre') }}
  • 31.
  • 32.
    PHP SERVICES ContentService,LocationService, SectionService, UserService, SearchService... VALUE OBJECTS Content, ContentCreateStruct, User, UrlAlias, SearchHit...
  • 33.
    // charger $contentService= $container->get( 'ezpublish.api.service.content' ); $content = $contentService->loadContent( 42 ); // créer $struct = $contentService->newContentCreateStruct( $contentTypeService->loadContentType( 'article' ) ); $struct->fields['titre']['fre-FR'] = 'Le contenu, simplement'; $struct->fields['titre']['eng-GB'] = 'Content made simple'; $struct->fields['titre']['jpn-JP'] = 'コンテンツ、ちょうど'; $content = $contentService->createContent( $struct ); $contentService->publishVersion( $content, 1 );
  • 34.
    REST HTTP/1.1 GET/api/ezp/v2/content/objects/64 Host: site.com Accept: application/vnd.ez.api.Content+json HTTP/1.1 DELETE /api/ezp/v2/content/objects/64/versions/1 Host: site.com
  • 35.
    GESTION UTILISATEURS Multi-utilisateurs,basé sur des rôles, extensible (FOSUserBundle)
  • 36.
    CONTENU RICHE EditeurXML, transformation XSLT, format de saisie extensible
  • 37.
    CACHE HTTP CONTEXTUEL $response->headers->set( 'X-Location-Id', $locationId ); $response->setVary( 'X-User-Hash' );
  • 38.
  • 39.
  • 40.
  • 41.
    ON Y TRAVAILLE (Avec YUI...)
  • 42.
    FIN DES QUESTIONS? @bdunogier http://github.com/bdunogier http://joind.in/talk/view/11958