1  <?php

2

3  Use Silex;

4  Use Cilex;

5  // Be awesome.

Using Silex makes life better

  • Lets you use the Modern PHP Ecosystem
  • Provides useful tools for you to use:
    • Routers, Requests, Response
    • Autoloading via composer
    • Error management
  • Small enough to learn how to do something in a half-day
  • Easy to migrate into a "big framework" later.

DEPRECATED

PHP

ECOSYSTEM

MODERN

PHP

ECOSYSTEM

  • Latest PHP
  • Git (ubiquitous option)
  • Composer
  • FIG/PSR
  • Components
  • Real OOP and Architecture
  • SemVer

Tools: Router, Request, Response

Out-of-the-box, silex provides everything you need to start HTTP.

<?php // web/index.php

// Dependency Namespaces are loaded via 
// Composer according to PSR
require_once __DIR__.'/../vendor/autoload.php';

// Gets an instance of a Silex web app 
$app = new Silex\Application();

// TODO: Add all the application logic here.

// Handles the request
// All equest object configuration can be set 
// up here (eg, trusted proxies, hosts, formats, etc...)
$app->run();

Tools: Router, Request, Response

Out-of-the-box, silex provides everything you need to start HTTP.

 

  • Routes
  • Request
  • Response
<?php // web/index.php

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

// Register a route to your app to
// execute a closure as the controller.

$app->get('/silex-is-cool', function () {

    // FIXME: A template in my controller!
    // We'll fix this in a few slides.
    $output = 'Thanks for visiting!';

    return $output;
});

$app->run();

Tools: Router, Request, Response

<?php // web/index.php

require_once __DIR__.'/../vendor/autoload.php';

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

$app = new Silex\Application();

// Register a route to your app to
// execute a closure as the controller.

$app->get('/silex-is-{adjective}', 
    function (Silex\Application $app, $adjective) {
        if ($adjective === "cilex") {
            $app->abort(400, "Client error.");
        }

        $output = sprintf(
            'Thanks for visiting! You think Silex is %s!',
            $adjective
        );

        return Response($output);
    }
);

$app->POST('/some-endpoint', function (Request $request) {
    return Response($request->get('someData'));
});

// see also: $app->{POST|PUT|GET|PATCH|MATCH}
$app->run();

BONUS!!!

Param converters,

Asserts,

and more.

 

Oh my!

<?php // web/index.php

require_once __DIR__.'/../vendor/autoload.php';

$nameFudger= function ($name) {
    return str_rot13($name);
};

$app->get('/user/{name}', function ($name) {
    return $name;
})
->convert('name', $nameFudger)
->assert('name', 'some|sort|of|regex');

// Other cool things: default values, named routes, 
// enforce HTTPS, pre-controller, post-controller,
// Send/Receive JSON, send files, send streams...

// Inject a controller provider to get controllers
// out of the index file!

$app->run();

Autoloading

composer

Take full advantage of powerful PHP components already built for you.

<?php // web/index.php

// ...

// Register provider into the service container (Pimple)
$app->register(new Silex\Provider\TwigServiceProvider(), array(
    'twig.path' => __DIR__.'/views',
));

$app->get('/hello/{name}', function ($name) use ($app) {

    // Use the twig service to render a template
    return $app['twig']->render('hello.html.twig', array(
        'name' => $name,
    ));

});

