Développer avec le sylius resourcebundle
-
Upload
arnaud-langlade -
Category
Internet
-
view
1.025 -
download
3
Transcript of Développer avec le sylius resourcebundle
DÉVELOPPER AVEC LE SYLIUSRESOURCEBUNDLE
QUI SUIS-JE ?
Arnaud Langlade (@_aRn0D)
Développeur Symfony chez Clever Age
www.clever-age.com / @CleverAge
SYLIUS
Framework E-commerce créé par Paweł Jędrzejewski
Ensemble de bundles Symfony et composants PHP e-commerce
Sylius Starndard Edition
Quelques chiffres : ~200 contributeurs / ~1700 stars
SYLIUSRESOURCEBUNDLELe SyliusResourceBundle vous permet de gérer rapidement et simplement vos ressources et de les
exposer via API REST.
Il n'y a pas que des composants e-commerce dans Sylius !
GESTION DES RESSOURCES? Z'AVEZ DIS CRUD?
CRUD = Create, Read, Update, Delete
UN CRUD, COMMENT ÇA FONCTIONNE?
POURQUOI LA CRÉATION DE CE BUNDLE?Le back office de Sylius est composé d'énormement de CRUDsEviter la duplication de code parce que c'est mal!Développer plus vite en automatisant des tâches
UNE SOLUTION? RESOURCECONTROLLER?Création du ResourceController :
C'est un contrôleur génériquePlus de code, il est intialisé via une configurationIl étend the FOSRestController
Utilisation du EventDispatcher (répartiteur d'évènement) :
Il permet de personnaliser les actionsSolution plus flexible
QUELS SONT ORM/ODM SUPPORTÉS ?Doctrine ORM : Sylius l'utilise par défautDoctrine Phpcr-ODM : Sylius intègre le CMF pour gérer des contenusDoctrine Mongodb-ODMBientôt sûrement plus !
ATTENTION!Ce n'est pas un admin generator!
Il faut créer vos formulaires, vos templates et le routing (pour le moment!)
CRÉER SON CRUD EN QUELQUES MINUTES !Par exemple, créons un CRUD pour gérer des clients (customer).
CONFIGURONS NOS RESSOURCES sylius_resource: resources: myapp.customer: driver: doctrine/orm classes: model: AppBundle\Entity\Customer repository: Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository templates: WebBundle:Backend/Customer myapp.address: # ...
MAIS QUE SE PASSE T'IL ? $ php app/console container:debug | grep customer
myapp.manager.customer alias for "doctrine.orm.default_entity_manager"myapp.controller.customer container Sylius\Bundle\ResourceBundle\Controller\ResourceControllermyapp.repository.customer container Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository
$ php app/console container:debug parameters
sylius.config.classes "myapp.customer": ...
CONFIGURONS NOS RESSOURCES sylius_resource: resources: myapp.customer: driver: doctrine/orm classes: model: AppBundle\Entity\Customer controller: AppBundle\Controller\CustomerController repository: AppBundle\Repository\CustomerRepository templates: WebBundle:Backend/Customer
CRÉONS NOTRE MODÈLE # AppBundle\Entity\Customer.php;
/** * @ORM\Entity * @ORM\Table(name="customer") */class Customer /** * @ORM\Column(type="string", length=100) */ protected $firstName;
/** * @ORM\Column(type="string", length=100) */ protected $lastName;
CRÉONS NOTRE FORMULAIRE // AppBundle\Form\Type\CustomerType.php;
class CustomerType extends AbstractResourceType public function getName() return 'myapp_customer';
Le formulaire doit être défini en tant que servicePattern du nom de formulaire : nom-application_resourceAbstractResourceType permet de configurer le data_class et le validation_group
CRÉONS NOS TEMPLATES # create.html.twig ou update.html.twig #
<form method="POST" action="..."> form_widget(form) </form>
# show.html.twig #
<div> <p> customer.firstname </p> <p> customer.lastname </p></div>
# index.html.twig #
% for customer in customers % customer.fistname customer.lastname % endfor %
CONFIGURONS NOS ROUTES # app/routing.yml
myapp_customer_index: pattern: /customer defaults: _controller: myapp.controller.customer:indexAction
Pattern des clés des routes : nom-application_resource_actionNe pas oublier que les contrôleurs sont définis en tant que serviceActions : index, show, create, update, delete, moveUp, moveDown, revert ou updateState
ET PAF ! ÇA FAIT DES CHOCAPICS !Notre CRUD est prêt à l'emploi !! On crée notre API ?
EXPOSER SES CLIENTS VIA API RESTConfigurer le FOSRestBundle
# app/config.yml
fos_rest: format_listener: rules: path: '/', priorities: ['html', 'json'], fallback_format: html
Le ResourceController retourne le données dans le format souhaité
GET /customer/57 HTTP/1.1Host: myshop.comAccept: application/json
CONFIGURER LE SÉRIALISEUR # Resources/config/serializer/Entity.Customer.yml
AppBundle\Entity\Customer: exclusion_policy: ALL properties: firstName: expose: true type: string lastName: expose: true type: string relations: rel: address href: route: myapp_address_show parameters: id: expr(object.getAddress().getId())
HTTP/1.1 200 OKContentType: application/json;
"id": 2, "firstName": "Arnaud", "lastName": "Langlade", "_links": "self": "href": "/address/2"
C'EST TOUT ?Lionframe (Rapid RESTful API Development)Génération automatique des formulaires et du routing
PLUS DE FLEXIBILITÉ ?Le comportement des méthodes du ResourceController est configurable
CONFIGURER LES METHODES DU RESOURCECONTROLLERAjouter une entrée _sylius dans le tableau defaults des routes
# app/routing.yml
myapp_customer_create: defaults: _sylius: template: WebBundle:Backend/Customer:custom_create.html.twig
RÉDIRIGER L'UTILISATEUR # app/routing.yml
myapp_product_create: pattern: /new methods: [GET, POST] _controller: myapp.controller.product:createAction _sylius: redirect: myapp_product_index
# Ou
redirect: route: myapp_product_show parameters: name: resource.sku
RÉCUPÉRER DES DONNÉES DANS LA BDD # app/routing.yml
myapp_customer_index: pattern: / methods: [GET] defaults: _controller: myapp.controller.customer:indexAction _sylius: # $repository>findBy(["group" => 'my_group']) criteria: group: my_group
# $request>get('criteria') filterable: true
RÉCUPÉRER DES DONNÉES DANS LA BDD # app/routing.yml
myapp_customer_index: pattern: / methods: [GET] defaults: _controller: myapp.controller.customer:indexAction _sylius: # $repository>findByFilter($request>get('filter')) repository: method: findByFilter arguments: [$filter]
LISTER SES RESSOURCES # app/routing.yml
myapp_customer_index: pattern: / methods: [GET] defaults: _controller: myapp.controller.customer:indexAction _sylius: # Trie sorting: updatedAt: desc # Ou asc
# $request>get('sorting'); sortable: true
# Paginate paginate: 50
MOTEUR D'EXPRESSION # app/routing.yml
myapp_order_index: path: /orders methods: [GET] defaults: _controller: app.controller.order:indexAction _sylius: repository: # $repository>findOrderByCustomer([$customer]); method: findOrderByCustomer arguments: ["expr:service('security.context').getToken().getUser()"]
VOUS VOULEZ MUTUALISER VOTRE CODE ?
SYLIUS FONCTIONNE AVEC DES BUNDLESIls doivent être facilement étendablesIls peuvent supporter plusieurs "drivers" (ORM/ODM)Ils ne doivent être couplés les uns aux autres
LA CONFIGURATION SÉMANTIQUE customer_bundle: driver: doctrine/orm templates: customer: CustomerBundle:Backend/Customer address: ... validation_groups: customer: [myapp] address: ... classes: customer: model: Myapp\CustomerBundle\Model\Customer controller: Sylius\Bundle\ResourceBundle\Controller\ResourceController repository: Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository form: default: Myapp\CustomerBundle\Form\Type\CustomerType choice: Myapp\CustomerBundle\Form\Type\CustomerChoiceType address: ...
MAIS QUE SE PASSE T'IL? $ php app/console container:debug | grep customer
myapp.controller.customer container Sylius\Bundle\ResourceBundle\Controller\ResourceControllermyapp.manager.customer n/a alias for doctrine.orm.default_entity_managermyapp.repository.customer container Sylius\Bundle\ResourceBundle\Doctrine\ORMEntityRepositorymyapp.form.type.customer container myapp\CustomerBundle\Form\Type\CustomerType
$ php app/console container:debug parameters | grep customer
myapp.model.customer.class myapp\CustomerBundle\Model\Customermyapp.model.customer.class myapp\CustomerBundle\Model\Customermyapp.controller.customer.class Sylius\Bundle\ResourceBundle\Controller\ResourceControllermyapp.repository.customer.class Sylius\Bundle\ResourceBundle\Doctrine\ORMEntityRepositorymyapp.form.type.customer.class myapp\CustomerBundle\Form\Type\CustomerTypemyapp.validation_group.customer ["myapp"]myapp_customer.driver doctrine/orm
ETENDRE FACILEMENT VOTRE BUNDLEUtiliser l'injecteur de dépendences (Dependency Injector)Déclarer votre classe en tant mapped-superclass (évènement loadClassMetadata)
GÉRER PLUSIEURS DRIVERSCréer votre "Doctrine Mapping Driver"Fournir plusieurs implementations Doctrine pour un modèleVos documents et entités sont dans le même namespace
LIMITER LE COUPLAGE DE VOS BUNDLESUtiliser le Resolve Target Entity ListenerDéfinir des relations entre différentes entités sans les écrire en durIl ré-écrit les paramètres targetEntity dans le mapping de votre modèle
<! Resources/config/doctrine/order.xml >
<onetomany field="orders" targetentity="Sylius\Component\Order\Model\OrderInterface"> <! ... ></onetomany>
VOUS ÊTES ÉQUIPÉS POUR CONSTRUIRE VOS BUNDLES!
GO TO THE FUTURE!Refactoring de la SyliusResourceExtension
Rendre le système plus flexibleUniformiser la configuration
De nouveaux FormType ?Un datagrid ?
VENEZ CONTRIBUER!Merci à tous les contributeurs!N'hésister pas à nous soumettre vos PRs...... surtout si vous aimez écrire de la doc :D !
MERCI! QUESTIONS ?
Arnaud Langlade
Twiter @_aRn0D
Sylius : www.sylius.org