Slide 1

Slide 1 text

The Wonderful World of the Symfony Components by your friend: Ryan Weaver @weaverryan Friday, September 28, 12

Slide 2

Slide 2 text

Who is this dude? • That “Docs” guy • KnpLabs US - Symfony consulting, training, Kumbaya • Writer for KnpUniversity.com screencasts • Husband of the much more talented @leannapelham knplabs.com github.com/weaverryan @weaverryan Friday, September 28, 12

Slide 3

Slide 3 text

Intro Life before components (The Desert of the Real) Friday, September 28, 12

Slide 4

Slide 4 text

Symfony consists of 23 individual components Friday, September 28, 12

Slide 5

Slide 5 text

Components are available via Composer Friday, September 28, 12

Slide 6

Slide 6 text

Snooze... Friday, September 28, 12

Slide 7

Slide 7 text

Who Cares? Friday, September 28, 12

Slide 8

Slide 8 text

We Suck at Sharing and that sucks for you @weaverryan 1 Friday, September 28, 12

Slide 9

Slide 9 text

Including External Libraries is Depressing Friday, September 28, 12

Slide 10

Slide 10 text

The Big Bummer :( @weaverryan • How do I autoload their files? • Does their library depend on anything else? • How do I even store their files in my project? Friday, September 28, 12

Slide 11

Slide 11 text

Include a Zend Framework 1 component in symfony1 Friday, September 28, 12

Slide 12

Slide 12 text

Friday, September 28, 12

Slide 13

Slide 13 text

manually download the library and commit it into your project Friday, September 28, 12

Slide 14

Slide 14 text

if you don’t want the WHOLE library, carefully delete everything except the dependent components Friday, September 28, 12

Slide 15

Slide 15 text

autoloading is completely custom ... blah gross! Friday, September 28, 12

Slide 16

Slide 16 text

Components are the key to mastering your framework @weaverryan 2 Friday, September 28, 12

Slide 17

Slide 17 text

If PHP is big, we’ll thrive If PHP is small, we’ll die @weaverryan 3 Friday, September 28, 12

Slide 18

Slide 18 text

Communities @weaverryan PHP is Huge! Right? http://www.flickr.com/photos/kitty-kat/ Friday, September 28, 12

Slide 19

Slide 19 text

@weaverryan PHP > Ruby Friday, September 28, 12

Slide 20

Slide 20 text

Fragmentation @weaverryan But fragmentation makes us tiny, isolated, and misguided trend-setters http://www.flickr.com/photos/slpunk99/7329609744 Friday, September 28, 12

Slide 21

Slide 21 text

PHP frameworks < Rails @weaverryan Friday, September 28, 12

Slide 22

Slide 22 text

I don’t want a damned CakePHP Plugin! @weaverryan CakePHP CodeIgniter Friday, September 28, 12

Slide 23

Slide 23 text

Fragmentation @weaverryan • More information we have to know • Difficult to hire • Disjointed forums, StackOverflow • Interoperability? What’s that? Friday, September 28, 12

Slide 24

Slide 24 text

Components are shareable across all of PHP Friday, September 28, 12

Slide 25

Slide 25 text

Act 1 Making Sharing Sexy Friday, September 28, 12

Slide 26

Slide 26 text

PHP Framework Interoperability Group http://www.php-fig.org/ Friday, September 28, 12

Slide 27

Slide 27 text

The United Nations of PHP Friday, September 28, 12

Slide 28

Slide 28 text

(A) The Problem of Autoloading Friday, September 28, 12

Slide 29

Slide 29 text

My Autoloader doesn’t like your PHPs @weaverryan • The symfony1 autoloader doesn’t know where ZF1 classes live. The Zf1 autoloader doesn’t know where symfony1 classes live • Each library has its own autoloader that you must discover, configure and use Friday, September 28, 12

Slide 30

Slide 30 text

like a town where every store has its own currency Friday, September 28, 12

Slide 31

Slide 31 text

From The Mountain: PSR-0 Class Naming Conventions @weaverryan “Thou shalt name your classes by following a predictable pattern” Friday, September 28, 12

Slide 32

Slide 32 text

class: sfRequest path: lib/vendor/symfony/???idk Friday, September 28, 12

Slide 33

Slide 33 text

class: Symfony\Component\HttpFoundation\Request path: vendor/symfony/src/Symfony/Component/ HttpFoundation/Request.php Friday, September 28, 12

Slide 34

Slide 34 text

use Symfony\Component\ClassLoader\UniversalClassLoader; $loader = new UniversalClassLoader(); $loader->registerNamespaces(array( 'Zend' => __DIR__.'/path/to/zf' )); $loader->register(); Friday, September 28, 12

Slide 35

Slide 35 text

(B) Managing Vendors in your project Friday, September 28, 12

Slide 36

Slide 36 text

Composer Friday, September 28, 12

Slide 37

Slide 37 text

{ "require": { "zendframework/ldap": "2.0.x-dev" } } 1) Composer.json Friday, September 28, 12

