Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Aumente o reconhecimento da sua carreira através da certificação Symfony

Aumente o reconhecimento da sua carreira através da certificação Symfony

Symfony hoje é um ambiente estável que é bem conhecido e reconhecido internacionalmente. Nesta palestra mostrarei como aumentar suas chances de obter a certificação Symfony utilizando as técnicas que utilizei para alcançar a certificação. Também falarei sobre quais são as vantagens de se destacar através de uma certificação Symfony.

44b348fa585f1aaa1984041b962b05f7?s=128

Hallison Boaventura

May 16, 2019
Tweet

Transcript

  1. Aumente o reconhecimento da sua carreira através da certificação Symfony

    Hallison Boaventura {github,twitter}.com/hallboav
  2. @hallboav • Reputação ◦ 119 packages ◦ 2,5 bilhões downloads

    • Referências ◦ Drupal ◦ Composer ◦ Laravel Por que Symfony?
  3. @hallboav • Open Source ◦ MIT - Massachusetts Institute of

    Technology • Inovação ◦ Symfony Panther, Messenger, Mercure, Flex, etc. • Interoperabilidade ◦ Liberdade ◦ Symfony Contracts Por que Symfony?
  4. @hallboav • Promessa de compatibilidade com versões anteriores ◦ Versionamento

    semântico ◦ Guia de uso do código do Symfony • Processo de entregas ◦ Modelo de entregas de versões baseado no tempo ▪ Patches a cada mês ▪ Minor version a cada seis mêses (maio, novembro) ▪ Major version a cada dois anos Por que Symfony?
  5. @hallboav Symfony Roadmap

  6. Symfony FTW! @hallboav • Diversidade de pensamentos (CARE) • Segurança,

    performance, inovação, etc. • Ótima arquitetura (extensível, direta, etc.) • Excelentes componentes ◦ Console tem +138 milhões downloads no packagist
  7. Minha história com o Symfony (~4 anos) @hallboav

  8. Aplicações que já escrevi utilizando Symfony @hallboav • Gerador de

    relatórios de um firewall de mercado ◦ FW > Syslog > Node.js > MongoDB > PHP > MongoDB ◦ Console, Progress Bar, Question Helper, Formatter Helper, Validator, Lock, Yaml, Config, OptionsResolver, Finder, Filesystem, etc. • Silex 2 JWT Security Service Provider ◦ Symfony Security Component
  9. Aplicações que já escrevi utilizando Symfony @hallboav • Backend de

    app para consulta de saldo do cartão de alimentação ◦ DomCrawler, CssSelector, Goutte (Non-Symfony) • Conversor de código do Zend Framework v2 para o v3 dentro da estrutura do Itamaraty ◦ Finder, Console, etc.
  10. Aplicações que já escrevi utilizando Symfony @hallboav • Lançador de

    registros de pontos ◦ Symfony Cache, Config, DomCrawler, etc.
  11. @hallboav Aplicações que estamos escrevendo utilizando Symfony • Integração com

    o SEI (Sistema Eletrônico de Informações)
  12. @hallboav Técnicas que utilizei para alcançar a certificação • Prática

    • Análise do código • Xdebug • Documentação • Lista de estudo com os tópicos e subtópicos exigidos pela Symfony
  13. @hallboav • SymfonyCasts (tutorials) (oficial) ◦ https://symfonycasts.com • Use uma

    lista para organizar a leitura da documentação ◦ https://thomasberends.github.io/symfony-certification -preparation-list ◦ https://symfony.com/doc/current/index.html (menu guia esquerda) • Contribua para a documentação Minhas recomendações além das técnicas que utilizei
  14. @hallboav Minhas recomendações além das técnicas que utilizei • Faça

    pequenos sistemas com os componentes standalones para estudá-los • Leia (constantemente) livros e blogs ◦ https://leanpub.com/symfony-selfstudy (livro) ◦ https://leanpub.com/a-year-with-symfony (livro) ◦ https://symfony.com/blog ◦ https://andreiabohner.org ◦ http://fabien.potencier.org
  15. @hallboav • Use a ferramenta Certificationy ◦ https://github.com/certificationy/certificationy-cli • Baixar

    documentação offline em formato PDF ◦ https://symfony.com/doc/current/index.html (EOP) • Veja a apresentação do Tobias Nyholm com o título "Deep dive into Symfony 4 internals" Minhas recomendações além das técnicas que utilizei
  16. @hallboav Symfony HttpKernel & EventDispatcher Components @hallboav

  17. Symfony EventDispatcher Component @hallboav

  18. class SymfonyMug { const CAPACITY = 100.0; protected $amount =

    0.0; public function fill(): void { $this->amount = self::CAPACITY; } public function isEmpty(): bool { return 0 === $this->amount; } // ... } class SymfonyMugEmptyEvent extends Event { const EMPTY = 'symfony_mug.empty'; protected $mug; public function __construct(SymfonyMug $mug) { $this->mug = $mug; } public function getMug(): SymfonyMug { return $this->mug; } } use Symfony\Component\EventDispatcher\Event;
  19. use Symfony\Component\EventDispatcher\EventSubscriberInterface; class SymfonyMugSubscriber extends EventSubscriberInterface { public static function

    getSubscribedEvents() { return [ SymfonyMugEmptyEvent::EMPTY => 'onEmpty', // O mesmo evento pode ser manipulado por dois métodos diferentes // SymfonyMugEmptyEvent::EMPTY => [ // ['onEmptyPre', 8], // ['onEmptyPost', -8], // ], ]; } public function onEmpty(SymfonyMugEmptyEvent $event): void { $event->getMug()->fill(); } }
  20. use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $dispatcher->addSubscriber(new SymfonyMugSubscriber()); $mug =

    new SymfonyMug(); // ... if ($mug->isEmpty()) { // Criamos um evento de caneca vazia $event = new SymfonyMugEmptyEvent($mug); // Disparamos o evento para quem estiver observando-o $dispatcher->dispatch(SymfonyMugEmptyEvent::EMPTY, $event); }
  21. O do Symfony @hallboav Symfony HttpKernel Component

  22. use Symfony\Component\HttpFoundation\Request; // Request::createFromGlobals(); $request = Request::create($uri = '/books?foo=bar', $method

    = 'GET', $parameters = [], $cookies = [], $files = [], $server = [], $content = null); echo 'Method: ', var_export($request->getMethod(), true), PHP_EOL; echo 'Scheme: ', var_export($request->getScheme(), true), PHP_EOL; echo 'HttpHost: ', var_export($request->getHttpHost(), true), PHP_EOL; echo 'RequestUri: ', var_export($request->getRequestUri(), true), PHP_EOL; echo 'PathInfo: ', var_export($request->getPathInfo(), true), PHP_EOL; echo 'QueryString: ', var_export($request->getQueryString(), true), PHP_EOL; echo 'Uri: ', var_export($request->getUri(), true), PHP_EOL; // Method: 'GET' // Scheme: 'http' // HttpHost: 'localhost' // RequestUri: '/books?foo=bar' // PathInfo: '/books' // QueryString: 'foo=bar' // Uri: 'http://localhost/books?foo=bar'
  23. use Symfony\Component\HttpFoundation\Response; $response = new Response( $content = '{"books":[{"isbn":"9785189880940"},{"isbn":"9790069769536"}]}', $status

    = 200, $headers = ['Content-Type' => 'application/json'] ); echo 'Content: ', var_export($response->getContent(), true), PHP_EOL; echo 'StatusCode: ', var_export($response->getStatusCode(), true), PHP_EOL; echo 'Content-Type: ', var_export($response->headers->get('Content-Type'), true), PHP_EOL; // Content: '{"books":[{"isbn":"9785189880940"},{"isbn":"9790069769536"}]}' // StatusCode: 200 // Content-Type: 'application/json'
  24. namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Request; /** * @author Fabien Potencier <fabien@symfony.com>

    */ interface HttpKernelInterface { const MASTER_REQUEST = 1; const SUB_REQUEST = 2; /** * Handles a Request to convert it to a Response. */ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true); }
  25. use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; class SfLiveKernel implements HttpKernelInterface

    { public function handle(Request $request, $type = 1, $catch = true) { if ('/blackfire' === $request->getPathInfo()) { return new Response('<a href="https://blackfire.io">Blackfire</a>'); } else if ('/darkmira' === $request->getPathInfo()) { return new Response('<a href="https://php.darkmiratour.rocks">Darkmira</a>'); } return new Response('Not found', 404); } } $kernel = new SfLiveKernel(); $request = Request::create('/blackfire'); $response = $kernel->handle($request, 1, false); // Essa chamada não captura exceções $response->send();
  26. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; public function handle(Request $request, $type = 1, $catch

    = true) { try { return $this->handleRaw($request); } catch (\Exception $e) { // rethrow ou manipular exception dependendo do $catch } } private function handleRaw(Request $request): Response { if ('/blackfire' === $request->getPathInfo()) { return new Response('<a href="https://blackfire.io">Blackfire</a>'); } else if ('/darkmira' === $request->getPathInfo()) { return new Response('<a href="https://php.darkmiratour.rocks">Darkmira</a>'); } throw new NotFoundHttpException('Not found'); }
  27. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; public function handle(Request $request, $type = 1, $catch

    = true) { try { return $this->handleRaw($request); } catch (\Exception $e) { if (false === $catch) { throw $e; } return $this->handleException($e); } } private function handleException(\Exception $e): Response { $response = new Response($e->getMessage()); if ($e instanceof HttpExceptionInterface) { $response->headers->add($e->getHeaders()); return $response->setStatusCode($e->getStatusCode()); } return $response->setStatusCode(500); }
  28. use Symfony\Component\HttpFoundation\Request; $kernel = new SfLiveKernel(); $request = Request::create('/blackfire'); $response

    = $kernel->handle($request); // Agora essa chamada captura exceções $response->send();
  29. @hallboav Adicionando EventDispatcher Component

  30. // ... $routes = [ // pathinfo => controller '/blackfire'

    => function (Request $request) { return new Response('<a href="https://blackfire.io">Blackfire</a>'); }, '/darkmira' => function (Request $request) { return new Response('<a href="https://php.darkmiratour.rocks">Darkmira</a>'); }, ]; // ...
  31. use Symfony\Component\EventDispatcher\Event; class RequestEvent extends Event { private $request; public

    function __construct(Request $request) { $this->request = $request; } public function getRequest(): Request { return $this->request; } }
  32. use Symfony\Component\EventDispatcher\EventSubscriberInterface; class RouterListener implements EventSubscriberInterface { protected $routes; public

    function __construct(array $routes = []) { $this->routes = $routes; } public static function getSubscribedEvents() { return ['kernel.request' => 'onKernelRequest']; } public function onKernelRequest(RequestEvent $event): void { $request = $event->getRequest(); foreach ($this->routes as $pathinfo => $controller) { if ($request->getPathInfo() === $pathinfo) { $request->attributes->add(['_controller' => $controller]); break; } } } }
  33. use Symfony\Component\EventDispatcher\EventDispatcherInterface; class SfLiveKernel implements HttpKernelInterface { protected $dispatcher; public

    function __construct(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } // ... private function handleRaw(Request $request): Response { $event = new RequestEvent($request); $this->dispatcher->dispatch('kernel.request', $event); if (null === $controller = $request->attributes->get('_controller')) { throw new NotFoundHttpException('Not found'); } return $controller($request); } // ... }
  34. use Symfony\Component\EventDispatcher\EventDispatcher; $routes = [ '/blackfire' => function (Request $request)

    { return new Response('<a href="https://blackfire.io">Blackfire</a>'); }, '/darkmira' => function (Request $request) { return new Response('<a href="https://php.darkmiratour.rocks">Darkmira</a>'); }, ]; $dispatcher = new EventDispatcher(); // RouterListener::onKernelRequest será executado sempre em cada request e irá // fazer o roteamento para a controller através do atributo "_controller", desta forma // a controller pode ser vista e executada pelo SfLiveKernel::handleRaw $dispatcher->addSubscriber(new RouterListener($routes)); $kernel = new SfLiveKernel($dispatcher); $request = Request::create('/blackfire'); $response = $kernel->handle($request); $response->send();
  35. @hallboav • SymfonyConnect (próximos slides) • Badge & PDF (próximos

    slides) • Investimento 250 euros (~R$ 1.120,00 16 maio '19) • 40% desconto na black friday (novembro) • Symfony 3.0 e 4.0 • Níveis (Advanced e Expert) • Porcentagem de acertos • SensioLabs University (3 meses de workshop) Processo da certificação
  36. None
  37. @hallboav Congratulations

  38. None
  39. @hallboav Ainda sobre o processo da certificação • 75 questões,

    15 tópicos, 90 minutos (~1m15s/questão) • Pearson VUE ou exame online • Tipos de perguntas ◦ true/false, única resposta, respostas múltiplas • Validade voucher (um ano após a compra) • Retake (2x por ano e tem que pagar) • Não cai questões sobre bundles de terceiros ou Doctrine
  40. @hallboav Tópicos do exame • PHP and Web Security (11)

    ◦ Web security (XSS, CSRF, etc.) ◦ SPL (Std. PHP Lib.) • HTTP (9) ◦ Client / Server interaction ◦ Caching • Data Validation (7) ◦ PHP object validation ◦ Validation groups ◦ Violations builder • Dependency Injection (9) ◦ Service container ◦ Tags ◦ Services autowiring
  41. @hallboav Tópicos do exame • Symfony Architecture (13) ◦ Symfony

    Flex ◦ Configuration ◦ Event dispatcher ◦ Oficial best practices • Standardization (9) ◦ Naming conventions ◦ Coding standards • Security (11) ◦ Authentication ◦ Authorization ◦ Firewalls ◦ Guard ◦ Voters and voting strategies
  42. @hallboav Tópicos do exame • Controllers (12) ◦ The base

    controller class ◦ Internal redirects • Routing (11) ◦ Config. (YAML, XML, PHP & annotations) ◦ Generate URL parameters ◦ Special internal routing attributes • HTTP Caching (6) ◦ Expiration (Expires, Cache-Control) ◦ Validation (ETag, Last-Modified) ◦ Edge Side Includes • Console (8) ◦ Options and arguments ◦ Built-in helpers
  43. @hallboav Tópicos do exame • Templating with Twig (12) ◦

    Template inheritance ◦ Translations and pluralization • Forms (11) ◦ Form events ◦ CSRF protection ◦ Handling file upload • Automated Tests (10) ◦ Functional tests with PHPUnit ◦ PHPUnit Bridge • Miscellaneous (7) ◦ Process and Serializer components ◦ Internationalization and localization (Translation Component)
  44. @hallboav Benefícios • Promoção de cargo & aumento de salário

    • Visibilidade mundial (possibilidade de trabalhar no exterior) • Maior legitimidade em todo ecossistema, não apenas no Symfony • Desempate de perfis em momentos de contratação • Realização pessoal
  45. @hallboav Fake Certification (4.0) Verdadeiro ou falso: Para definir um

    serviço privado utilizamos "private: true"? 1. Verdadeiro 2. Falso
  46. @hallboav Fake Certification (4.0) Quais padrões de projeto o componente

    EventDispatcher implementa? 1. Mediator 2. Strategy 3. Adapter 4. Observer
  47. @hallboav Fake Certification (4.0) Responsável por limpar o cache do

    Symfony? 1. cache:clear 2. clear:cache 3. cache:clean 4. c:c
  48. @hallboav Fake Certification (4.0) Quais estratégias de decisão de acesso

    dos Voters existem? 1. affirmative 2. negative 2. concensus 3. unanimous
  49. @hallboav Mantenha-se atualizado • Siga o blog do Symfony (symfony.com/blog)

    • Siga pessoas que discutem Symfony no Twitter ◦ @SymfonyBrasil, @symfony, @nicolagrekas, @fabpot, @xabbuh, @TobiasSchultze, @Stof70, @weaverryan, @seldaek, @andreiabohner, @CyrilleGrandval, @jucycabrera, @KaFernandesDev, etc. • SymfonyBrasil no Telegram (https://t.me/SymfonyBrasil)
  50. Obrigado! @hallboav