Share
Embed
Symfony2 Components. Как не изобретать велосипед (DrupalCafe version)
DrupalCafe #3 Spb
Не изобретайте велосипеды, катайтесь на них, улучшайте их, получайте удовольствие и не тратьте время зря. Фреймворк Symfony2 предоставляет отличный набор независимых компонентов для различных задач веб-разработки. Давайте посмотрим, как можно их использовать для решения наших задач.
Roma
March 02, 2013
Transcript
61 slides
-
Symfony2 Components. Как не изобретать велосипед Роман Лапин, Evercode Lab
@memphys, [email protected] Обновлено и адаптировано специально для DrupalCafe #3 ;) -
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 -
PHP < 5.3 Много библиотек, фреймворков и вообще готового кода
Большое коммьюнити PEAR (это боль) НО! Copy + Paste :( -
Обмениваться кодом, находить готовые решения и переисользовать код было больно,
грустно и местами противно. -
PHP >= 5.3 Namespaces (наконец-то!) PHP Framework Interop Group Стандарты
Composer Прогресс Спасибо, GitHub! -
Это надо знать http:/ /www.phptherightway.com/ http:/ /www.php-fig.org/ PSR-0 ... PSR-3
http:/ /getcomposer.org/ https:/ /packagist.org/ -
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. -
Symfony2+Drupal=<3 Today, I want to officially announce that Drupal will
adopt some of the Symfony Components for their upcoming version 8. And I'm not talking about some minor components, they are embracing our vision and they will use the major components that will allow them to build a great low-level architecture for Drupal 8: HttpFoundation, HttpKernel, Routing, EventDispatcher, DependencyInjection, and ClassLoader. Fabien Potencier - March 22, 2012 http:/ /symfony.com/blog/symfony2-meets-drupal-8 -
Компоненты ClassLoader Config DependencyInjection EventDispatcher HttpFoundation HttpKernel Routing Templating BrowserKit
Process Console Finder CssSelector DomCrawler Form Locale Serializer Yaml Validator Translation -
Компоненты ClassLoader Config DependencyInjection EventDispatcher HttpFoundation HttpKernel Routing Templating BrowserKit
Process Console Finder CssSelector DomCrawler Form Locale Serializer Yaml Validator Translation -
Компоненты в Drupal8 ClassLoader Config DependencyInjection EventDispatcher HttpFoundation HttpKernel Routing
Templating BrowserKit Process Console Finder CssSelector DomCrawler Form Locale Serializer Yaml Validator Translation -
Причины Независимые и изолированные Покрыты тестами Очень приятный API Широкое
распространение Проведен независимый аудит безопасности -
Установка { "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'; -
{ "name": "drupal/drupal", "description": "Drupal is an open source content
management platform powering millions of websites and applications.", "license": "GPL-2.0+", "repositories": [{ "type": "vcs", "url": "https://github.com/msonnabaum/phpunit.git" } ], "require": { "symfony/class-loader": "2.2.0-BETA2", "symfony/dependency-injection": "2.2.0-BETA2", "symfony/event-dispatcher": "2.2.0-BETA2", "symfony/http-foundation": "2.2.0-BETA2", "symfony/http-kernel": "2.2.0-BETA2", "symfony/routing": "2.2.0-BETA2", "symfony/serializer": "2.2.0-BETA2", "symfony/validator": "2.2.0-BETA2", "symfony/yaml": "2.2.0-BETA2", "twig/twig": "1.12.1", "doctrine/common": "2.3.0", "guzzle/http": "3.1.0", "kriswallsmith/assetic": "1.1.0-alpha1", "symfony-cmf/routing": "dev-master#ea4a10", "easyrdf/easyrdf": "0.8.0-beta.1", "phpunit/phpunit": "3.7 as dev-3.7" }, "minimum-stability": "dev" } -
ClassLoader The ClassLoader Component loads your project classes automatically if
they follow some standard PHP conventions. { "require": { "symfony/class-loader": "2.2.0-BETA2", } } -
ClassLoader require_once '/path/to/src/Symfony/Component/ClassLoader/ UniversalClassLoader.php'; use Symfony\Component\ClassLoader\UniversalClassLoader; $loader = new UniversalClassLoader();
// You can search the include_path as a last resort. $loader->useIncludePath(true); // ... register namespaces and prefixes here - see below $loader->register(); -
ClassLoader $loader->registerNamespaces(array( 'Symfony' => __DIR__.'/../vendor/symfony/symfony/src', 'Monolog' => __DIR__.'/../vendor/monolog/monolog/src', )); $loader->registerPrefixes(array(
'Swift_' => __DIR__.'/vendor/swiftmailer/swiftmailer/ lib/classes', 'Twig_' => __DIR__.'/vendor/twig/twig/lib', )); -
HttpFoundation The Symfony2 HttpFoundation component replaces these default PHP global
variables and functions by an Object-Oriented layer. { "require": { "symfony/http-foundation": "2.2.0-BETA2", } } -
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); -
Routing The Routing Component maps an HTTP request to a
set of configuration variables. { "require": { "symfony/routing": "2.2.0-BETA2", } } -
Routing use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $route
= new Route( '/archive/{month}', // path array('controller' => 'showArchive'), // default values array('month' => '[0-9]{4}-[0-9]{2}'), // requirements array() // options ); $routes = new RouteCollection(); $routes->add('route_name', $route); $context = new RequestContext($_SERVER['REQUEST_URI']); $matcher = new UrlMatcher($routes, $context); $parameters = $matcher->match('/archive/2012-01'); // array('controller' => 'showArchive', '_route' => 'route_name') -
HttpKernel HttpKernel provides the building blocks to create flexible and
fast HTTP-based frameworks. { "require": { "symfony/http-kernel": "2.2.0-BETA2", } } -
HttpKernelInterface interface HttpKernelInterface { /** * Handles a Request to
convert it to a Response. * * @param Request $request A Request instance * * @return Response A Response instance */ function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true); } -
HttpKernelInterface $routes = new RouteCollection(); $routes->add('hello', new Route('/hello', array('_controller' =>
function (Request $request) { return new Response(sprintf("Hello %s", $request->get('name'))); } ))); $request = Request::createFromGlobals(); $context = new RequestContext(); $context->fromRequest($request); $matcher = new UrlMatcher($routes, $context); $dispatcher = new EventDispatcher(); $dispatcher->addSubscriber(new RouterListener($matcher)); $resolver = new ControllerResolver(); $kernel = new HttpKernel($dispatcher, $resolver); $kernel->handle($request)->send(); -
Finder The Finder Component finds files and directories via an
intuitive fluent interface. { "require": { "symfony/finder": "2.2.0-BETA2", } } -
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. { "require": { "symfony/console": "2.2.0-BETA2", } } -
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>'); } -
Form Form provides tools for defining forms, rendering and binding
request data to related models. Furthermore it provides integration with the Validation component. { "require": { "symfony/form": "2.2.0-BETA2", } } -
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> -
Twig The flexible, fast, and secure template engine for PHP
{ "require": { "twig/twig": "1.12.1", } } -
Twig <?php echo $var ?> <?php echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8')
?> {{ var }} {{ var|escape }} {% for user in users %} * {{ user.name }} {% else %} No user have been found. {% endfor %} {% extends "layout.html" %} {% block content %} Content of the page... {% endblock %} -
Где применять? Рефакторинг Новые приложения Интеграция в существующий код Велосипеды,
говорите? ;) Ваши варианты -
Что-нибудь еще? EventDispatcher (https:/ /speakerdeck.com/ nucleartux/symfony-event-dispatcher) DependencyInjection (https:/ / speakerdeck.com/toothfairy/inversion-of-
control-in-symfony-2) http:/ /symfony.com/components -
Что-нибудь еще? Silex (http:/ /silex.sensiolabs.org/) Twig (http:/ /twig.sensiolabs.org/) SwiftMailer (http:/
/swiftmailer.org/) KnpBundles (http:/ /knpbundles.com/) Symfony2 CMF (http:/ /cmf.symfony.com/) -
Источники http:/ /symfony.com/components “Create your own framework... on top of
the Symfony2 Components” by Fabien Potencier Source code http:/ /www.php-fig.org/ https:/ /igor.io/ -
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) -
Будьте не просто Drupal разработчиком, или Symfony разработчиком, или даже
PHP или Ruby разработчиком. Смотрите шире, обменивайтесь идеями, ищите решения действительно важных и новых проблем.