Symfony best practices и не только Олег Зинченко

Dd3f18c87b851137000c7427d7bd5d32?s=47 fwdays
November 18, 2014

Symfony best practices и не только Олег Зинченко

Dd3f18c87b851137000c7427d7bd5d32?s=128

fwdays

November 18, 2014
Tweet

Transcript

  1. Symfony Best Practices and beyond Oleg Zinchenko KNPLabs https://twitter.com/1cdecoder https://github.com/cystbear

    http://knplabs.com/
  2. Symfony Best Practices Book http://symfony.com/doc/current/best_practices/index.html

  3. Ryan Weaver (KNPer) https://twitter.com/weaverryan https://knpuniversity.com/

  4. Disclaimer THE SOFTWARE SLIDES IS PROVIDED "AS IS" WITHOUT WARRANTY

    OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  5. Creating the Project

  6. Always use Composer to install Symfony https://getcomposer.org/ https://packagist.org/

  7. AcmeDemoBundle

  8. Create only one bundle called AppBundle uberCMS/ ├─ app/ │

    ├─ console │ ├─ cache/ │ ├─ config/ │ └─ logs/ │ └─ Resources/ ├─ src/ │ └─ AppBundle/ ├─ vendor/ └─ web/ ├─ app.php └─ app_dev.php
  9. Create only one bundle called AppBundle What about API Bundle?

    What about Core Bundle? What about DDD? Do not use Sf3 dir structure... yet Imagine several kernels
  10. Configuration

  11. Infrastructure/Application Related Configuration parameters.yml parameters.yml.dist app/config/config.yml

  12. Infrastructure/App Related Configuration # app/config/config.yml imports: - resource: parameters.yml -

    resource: framework.yml - resource: doctrine.yml - resource: doctrine_extension.yml - resource: html_purifier.yml - resource: facebook.yml - resource: mailer.yml - resource: monolog.yml - resource: twig.yml - resource: imagine.yml
  13. Use constants to define configuration options that rarely change Different

    environments Different clients
  14. Semantic Configuration: Don't Do It services.xml/yml + *Extension.php + Configuration.php

    http://symfony2-document.readthedocs.org/en/latest/cookbook/bundles/extension.html
  15. Business Logic

  16. Business Logic or How to reach Zen

  17. Service Format: YAML

  18. Config Formats Routing DBmapping Services Validation Serializer map Translations Yaml

    Annotation XML Annotation, XML Yaml Yaml
  19. Service: No Class Parameter # app/config/services.yml parameters: slugger.class: AppBundle\Slugger services:

    slugger: class: "%slugger.class%"
  20. Service: No Class Parameter # app/config/services.yml services: slugger: class: AppBundle\Slugger

  21. Annotations for Doctrine mappings /** @MongoDB\Document */ class Topic {

    /** @MongoDB\Id */ protected $id; /** @MongoDB\String */ protected $name; /** @MongoDB\Int */ protected $code; // .... }
  22. Annotations for Doctrine mappings

  23. Data Fixtures One fixture file per entity OrderedFixtureInterface DoctrineFixturesBundle +

    Alice & bundle + Faker https://github.com/doctrine/DoctrineFixturesBundle https://github.com/hautelook/AliceBundle https://github.com/fzaninotto/Faker
  24. Controllers

  25. Make your controller extend the FrameworkBundle Get Request Submit form

    if any Call one Service method Return Response Rendering HTML far away
  26. Routing Configuration Annotations External format (YAML, XML) /** @Route("/") */

    public function indexAction() { } _index: pattern: / defaults: { _controller: AcmeBundle:Frontend:index }
  27. Use ParamConverter /** @ParamConverter("post", class="BlogBundle:Post") */ public function showAction(Post $post)

    { return $this->render('show.html.twig', array( 'post' => $post, )); }
  28. Templates

  29. Use Twig for your templates

  30. Store all your templates in app/Resources/views/ Inconsistently with Bundle coupling

    Hard to maintain Probably easier write template path Inside bundles In app/ DemoBunde:Default:index.html.twig default/index.html.twig ::layout.html.twig layout.html.twig AcmeDemoBundle::index.html.twig index.html.twig
  31. Forms

  32. Use Form Types Define your forms as PHP classes class

    PostType extends AbstractType { public function buildForm( FormBuilderInterface $builder, array $options ) { $builder ->add('title') ->add('summary', 'textarea') ->add('content', 'textarea') ; }
  33. public function setDefaultOptions( OptionsResolverInterface $resolver ) { $resolver->setDefaults(array( 'data_class' =>

    'AppBundle\Entity\Post' )); } Use Form Types Always add “form model”
  34. class PostType extends AbstractType { public function buildForm(// ...) {

    $builder // ... ->add('save', 'submit', array('label' => 'Create Post')) ; } Wrong code example “Add buttons in the templates, not in the form classes or the controllers” Form Templates
  35. Form Templates <form method="POST" {{ form_enctype(form) }}> {{ form_widget(form) }}

    </form> “Don't use the form() or form_start()”
  36. Handling Forms $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em =

    $this->getDoctrine()->getManager(); $em->persist($post); $em->flush(); } return $this->redirect(...);
  37. Handling Forms $form->handleRequest($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($post);

    $em->flush(); } return $this->redirect(...);
  38. i18n

  39. Use the XLIFF for your translation files Too Verbose Extra

    complexity Accidental complexity Inconsistently with service configs
  40. Translation files location “Store the translation files in the app/Resources/translations

    directory” Same issues as for templates Inconsistently with Bundle coupling
  41. Translation Keys “Always use keys for translations instead of content

    strings” At form types At templates At validation messages
  42. Security

  43. None
  44. Firewalls “Be simple: use only one firewall entry with the

    anonymous key enabled” Remember about API auth
  45. Password hashing “Use the bcrypt encoder for encoding your users

    passwords” security: encoders: AppBundle\Entity\User: bcrypt For old Sf systems <2.3 https://github.com/elnur/ElnurBlowfishPasswordEncoderBundle
  46. Authorization

  47. Authorization Protecting broad URL patterns, use access_control access_control: - {

    path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/, roles: ROLE_ADMIN }
  48. Authorization Whenever possible, use the @Security annotation /** * @Security("has_role('ROLE_ADMIN')")

    */ public function indexAction() { // ... }
  49. Custom Voter class PostVoter extends AbstractVoter { const CREATE =

    'create'; const EDIT = 'edit'; protected function getSupportedAttributes() { return array(self::CREATE, self::EDIT); } protected function getSupportedClasses() { return array('AppBundle\Entity\Post'); } } For fine-grained restrictions, define a custom security voter
  50. For fine-grained restrictions, define a custom security voter protected function

    isGranted($attribute, $post, $user = null) { if (!$user instanceof UserInterface) return false; if ($attribute == self::CREATE && in_array(ROLE_ADMIN, $user->getRoles()) ) return true; if ($attribute == self::EDIT && $user->getEmail() === $post->getAuthorEmail() ) return true; return false; } Custom Voter
  51. Applying voter Custom Voter # app/config/services.yml services: post_voter: class: AppBundle\Security\PostVoter

    public: false tags: - { name: security.voter } /** * @Security("is_granted('edit', post)") */ public function editAction(Post $post)
  52. Phew

  53. Authorization ACL For restricting access to any object by any

    user via an admin interface, use the Symfony ACL
  54. Drop ACE, use voters http://symfony.com/doc/current/cookbook/security/acl.html http://slides.com/marieminasyan/drop-ace-use-role-voters https://www.youtube.com/watch?v=e7HfW4TgnUY

  55. Web Assets

  56. Use Assetic, Kris approves https://twitter.com/kriswallsmith http://kriswallsmith.net/

  57. Tests

  58. Write tests, they approve

  59. None