Slide 38

Slide 38 text

$ curl -s https://getcomposer.org/installer | php $ php composer.phar install 2) Composer.phar Friday, September 28, 12

Slide 39

Slide 39 text

require 'vendor/autoload.php'; use Zend\Ldap\Ldap; $options = array(...); $ldap = new Ldap($options); 3) Use It Friday, September 28, 12

Slide 40

Slide 40 text

Friday, September 28, 12

Slide 41

Slide 41 text

Act 2 Your friendly, neighborhood Symfony Components Friday, September 28, 12

Slide 42

Slide 42 text

The Symfony Components • HttpFoundation • HttpKernel • Event Dispatcher • Routing • CSSSelector • DomCrawler • BrowserKit • Config • Yaml • DependencyInjection • Security @weaverryan • OptionsResolver • Console • Filesystem • Finder • Locale • Process • Serializer • Templating • Form • Translation • Validator Friday, September 28, 12

Slide 43

Slide 43 text

The Symfony Components • HttpFoundation • HttpKernel • Event Dispatcher • Routing • CSSSelector • DomCrawler • BrowserKit • Config • Yaml • DependencyInjection • Security @weaverryan • OptionsResolver • Console • Filesystem • Finder • Locale • Process • Serializer • Templating • Form • Translation • Validator The “Framework” Components Friday, September 28, 12

Slide 44

Slide 44 text

Level 1 HttpFoundation symfony/http-foundation Friday, September 28, 12

Slide 45

Slide 45 text

@weaverryan { "require": { "symfony/http-foundation": "2.1.x-dev" } } php composer.phar install

Slide 46

Slide 46 text

@weaverryan Request /foo Response

Hi!

? ? ? ? ? ? Mystery PHP Code Friday, September 28, 12

Slide 47

Slide 47 text

The Request Friday, September 28, 12

Slide 48

Slide 48 text

GET /foo?p=v1 HTTP/1.1 Host: knplabs.com Accept: text/html User-Agent: Mozilla/5.0 // /foo?p=v1 $uri = $_SERVER['REQUEST_URI']; $p = isset($_GET['p']) ? $_GET['p'] : ''; $host = $_SERVER['HTTP_HOST']; $accept = $_SERVER['HTTP_ACCEPT']; $ua = $_SERVER['HTTP_USER_AGENT']; Friday, September 28, 12

Slide 49

Slide 49 text

use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); $uri = $request->getPathInfo(); /foo $p = $request->query->get('p'); $host = $request->getHost(); $accept = $request->headers->get('Accept'); GET /foo?p=v1 HTTP/1.1 Host: knplabs.com Accept: text/html User-Agent: Mozilla/5.0 Friday, September 28, 12

Slide 50

Slide 50 text

The Response Friday, September 28, 12

Slide 51

Slide 51 text

HTTP/1.1 200 OK Date: Tue, 04 Jun 2011 21:05:05 GMT Content-Type: text/html Set-Cookie:foo=fooval; path=/; httponly

Foo!

header('Content-Type', 'text/html'); setcookie('foo', 'fooval'); echo '

Foo!

'; Friday, September 28, 12