// ...
$ composer require twig/twig
$ composer require symfony/twig-bridge
{# web/views/hello.html.twig #}
Hello {{ name }}!

ERRORS

$app->error(function (\Exception $e, $code) use ($app) {
    if ($app['debug']) {
        return;
    }

    switch ($code) {
        case 404:
            $message = 'The requested page could not be found.';
            break;
        default:
            $message = 'We are sorry, but something went terribly wrong.';
    }
});

Small enough to GROK quickly

In less than an hour you've already seen "the big stuff".

 

If you want to know everything else...

  • using Pimple (a DI container)
  • Writing a Provider
  • Event Dispatcher
  • Testing
$ wget ftp://ftp.trailing-edge.com/pub/rsx11freewarev2/rsx81b/374001/jargon.txt
$ grep -A 2 '^GROK' jargon.txt
GROK [from the novel "Stranger in a Strange Land", by Robert Heinlein,
   where it is a Martian word meaning roughly "to be one with"] v. To
   understand, usually in a global sense.

Using Cilex makes life better

on the command line

  • Does things similarly to how Silex does it
  • Provides a way to do it from the command line
  • Easy to use code you wrote in Silex
  • Easy to use code you wrote in something that isn't Silex

Meet the new cilex, same as the old silex

<?php // app.php

require_once __DIR__.'/vendor/autoload.php';

// Get a new instance of Cilex
$app = new \Cilex\Application('Cilex');

// TODO: All the things

// Start parsing the commands and route it to things etc...
$app->run();

Meet the new cilex, same as the old silex

$ php run.php 
Cilex version 

Usage:
 command [options] [arguments]

Options:
 --help (-h)           Display this help message
 --quiet (-q)          Do not output any message
 --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 
                       2 for more verbose output and 3 for debug
 --version (-V)        Display this application version
 --ansi                Force ANSI output
 --no-ansi             Disable ANSI output
 --no-interaction (-n) Do not ask any interactive question

Available commands:
 help         Displays help for a command
 list         Lists commands

Adding a "command"

<?php // run.php

require_once __DIR__.'/vendor/autoload.php';

// Get a new instance of Cilex
$app = new \Cilex\Application('Cilex');

// Registers a command into Cilex. This is similar to adding routes.
$app->command(
    // look at this class if confused about commands
    new \Cilex\Command\GreetCommand()
);

// Start parsing the commands and route it to things etc...
$app->run();

Meet the new cilex, same as the old silex

$ php run.php 
Cilex version 

Usage:
 command [options] [arguments]

Options:
 --help (-h)           Display this help message
 --quiet (-q)          Do not output any message
 --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 
                       2 for more verbose output and 3 for debug
 --version (-V)        Display this application version
 --ansi                Force ANSI output
 --no-ansi             Disable ANSI output
 --no-interaction (-n) Do not ask any interactive question

Available commands:
 help         Displays help for a command
 list         Lists commands
demo
 demo:greet   Greet someone

Meet the new cilex, same as the old silex

$ php run.php demo:greet --help
Usage:
 demo:greet [--yell] [name]

Arguments:
 name                  Who do you want to greet?

Options:
 --yell                If set, the task will yell in uppercase letters
 --help (-h)           Display this help message
 --quiet (-q)          Do not output any message
 --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
 --version (-V)        Display this application version
 --ansi                Force ANSI output
 --no-ansi             Disable ANSI output
 --no-interaction (-n) Do not ask any interactive question


$ php run.php demo:greet 
Hello


$ php run.php demo:greet --yell achievers
HELLO ACHIEVERS

Is this wizardry?

<?php // ../vendors/Cilex/Cilex/Src/Cilex/Command/GreetCommand.php
// namespaces and use... 
class GreetCommand extends Command {
    protected function configure() {
        $this
            ->setName('demo:greet')
            ->setDescription('Greet someone')
            ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?')
            ->addOption('yell', null, InputOption::VALUE_NONE, 'If set, the task will yell in uppercase letters');
    }
    protected function execute(InputInterface $input, OutputInterface $output) {
        $name = $input->getArgument('name');
        $text = 'Hello';

        if ($name) { 
            $text .= ' '.$name;
        }

        if ($input->getOption('yell')) {
            $text = strtoupper($text);
        }

        $output->writeln($text);
    }
}

Inject

all the

things

<?php // ... blah blah this is a class...

    protected function execute(
        InputInterface $input,
        OutputInterface $output
    ) {
        $twig = $this->getApplication()->getService('twig');

        $text = $twig->render('hello.txt.twig', [
            'name' => $input->getArgument('name'),
            'yell' => $input->getOption('yell'),
        ]);

        $output->writeln($text);
    }
// inside run.php

// The silex provider is probably compatible
$app->register(new Silex\Provider\TwigServiceProvider(), [
    'twig.path' => __DIR__.'/views',
]);
$ composer require twig/twig
$ composer require symfony/twig-bridge
{# views/hello.txt.twig #}
Hello {{ yell ? name|capitalize : name }}!

Thanks jerk, now I have two code bases to take care of

Options

  • Put Cilex and Silex in the same repo
  • Make your business a dependency of the framework implementation*
  • Pick only one, and make the other as a service (eg, logic in Silex, and Cilex becomes a glorified CURL)**
  • Justify why you shouldn't use this tool, and know what would make you want to use it.

* Option I like the best for demonstrating these frameworks

** Option I like best

GET TO

THE CODE

ALREADY!!!!11!1!111

More

fun

stuff

Articles if you want to know more:

Scaling Silex to a large app

Silex Docs

Pimple Docs

Twig Docs

Other times people

let me ramble in public:

https://github.com/Incognito/blog/wiki/

Public-speaking-and-articles

Made with Slides.com