Share
Embed
Symfony2 Components. How not to reinvent the wheel.
WebConf Riga 2012, 10.11.2012
Evercode Talks №1, 08.11.2012
Don't reinvent the wheel, use the existing one, make them better, enjoy and don't waste your time. Symfony2 framework has a remarkable set of standalone decoupled components for various task of web development. Let's see how we can use them for our tasks.
Roma
November 10, 2012
Transcript
49 slides
-
Symfony2 Components. How not to reinvent the wheel. Roman Lapin,
Evercode Lab @memphys, [email protected] -
Don’t Reinvent The Wheel, Unless You Plan on Learning More
About Wheels. Jeff Atwood (http:/ /www.codinghorror.com/blog/2009/02/dont-reinvent-the-wheel-unless-you-plan-on-learning- more-about-wheels.html) -
Symfony Components Beside being a full-stack framework, Symfony is also
a set of decoupled and standalone components. Symfony Components implement common features needed to develop websites. -
Reasons Decoupled and Standalone Highly tested Clean API Widely adopted
Audited for security issues by an independent company There are people (great community) -
Components ClassLoader Config DependencyInjection EventDispatcher HttpFoundation HttpKernel Routing Templating BrowserKit
Process Console Finder CssSelector DomCrawler Form Locale Serializer Yaml Validator Translation -
Components ClassLoader Config DependencyInjection EventDispatcher HttpFoundation HttpKernel Routing Templating BrowserKit
Process Console Finder CssSelector DomCrawler Form Locale Serializer Yaml Validator Translation -
Installation { "require": { "symfony/console": "2.1.*", "symfony/process": "2.1.*", "symfony/finder": "2.1.*",
"symfony/form": "2.1.*", "symfony/validator": "2.1.*", "symfony/config": "2.1.*", "symfony/translation": "2.1.*", "symfony/security": "2.1.*" ... } } $ composer install require_once __DIR__.'/../vendor/autoload.php'; -
HttpFoundation The Symfony2 HttpFoundation component replaces these default PHP global
variables and functions by an Object-Oriented layer. -
HttpFoundation use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); $input = $request->get('name', 'World');
// the URI minus any query parameters $request->getPathInfo(); // retrieve SERVER variables $request->server->get('HTTP_HOST'); // retrieves an instance of UploadedFile identified by foo $request->files->get('foo'); -
HttpFoundation // COOKIE value $request->cookies->get('PHPSESSID'); // HTTP request header $request->headers->get('host');
$request->getMethod(); // GET, POST, PUT, DELETE, HEAD // simulate a request $request = Request::create('/awesome.php?say=wooohooo'); -
HttpFoundation use Symfony\Component\HttpFoundation\Response; $response = new Response(); $response->setContent(“What’s up, Doc?”);
$response->setStatusCode(200); $response->headers->set('Content-Type', 'text/html'); // HTTP cache headers $response->setMaxAge(10); -
Finder The Finder Component finds files and directories via an
intuitive fluent interface. -
Finder use Symfony\Component\Finder\Finder; $finder = new Finder(); $finder->files() ->in(__DIR__) ->in(__DIR__.'/../data')
->exclude('crap') ; foreach ($finder as $file) { print $file->getRealpath()."\n"; print $file->getFilename()."\n"; } -
Finder // files or directories $finder->files(); $finder->directories(); $finder->files()->followLinks(); $finder->ignoreVCS(false); //
sorting $finder->sortByName(); $finder->sortByType(); -
Console The Console component allows you to create command-line commands.
Your console commands can be used for any recurring task, such as cronjobs, imports, or other batch jobs. -
Console #!/usr/bin/env php <?php use Symfony\Component\Console\Application; use App\Command\ParseCommand; $console =
new Application(); $console->add(new ParseCommand()); $console->run(); -
Console namespace App\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use
Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -
Console class ParseCommand extends Command { protected function configure() {
$this ->setName('parse') ->setDescription('Parses cached information') ->addArgument('date', InputArgument::OPTIONAL, "Put in some date.", date('Y-m-d')) ; } } -
Console protected function execute(InputInterface $input, OutputInterface $output) { $date =
$input->getArgument('date'); if (empty($date)) { $date = date('Y-m-d'); } $formatter = new CsvFormatter(); $formatter->process($date); $output->writeln('<info>operation finished</info>'); } -
CssSelector use Symfony\Component\CssSelector\CssSelector; print CssSelector::toXPath('div.item > h4 > a'); descendant-or-self::div[contains(concat('
',normalize- space(@class), ' '), ' item ')]/h4/a -
CssSelector $document = new \DOMDocument(); $document->preserveWhiteSpace = false; $document->loadHTML($html); $xpath
= new \DOMXPath($document); $blocks = $xpath->query( CssSelector::toXPath('div.filters ul li b a') ); -
DomCrawler $document = new \DOMDocument(); $document->preserveWhiteSpace = false; $document->loadHTML($html); $xpath
= new \DOMXPath($document); $blocks = $xpath->query( CssSelector::toXPath('div.filters ul li b a') ); -
DomCrawler use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\CssSelector\CssSelector; $crawler = new Crawler($html); $crawler
= $crawler->filterXPath( CssSelector::toXPath('div.filters ul li b a') ); $crawler = $crawler->filter('div.filters ul li b a'); -
DomCrawler $crawler->filter('body > p')->first(); $crawler->filter('body > p')->last(); $crawler->filter('body > p')->siblings();
$crawler->filter('body > p')->nextAll(); $crawler->filter('body > p')->previousAll(); $crawler->filter('body')->children(); $crawler->filter('body > p')->parents(); -
DomCrawler $link = $crawler->selectLink('follow the rabbit')->link(); $uri = $link->getUri(); $form
= $crawler->selectButton('validate')->form(); $form = $crawler->selectButton('validate')->form(array( 'name' => 'Just Bugs', )); $uri = $form->getUri(); -
DomCrawler use Goutte\Client; // make a real request to an
external site $client = new Client(); $crawler = $client->request('GET', 'https://github.com/login'); // select the form and fill in some values $form = $crawler->selectButton('Log in')->form(); $form['login'] = 'rabbitcoder'; $form['password'] = 'Carrot123'; // submit that form $crawler = $client->submit($form); -
Form Form provides tools for defining forms, rendering and binding
request data to related models. Furthermore it provides integration with the Validation component. -
Form namespace App\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Validator\Constraints as
Assert; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class RegisterType extends AbstractType { ... public function getName() { return 'register'; } } -
Form public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('event',
'choice', array( 'choices' => $events, 'constraints' => new Assert\Choice(array_keys($events)), 'required' => true, 'attr' => array( 'class' => 'input-xlarge' ), )) ->add('first_name', 'text', array( 'constraints' => new Assert\NotBlank(), 'required' => true, )) } -
Form $app->match('/', function (Request $request) use ($app) { $form =
$app['form.factory']->create( new RegisterType($app['event_service']) ); if ('POST' == $request->getMethod()) { $form->bind($request); if ($form->isValid()) { $data = $form->getData(); // ... return $app->redirect('success'); } } return $app['twig']->render('index.html.twig', array( 'form' => $form->createView() )); }); -
Form <form action="/" method="post" novalidate> {{ form_widget(form) }} <input type="submit"
name="submit" value="Submit" /> </form> -
Security Security provides an infrastructure for sophisticated authorization systems, which
makes it possible to easily separate the actual authorization logic from so called user providers that hold the users credentials. -
Security $app->match('/admin', function (Request $request) use ($app) { return $app['twig']->render('admin.html.twig',
array()); }) ->bind('admin'); -
Security $app->register(new Silex\Provider\SecurityServiceProvider()); $app['security.firewalls'] = array( 'admin' => array( 'pattern'
=> '^/admin', 'http' => true, 'users' => array( 'admin_login' => array( 'ROLE_ADMIN', 'encrypted_pass' ), ), ), ); -
Use cases? Refactoring New apps Integrating in existent code Inventing
the wheel (yet another framework?) You name it! -
Want more? Composer (http:/ /getcomposer.org/) Packagist (https:/ /packagist.org/) Silex (http:/
/silex.sensiolabs.org/) Twig (http:/ /twig.sensiolabs.org/) SwiftMailer (http:/ /swiftmailer.org/) KnpBundles (http:/ /knpbundles.com/) -
Sources http:/ /symfony.com/components “Create your own framework... on top of
the Symfony2 Components” by Fabien Potencier Source code http:/ /www.php-fig.org/ -
Reinvent away. Most of our current technology sucks, and even
if it didn't, who am I to try and stop you? Bob Lee (http:/ /blog.crazybob.org/2007/09/why-reinvent-wheel.html)