Slide 52

Slide 52 text

HTTP/1.1 200 OK Date: Tue, 04 Jun 2011 21:05:05 GMT Content-Type: text/html Set-Cookie:foo=fooval; path=/; httponly

Foo!

use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Cookie; $response = new Response('

Foo!

'); $cookie = new Cookie('foo', 'fooval'); $response->headers->setCookie($cookie); $response->send(); Friday, September 28, 12

Slide 53

Slide 53 text

A Mini Framework Friday, September 28, 12

Slide 54

Slide 54 text

// not dependable! $uri = $_SERVER['REQUEST_URI']; ob_start(); if ($uri == '/') { echo 'Homepage! \o/'; } else { echo 'sad missing page :/'; } header('X-TOKEN: Foo'); ob_end_flush(); Friday, September 28, 12

Slide 55

Slide 55 text

$req = Request::createFromGlobals(); if ($req->getPathInfo() == '/') { $res = new Response('Homepage! \o/'); } else { $res = new Response('sad missing page :/'); } $res->headers->set('X-SECRET', 'Foo'); $res->send(); Symfony3 Friday, September 28, 12

Slide 56

Slide 56 text

Get some learning about HttpFoundation @weaverryan • Docs: http://bit.ly/sf2-http-foundation • Code: http://bit.ly/sf2-http-foundation-code • API: http://bit.ly/sf2-http-foundation-api Friday, September 28, 12

Slide 57

Slide 57 text

Level 2 HttpKernel symfony/http-kernel Friday, September 28, 12

Slide 58

Slide 58 text

@weaverryan Framework Request Determine the controller ? ? ? Execute it Flush the Response Response Friday, September 28, 12

Slide 59

Slide 59 text

Framework: A pattern for converting a request into a response Friday, September 28, 12

Slide 60

Slide 60 text

@weaverryan Framework Request Determine the controller ? ? ? Execute it Flush the Response Response Friday, September 28, 12

Slide 61

Slide 61 text

@weaverryan HttpKernel Request Determine the controller ? ? ? Execute it Flush the Response Response Friday, September 28, 12

Slide 62

Slide 62 text

$kernel = new HttpKernel(...); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); There be magic inside! Friday, September 28, 12

Slide 63

Slide 63 text

These lines execute your Symfony application (hint, see - web/app.php) Friday, September 28, 12

Slide 64

Slide 64 text

... and Drupal 8 too ... Friday, September 28, 12

Slide 65

Slide 65 text

Yea, this is abstract Stay Tuned... Friday, September 28, 12

Slide 66

Slide 66 text

Level 3 EventDispatcher symfony/event-dispatcher Friday, September 28, 12

Slide 67

Slide 67 text

@weaverryan Event Dispatcher A classic “observer pattern” Listener Listener Tell me when Liz gets to work Tell me when Liz gets to work Friday, September 28, 12

Slide 68

Slide 68 text

@weaverryan Event Dispatcher • Event Dispatcher: a classic “observer pattern” Listener Listener Yo! I’m at work! Friday, September 28, 12

Slide 69

Slide 69 text

@weaverryan Event Dispatcher • Event Dispatcher: a classic “observer pattern” Listener Listener Liz is at work! Liz is at work! Friday, September 28, 12

Slide 70

Slide 70 text

Event Dispatcher • Event Dispatcher: a classic “observer pattern” Listener Listener She’s the best around! I’m totally going to go talk with her!! Friday, September 28, 12

Slide 71

Slide 71 text

Level 4 Routing symfony/routing Friday, September 28, 12

Slide 72

Slide 72 text

@weaverryan Router Url Match against a route Return info about the route Route Route Friday, September 28, 12

Slide 73

Slide 73 text

$loader = new ClosureLoader(); $router = new Router($loader, function() { $collection = new RouteCollection(); $route = new Route('/blog/{slug}'); $collection->add('blog', $route); return $collection; }); $results = $router->match('/blog/sflive'); array( 'slug' => 'sflive', '_route' => 'blog', ) Friday, September 28, 12

Slide 74

Slide 74 text

