$30 off During Our Annual Pro Sale. View Details »

Immersion in the Sylius

Immersion in the Sylius

Slides from my first talk ever, presented at Symfony CAMP UA 2013.

Pawel Jedrzejewski

October 26, 2013
Tweet

More Decks by Pawel Jedrzejewski

Other Decks in Programming

Transcript

  1. Immersion in the Sylius
    Paweł Jędrzejewski

    View Slide

  2. Who am I?
    Paweł Jędrzejewski
    Huge beliver in Open Source
    Symfony & BDD evangelist
    Creator of Sylius
    Working for Opensoft on

    View Slide

  3. ŁÓDŹ, POLAND

    View Slide

  4. ?

    View Slide

  5. THE PROBLEM
    PHP has changed
    This change created the market for a new e-commerce solution
    among developers
    With the flexibility of modern frameworks and the new way of
    collaboration we can build something interesting for the business
    Sylius reflects this evolution

    View Slide

  6. View Slide

  7. WHAT IS SYLIUS
    A short history
    Open sourced in 2011 as a set of bundles
    Main application in development for ~9 months
    Already used in production by developers and companies

    View Slide

  8. FLEXIBILITY QUALITY PEOPLE

    View Slide

  9. View Slide

  10. View Slide

  11. FLEXIBILITY QUALITY PEOPLE

    View Slide

  12. QUALITY
    Behat and phpspec, perfect combination
    Most of new features start with an RFC issue
    Discussion about the idea and eventual implementation
    Behat features
    Implementation

    View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. View Slide

  17. FLEXIBILITY QUALITY PEOPLE

    View Slide

  18. BUNDLES vs. MAIN APPLICATION
    Set of 19 decoupled and
    independent bundles
    Can be used to create a
    custom platform
    Integrate e-commerce into
    existing application
    Standard webshop
    experience
    Highly customizable
    Easy to understand for
    every Symfony2 developer

    View Slide

  19. Sylius Bundles
    What they can do for you?
    EVERY SINGLE SYLIUS FEATURE AVAILABLE FOR YOUR PROJECt

    View Slide

  20. Simpler CRUD for symfony
    SyliusResourceBundle
    Removing tons of duplicated code in controllers for basic CRUD
    actions.
    Removing the manager and manipulator classes, relying on
    Doctrine instead.
    Removing the "frontend" and "backend" controllers.
    Supporting different persistence layers.
    Make the controllers format agnostic. (API)

    View Slide

  21. ADD YOUR RESOURCE
    sylius_resource:
    resources:
    acme.user:
    driver: doctrine/orm
    templates: AcmeShopBundle:User
    classes:
    model: Acme\ShopBundle\Entity\User
    repository: Acme\ShopBundle\Entity\UserRepository
    controller: Acme\ShopBundle\Controller\UserController

    View Slide

  22. acme.controller.user
    showAction
    indexAction
    createAction
    updateAction
    deleteAction

    View Slide

  23. acme_user_show:
    pattern: /users/{id}
    methods: [GET]
    defaults:
    _controller: acme.controller.user:showAction
    acme_profile_show:
    pattern: /profile/{username}
    methods: [GET]
    defaults:
    _controller: acme.controller.user:showAction
    _sylius:
    template: AcmeShopBundle:Profile:show.html.twig
    criteria: { username: $username, enabled: true }

    View Slide

  24. acme_profile_show:
    pattern: /profile/{username}
    methods: [GET]
    defaults:
    _controller: acme.controller.user:showAction
    _sylius:
    template: AcmeShopBundle:Profile:show.html.twig
    method: findOneForProfilePage
    arguments: [$username]
    acme_user_disabled_index:
    pattern: /users/disabled
    methods: [GET]
    defaults:
    _controller: acme.controller.user:indexAction
    _sylius:
    template: AcmeShopBundle:User:disabled.html.twig
    criteria: { enabled: false }

    View Slide

  25. acme_user_recently_registered:
    pattern: /users/recently-registered
    methods: [GET]
    defaults:
    _controller: acme.controller.user:indexAction
    _sylius:
    template: AcmeShopBundle:User:recentlyRegistered.html.twig
    criteria: { enabled: true }
    sorting: { createdAt: desc }
    paginate: false
    limit: 5

    View Slide

  26. acme_user_update_addresses:
    pattern: /users/{id}/update-addresses
    methods: [GET]
    defaults:
    _controller: acme.controller.user:updateAction
    _sylius:
    template: AcmeShopBundle:User:updateAddresses.html.twig
    form: acme_user_addresses
    redirect:
    route: acme_user_index

    View Slide

  27. Docs.sylius.org

    View Slide

  28. CONFIGURATION
    sylius_taxation:
    driver: doctrine/orm
    classes:
    tax_rate:
    model: Acme\ShopBundle\Entity\TaxRate
    controller: Acme\ShopBundle\Controller\TaxRateController
    repository: Acme\ShopBundle\Entity\TaxRateRepository
    form: Acme\ShopBundle\Form\Type\TaxRateType
    validation_groups:
    tax_rate: [sylius, acme]

    View Slide

  29. USING CUSTOM MODELS and FORMS
    Every model class can be overridden
    All repositories, managers and forms are
    updated automatically
    Form class can be customized

    View Slide

  30. OVERRIDING CONTROLLERS
    All models use default or slightly customized
    CRUD controller
    Add your own methods

    View Slide

  31. YOUR OWN REPOSITORY
    Sylius repositories extend native Doctrine
    implementations
    Override the repositories through configuration
    Repositories are services

    View Slide

  32. CHANGE THE RULES, VALIDATION
    All Sylius models ship with their own validation
    mapping under group „sylius”
    You can easily override it with your own rules
    Consistent translation messages

    View Slide

  33. DOCTRINE RTEL, DYNAMIC RELATIONS
    We're using interfaces instead of
    implementation to define the relations
    When you override the model class, all relations
    get updated automatically
    Defaults are turned into entities if you don't
    provide your own class

    View Slide

  34. WE LOVE EVENTS, YOU SHOULD TOO
    The default controller triggers multiple useful
    events during CRUD actions
    sylius.product.pre_create
    sylius.product.post_create

    View Slide

  35. PRODUCTS
    SyliusProductBundle

    View Slide

  36. View Slide

  37. ORDERS AND CART
    SyliusOrderBundle + SyliusCartBundle
    Generic Order model with support of Adjustments
    Cart bundle provides actions and services for customer to
    interact with the Order entity
    The order/cart items can be easily customized to handle
    different options

    View Slide

  38. View Slide

  39. COUNTRIES, ZONES AND ADDRESSES
    SyliusAddressingBundle
    Provides a very basic Address model
    Countries and their Provinces management
    Zones system with a ZoneMatcher service
    Useful for taxation and shipping zones

    View Slide

  40. $billingAddress = $order->getBillingAddress();
    $zone = $this->zoneMatcher->match($billingAddress);
    $address = $location->getAddress();
    $zones = $this->zoneMatcher->matchAll($address);

    View Slide

  41. TAKE CARE OF YOUR INVENTORY
    SyliusInventoryBundle
    Built around 1 interface you need to implement
    Tracks every single inventory unit
    Based on events
    Items available on demand
    Backorders

    View Slide

  42. HATE IT OR LOVE IT, TAXATION
    SyliusTaxationBundle
    TaxableInterface = heart of the bundle
    Multiple tax categories and rates support
    Customizable tax calculators
    Tax included in price

    View Slide

  43. MERCHANDISE NEEDS TO BE SHIPPED
    SyliusShippingBundle
    Integrate through one interface
    Manage Shipments and Shipping Methods
    Custom shipping rules
    Flexible calculators system

    View Slide

  44. class PerItemRateCalculator extends Calculator
    {
    public function calculate(ShippingSubjectInterface $subject, array $configuration)
    {
    return $configuration['amount'] * $subject->getShippingItemCount();
    }
    public function getConfigurationFormType()
    {
    return 'sylius_shipping_calculator_per_item_rate_configuration';
    }
    public function setConfiguration(OptionsResolverInterface $resolver)
    {
    $resolver
    ->setRequired(array( 'amount'))
    ->setAllowedTypes(array('amount' => array('numeric')))
    ;
    }
    }

    View Slide

  45. View Slide

  46. CATEGORIZE ALL THIS STUFF, NOW
    SyliusTaxonomiesBundle
    Classify any Model using different Taxonomies
    Flexible forms
    Based on DoctrineExtensions

    View Slide

  47. View Slide

  48. JUST FEW STEPS MORE
    SyliusFlowBundle
    Useful for anything which takes more than 1
    action to complete
    Checkouts, installation wizards, complex actions
    Used by OroCRM and Akeneo PIM for installers

    View Slide

  49. PROCESS SCENARIO
    class CheckoutProcessScenario implements ProcessScenarioInterface
    {
    public function build(ProcessBuilderInterface $builder)
    {
    $builder
    ->add('security', 'sylius_checkout_security')
    ->add('addressing', 'sylius_checkout_addressing')
    ->add('shipping', 'sylius_checkout_shipping')
    ->add('payment', 'sylius_checkout_payment')
    ->add('finalize', 'sylius_checkout_finalize')
    ->add('purchase', 'sylius_checkout_purchase')
    ;
    }
    }

    View Slide

  50. PAYUM INTEGRATION
    SyliusPayumBundle NEW!
    Integrates Payum library into Sylius checkout
    Replaceable by other bundles in future
    PayPal Express Checkout and Stripe support
    Omnipay usage through a bridge

    View Slide

  51. Make your app configurable, EASILY
    SyliusSettingsBundle
    You can define settings schema and the form
    User edits the settings through UI
    You get the access via services and Twig

    View Slide

  52. Settings schema
    class GeneralSettingsSchema implements SchemaInterface
    {
    public function buildSettings(SettingsBuilderInterface $builder)
    {
    $builder
    ->setDefaults(array(
    'meta_keywords' => 'symfony, sylius, ecommerce, webshop, shopping cart',
    'meta_description' => 'Sylius is modern ecommerce solution for PHP.',
    ))
    ->setAllowedTypes(array(
    'meta_keywords' => array('string'),
    'meta_description' => array('string'),
    ))
    ;
    }

    View Slide

  53. EDITING VIA FORM
    public function buildForm(FormBuilderInterface $builder)
    {
    $builder
    ->add('meta_keywords', 'text', array(
    'constraints' => array(new NotBlank())
    ))
    ->add('meta_description', 'textarea', array(
    'constraints' => array(new NotBlank())
    ))
    ;
    }

    View Slide

  54. View Slide

  55. PROMOTIONS ARE NICE
    SyliusPromotionsBundle
    Can be integrated with any Model
    Very flexible Actions and Rules system
    Support for promotion coupons

    View Slide

  56. PROMOTION STRUCTURE
    SUPER AWESOME PROMOTION
    ACTION
    ACTION
    ACTION
    RULE
    RULE

    View Slide

  57. CUSTOM RULES
    interface RuleCheckerInterface
    {
    /**
    * @param PromotionSubjectInterface $subject
    * @param array $configuration
    *
    * @return Boolean
    */
    public function isEligible(PromotionSubjectInterface $subject, array $configuration);
    /**
    * @return string
    */
    public function getConfigurationFormType();
    }

    View Slide

  58. YOUR OWN ACTIONS
    class AddPackageAction implements PromotionActionInterface
    {
    public function execute(PromotionSubjectInterface $subject, array $configuration)
    {
    $package = $this->findPackage($configuration);
    $item = $this->cartItemRepository->createNew();
    $item->setQuantity(1);
    $item->setUnitPrice(isset($configuration['price']) ? $configuration['price'] : $package->getGrossPrice());
    $item->setPackage($package);
    $subject->addItem($item);
    }
    public function getConfigurationFormType()
    {
    return 'xyz_promotion_action_add_package_configuration';
    }
    }

    View Slide

  59. View Slide

  60. Sylius Application
    How to bootstrap Symfony2 shop in minutes? (soon)
    Bringing smile back to developer's faces

    View Slide

  61. INSTALLATION
    $ composer create-project sylius/sylius -s dev path/to/install
    $ cd path/to/install
    $ app/console sylius:install
    $ composer create-project sylius/sylius-standard -s dev path/to/install
    $ cd path/to/install
    $ app/console sylius:install

    View Slide

  62. ONE CORE TO RULE THEM ALL
    SyliusCoreBundle
    Integrates all the bundles together
    Standard webshop application
    Contains all the models and services

    View Slide

  63. THE WEB INTERFACE
    SyliusWebBundle
    Provides the default web interface for Sylius
    Contains all the templates and menu builders
    Splitted into Frontend & Backend parts

    View Slide

  64. View Slide

  65. THE BACKEND

    View Slide

  66. public function forwardAction(ProcessContextInterface $context)
    {
    $request = $this->getRequest();
    $order = $this->getCurrentCart();
    $this->dispatchCheckoutEvent(SyliusCheckoutEvents::ADDRESSING_INITIALIZE, $order);
    $form = $this->createCheckoutAddressingForm($order);
    if ($request->isMethod('POST') && $form->bind($request)->isValid()) {
    $this->dispatchCheckoutEvent(SyliusCheckoutEvents::ADDRESSING_PRE_COMPLETE, $order);
    $this->getManager()->persist($order);
    $this->getManager()->flush();
    $this->dispatchCheckoutEvent(SyliusCheckoutEvents::ADDRESSING_COMPLETE, $order);
    return $this->complete();
    }
    return $this->renderStep($context, $order, $form);
    }

    View Slide

  67. View Slide

  68. TO DO
    Documentation, documentation, documentation
    New default store look
    Rework translations and integrate with CrowdIn
    Polish the checkout process
    Integrate BazingaHateoasBundle for API
    Integrate Symfony CMF and Create.js

    View Slide

  69. COMING SOON...
    Pull Requests
    Customer groups
    Subscriptions support
    Product reviews
    Symfony CMF integration (editable blocks and pages)
    Facebook/Amazon and so on...

    View Slide

  70. View Slide

  71. Www.sylius.org
    Github.com/sylius
    @pjedrzejewski
    THANK YOU
    Questions?

    View Slide