$loader = new ClosureLoader(); $router = new Router($loader, function() { $collection = new RouteCollection(); $route = new Route('/blog/{slug}', array( '_controller' => 'SomeBundle:Blog:show' )); $collection->add('blog', $route); return $collection; }); $results = $router->match('/blog/sflive'); array( '_controller' => 'SomeBundle:Blog:show', 'slug' => 'sflive', '_route' => 'blog' ) Friday, September 28, 12

Slide 75

Slide 75 text

Input: Request Information Output: An array of info Friday, September 28, 12

Slide 76

Slide 76 text

Level 5 A “Framework” Friday, September 28, 12

Slide 77

Slide 77 text

$kernel = new HttpKernel(...); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); Friday, September 28, 12

Slide 78

Slide 78 text

@weaverryan HttpKernel::handle() HttpFoundation + EventDispatcher + Routing (optional) = Framework Friday, September 28, 12

Slide 79

Slide 79 text

@weaverryan HttpKernel::handle() Request + Determine Controller + Controller Returns a Response = Response Friday, September 28, 12

Slide 80

Slide 80 text

Homework: Hack your Framework ... or do Karaoke later... your call Friday, September 28, 12

Slide 81

Slide 81 text

@weaverryan HttpKernel::handleRaw() private function handleRaw(Request $request, $type = self::MASTER_REQUEST) { // request $event = new GetResponseEvent($this, $request, $type); $this->dispatcher->dispatch(KernelEvents::REQUEST, $event); if ($event->hasResponse()) { return $this->filterResponse($event->getResponse(), $request, $type); } // load controller if (false === $controller = $this->resolver->getController($request)) { throw new NotFoundHttpException('Unable to find the controller); } $event = new FilterControllerEvent($this, $controller, $request, $type); $this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event); $controller = $event->getController(); // ... returns a response } The kewlest code I know about... seriously Friday, September 28, 12

Slide 82

Slide 82 text

@weaverryan • Symfony\Component\HttpKernel\HttpKernel::handle() http://bit.ly/sf2-http-kernel-code • Symfony Framework Important Classes Symfony\Component\HttpKernel\EventListener\RouterListener - Executes the routing Symfomy\Bundle\FrameworkBundle\Controller\ControllerResolver - Parses _controller and instantiates the controller object step/var_dump()die; the core Friday, September 28, 12

Slide 83

Slide 83 text

Timeline of events in the Symfony Framework kernel.request kernel.controller kernel.response Friday, September 28, 12

Slide 84

Slide 84 text

Profile events in the Symfony Framework Friday, September 28, 12

Slide 85

Slide 85 text

The Symfony Components • HttpFoundation • HttpKernel • Event Dispatcher • Routing • CSSSelector • DomCrawler • BrowserKit • Config • Yaml • DependencyInjection • Security @weaverryan • OptionsResolver • Console • Filesystem • Finder • Locale • Process • Serializer • Templating • Form • Translation • Validator Awesome Tools Friday, September 28, 12

Slide 86

Slide 86 text

Process symfony/process Now with more Windows Love! Friday, September 28, 12

Slide 87

Slide 87 text

@weaverryan { "require": { "symfony/process": "2.1.x-dev" } } Find Symfony’s Process on Packagist.org php composer.phar install 1 2 3

Slide 88

Slide 88 text

Slide 89

Slide 89 text

Run the script synchronously Friday, September 28, 12

Slide 90

Slide 90 text

// app.php require 'vendor/autoload.php'; use Symfony\Component\Process\Process; $process = new Process('php dinner.php'); // if dinner takes longer than 5 seconds // to cook, freak out! $process->setTimeout(5); $process->run(function($type, $buffer) { echo $buffer; }); // executed after the command finishes if (!$process->isSuccessful()) { throw new \Exception('Process misbehaved') } Friday, September 28, 12

Slide 91

Slide 91 text

Friday, September 28, 12

Slide 92

Slide 92 text

Run the script asynchronously Friday, September 28, 12

Slide 93

Slide 93 text

$process = new Process('php dinner.php'); $process->start(); // do more work here echo "WORKING!!! \n"; while ($process->isRunning()) { // wait for the process to finish }; echo $process->getOutput(); Friday, September 28, 12

Slide 94

Slide 94 text

Interacting via Stdin Friday, September 28, 12

Slide 95

Slide 95 text

$process = new Process('php dinner.php'); $process->setStdin('turkey'); “turkey” is read from Stdin Friday, September 28, 12

Slide 96

Slide 96 text

$process = new Process('php dinner.php'); $process->run(function($type, $buffer) { if ($type == 'err') { // perhaps do some logging? echo $buffer; } }); Handling things that blow up! if (!$process->isSuccessful()) { echo sprintf( "Process failed! Exit code %s, '%s'\n", $process->getExitCode(), $process->getExitCodeText() ); } Friday, September 28, 12

Slide 97

Slide 97 text

Find out more about Process @weaverryan • Docs: http://bit.ly/sf2-process • Code: http://bit.ly/sf2-process-code • API: http://bit.ly/sf2-process-api Friday, September 28, 12

Slide 98

Slide 98 text

SPORK! @kriswallsmith $manager = new Spork\ProcessManager(); $manager->fork(function() { // do something in another process! return 'Hello from '.getmypid(); })->then(function(Spork\Fork $fork) { // do something in the parent process afterwards echo "{$fork->getPid()} says '{$fork->getResult()}'"; }); Fork yourself some more PHP https://github.com/kriswallsmith/spork Friday, September 28, 12

Slide 99

Slide 99 text

Finder symfony/finder Friday, September 28, 12

Slide 100

Slide 100 text

From the Fablog http://fabien.potencier.org/article/44/php-iterators-and- streams-are-awesome use Symfony\Components\Finder\Finder; $s3 = new \Zend_Service_Amazon_S3($key, $secret); $s3->registerStreamWrapper("s3"); $finder = new Finder(); $finder->name('photos*') ->size('< 100K') ->date('since 1 hour ago'); foreach ($finder->in('s3://bucket-name') as $file) { // do something print $file->getFilename()."\n"; } Friday, September 28, 12

Slide 101

Slide 101 text

Find(er) out more about Finder @weaverryan • Docs: http://bit.ly/sf2-finder • Code: http://bit.ly/sf2-finder-code • API: http://bit.ly/sf2-finder-api Friday, September 28, 12

Slide 102

Slide 102 text

Filesystem symfony/filesystem New in 2.1! Friday, September 28, 12

Slide 103

Slide 103 text

@weaverryan { "require": { "symfony/filesystem": "2.1.x-dev" } } Find Symfony’s Filesystem on Packagist.org php composer.phar update symfony/filesystem 1 2 3

Slide 104

Slide 104 text

// ... use Symfony\Component\Filesystem\Filesystem; $filesystem = new Filesystem(); $filesystem->copy( 'cowboy.jpg', 's3://my-bucket/cowboy.jpg' ); $filesystem->copy( 's3://my-bucket/rodeo.mov', 'rodeo.mov' ); $filesystem->mirror( 'thumbnails', 's3://my-bucket/thumbnails' ); Friday, September 28, 12

Slide 105

Slide 105 text

// ... use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; $finder = new Finder(); $finder->name('*.jpg') ->date('since 1 hour ago'); ->in('thumbs'); $filesystem = new Filesystem(); $filesystem->chmod($finder, 0777); Friday, September 28, 12

Slide 106

Slide 106 text

// ... use Symfony\Component\Filesystem\Filesystem; $filesystem = new Filesystem(); $filesystem->touch('foo.txt'); $filesystem->chmod('foo.txt', 0777); $filesystem->symlink('/some/dir', '/symlink/target') Friday, September 28, 12

Slide 107

Slide 107 text

Find out more about Filesystem @weaverryan • Docs: http://bit.ly/sf2-filesystem • Code: http://bit.ly/sf2-filesystem-code • API: http://bit.ly/sf2-filesystem-api Friday, September 28, 12

Slide 108

Slide 108 text

Console symfony/console Friday, September 28, 12

Slide 109

Slide 109 text

Friday, September 28, 12

Slide 110

Slide 110 text

add('App', __DIR__); use Symfony\Component\Console\Application; use App\Command\EchoCommand; $app = new Application(); $app->add(new EchoCommand()); $app->run(); Friday, September 28, 12

Slide 111

Slide 111 text

namespace App\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class EchoCommand extends Command { protected function configure() { $this->setName('echo')->addArgument('msg'); } public function execute( InputInterface $input, OutputInterface $output) { $output->writeln('Yo '.$input->getArgument('msg')); } } Friday, September 28, 12

Slide 112

Slide 112 text

Output with pretty colors Friday, September 28, 12

Slide 113

Slide 113 text

Find out more about Command @weaverryan • Docs http://bit.ly/sf2-console • Code http://bit.ly/sf2-console-code • API http://api.symfony.com/master/namespaces.html -> and search for “Console” Friday, September 28, 12

Slide 114

Slide 114 text

If you download Composer in the next 5 minutes, we’ll throw in a special gift! Friday, September 28, 12

Slide 115

Slide 115 text

CssSelector + DomCrawler symfony/css-selector symfony/dom-crawler Friday, September 28, 12

Slide 116

Slide 116 text

require 'vendor/autoload.php'; use Symfony\Component\DomCrawler\Crawler; $html = <<<'HTML'

Hello World!

Hello Crawler!

HTML; $crawler = new Crawler($html); $crawler->filter('p')->eq(0)->attr('class'); $crawler->filter('p')->eq(1)->text(); Friday, September 28, 12

Slide 117

Slide 117 text

Goutte! Friday, September 28, 12

Slide 118

Slide 118 text

Config symfony/config Friday, September 28, 12

Slide 119

Slide 119 text

Config @weaverryan • Load configuration from many formats (YAML, PHP files, XML) • Config Validation • Caching for parsed config Friday, September 28, 12

Slide 120

Slide 120 text

Validator symfony/validator Friday, September 28, 12

Slide 121

Slide 121 text

Shh... a little setup Friday, September 28, 12

Slide 122

Slide 122 text

require 'vendor/autoload.php'; use Symfony\Component\Validator\Validator; use Symfony\Component\Validator\Mapping\ClassMetadataFactory; use Symfony\Component\Validator\ConstraintValidatorFactory; // a little setup $metadata = new ClassMetadataFactory(); $constraintFactory = new ConstraintValidatorFactory(); $validator = new Validator($metadata, $constraintFactory); Friday, September 28, 12

Slide 123

Slide 123 text

use Symfony\Component\Validator\Constraints\Email; $value = 'ryan[AT]knplabs.com'; $email = new Email(); $email->message = 'Invalid! You entered {{ value }}'; $errors = $validator->validateValue($value, $email); if (count($errors) > 0) { echo strtr( $errors[0]->getMessageTemplate(), $errors[0]->getMessageParameters() ); } Friday, September 28, 12

Slide 124

Slide 124 text

34 Core Validators and counting • String length • Regular expressions • Ip addresses • Dates • Collections • File size, mime-type, etc ... and the brand new Luhn validator for credit card numbers thanks to @merk -----------------------------------> @weaverryan See the “Reference” section of the docs Friday, September 28, 12

Slide 125

Slide 125 text

But wait there’s more! Friday, September 28, 12

Slide 126

Slide 126 text

More Components • DependencyInjection • Security • OptionsResolver • Locale • Serializer • Templating • Form • Translation @weaverryan Friday, September 28, 12

Slide 127

Slide 127 text

Many components are easy Friday, September 28, 12

Slide 128

Slide 128 text

Some are still wtf-hard Friday, September 28, 12

Slide 129

Slide 129 text

(cough) Security (cough) Friday, September 28, 12

Slide 130

Slide 130 text

Documentation Documentation Documentation Friday, September 28, 12

Slide 131

Slide 131 text

The Security Component https://github.com/symfony/symfony-docs/pull/1604 WIP by @matthiasnoback Friday, September 28, 12

Slide 132

Slide 132 text

Act 3 Kicking ass in the new PHP eco-system Friday, September 28, 12

Slide 133

Slide 133 text

The PHP Ecosphere • Symfony • Zend Framework • EZ Components • Drupal • ... • Individuals @weaverryan Symfony is only one part of the picture What other stuff exists? Friday, September 28, 12

Slide 134

Slide 134 text

How do we find good libraries? Friday, September 28, 12

Slide 135

Slide 135 text

Friday, September 28, 12

Slide 136

Slide 136 text

Friday, September 28, 12

Slide 137

Slide 137 text

Some Favorites Friday, September 28, 12

Slide 138

Slide 138 text

Mink behat/mink http://mink.behat.org/ By @everzet, written on Fabien’s childhood computer Friday, September 28, 12

Slide 139

Slide 139 text

Command a browser, find elements, click them, and fill out forms $driver = new \Behat\Mink\Driver\SahiDriver('firefox'); $session->visit('http://my_project.dev/some_page.php'); $page = $session->getPage(); $anchor = $page->find('css', '.something'); $anchor->click(); // get the content of the new page echo $page->getContent(); Friday, September 28, 12

Slide 140

Slide 140 text

Monolog monolog/monolog https://github.com/Seldaek/monolog Your Friend Jordi Friday, September 28, 12

Slide 141

Slide 141 text

A Logger, where bells and whistles come standard use Monolog\Logger; use Monolog\Handler\StreamHandler; use Monolog\Handler\FirePHPHandler; // Create the logger $logger = new Logger('my_logger'); $logger->pushHandler(new StreamHandler( __DIR__.'/my_app.log' )); $logger->pushHandler(new FirePHPHandler()); $logger->addInfo('My logger is now ready'); Friday, September 28, 12

Slide 142

Slide 142 text

Zend Framework 2 They have some stuff Friday, September 28, 12

Slide 143

Slide 143 text

Yay Find More! Friday, September 28, 12

Slide 144

Slide 144 text

Epilogue 4 Reasons to get silly-excited about the Future Friday, September 28, 12

Slide 145

Slide 145 text

1) Look for Participation & Consolidation Friday, September 28, 12

Slide 146

Slide 146 text

Shared Building-blocks • Drupal • phpBB • Midgard • Zikula • ez Publish 5 • ... @weaverryan Friday, September 28, 12

Slide 147

Slide 147 text

Less Library Duplication? • Zend/Form • Zend/Serializer • Zend/Http • Zend/EventManager • Zend/Log • Zend/Navigation • ... @weaverryan • Symfony/Form • Symfony/Serializer • Symfony/HttpFoundation • Symfony/EventDispatcher • Monlog • KnpMenu • ... Friday, September 28, 12

Slide 148

Slide 148 text

2) More high quality, community-grown libraries Friday, September 28, 12

Slide 149

Slide 149 text

Solving 1 specific problem is a low barrier to entry Friday, September 28, 12

Slide 150

Slide 150 text

Find them, fork them. Friday, September 28, 12

Slide 151

Slide 151 text

Write their docs :) Friday, September 28, 12

Slide 152

Slide 152 text

Programmers that write docs get hugs Friday, September 28, 12

Slide 153

Slide 153 text

3) Easier upgrades Friday, September 28, 12

Slide 154

Slide 154 text

4) Grow your Community Friday, September 28, 12

Slide 155

Slide 155 text

Solutions exist outside of your framework Friday, September 28, 12

Slide 156

Slide 156 text

Fabien will not come to your house and tell you about them Friday, September 28, 12

Slide 157

Slide 157 text

Cast your vote by using the best libraries and improving them Friday, September 28, 12

Slide 158

Slide 158 text

and realize the power of the entire PHP community Friday, September 28, 12

Slide 159

Slide 159 text

Thanks... Ryan Weaver @weaverryan Friday, September 28, 12

Slide 160

Slide 160 text

... and we love you! Ryan Weaver @weaverryan Ryan Weaver @weaverryan https://joind.in/7218 Friday, September 28, 12