Using Symfony Components


Stand-alone in any project


Confoo - February 23rd, 2022

© David Buchmann







David Buchmann - david@liip.ch

PHP Engineer, Liip AG, Switzerland

We are hiring: https://liip.ch/jobs

OH:

Symfony is this massive
PHP framework to build applications with.

Massive?

To full stack or not?

When to use components stand alone

Large systems like Drupal and Laravel use Symfony components

Overview

Component Ecosystem

Why bother to use any 3rd party component?

Not convenient to use stand alone

Reinvented Wheels

My personal opinion, you are free to disagree :-)

Utilities and components that solve a specific problem

Utilities: Do something small

Solving Specific Problems

OptionsResolver

OptionsResolver

Now how to implement this in your class?

Naive Approach

__construct(array $options = [])
{
  if (!\array_key_exists('ttl', $options)) {
    $options['ttl'] = 42;
  }
  ...
}
            

Drawbacks of the naive approach

Enter the OptionsResolver

$resolver = new OptionsResolver();
$resolver->setDefaults([
    'default_ttl' => 0,
]);
$resolver->setAllowedTypes(
    'default_ttl', ['int']
);
$this->config = $resolver->resolve($config);
            

Example on this and the next slides are from php-http/cache-plugin

OptionsResolver

=> There is no large cost in adding it to your dependencies.

OptionsResolver functionality

Custom normalizers

$resolver->setNormalizer(
    'respect_response_cache_directives',
    function (Options $options, $value) {
        if (false === $options['respect_cache_headers']) {
            return [];
        }

        return $value;
    }
);
            

Console

Console

PHP and the command line

Symfony Console gives you control over the console cursor:

https://github.com/dbu/php-snake


Lets look at some examples from the Doctrine ORM database abstraction layer.

Command

Set the name, description, arguments and options.

protected function configure()
{
  $this->setName('orm:run-dql')
    ->setDescription('Executes queries from the cli')
    ->addArgument('dql', InputArgument::REQUIRED, 'DQL...')
    ->addOption('em', null, InputOption::VALUE_REQUIRED,
        'Name of the entity manager to operate on')
    ->addOption('show-sql', null, InputOption::VALUE_NONE,
        'Dump generated SQL instead of executing query')
    ->setHelp('...');
}

bin/console orm:run-dql "select * from Model\User" --em=userdata

Arguments

Options

Command::execute

Read input

Input is the place to get options:

$em = $input->getOption('em') === null
    ? $this->emProvider->getDefaultManager()
    : $this->emProvider->getManager($input->getOption('em'))
;

And arguments:

$dql = $input->getArgument('dql');
            

Bootstrap the Console

Only needed when using console stand-alone. Minimal example from https://github.com/liip/varnish-plus-cli

#!/usr/bin/env php
<?php
require __DIR__.'/../vendor/autoload.php';
use App\Command\VclDeployCommand;
use App\Command\VclTwigCompileCommand;
use Symfony\Component\Console\Application;

$application = new Application('Varnish Plus CLI');
$application->add(new VclTwigCompileCommand());
$application->add(new VclDeployCommand());
$application->run();
        

Configuration Management

Interactive Commands

Use the QuestionHelper to interact with the user

if ($input->isInteractive()) {
    $question = 'Are you sure you wish to continue? (y/n)';
    $confirmation = $this->getHelper('question')->ask(
        $input,
        $output,
        new ConfirmationQuestion($question)
    );
    if ($confirmation) {
        $this->markVersions($input, $output);
    } else {
        $output->writeln('<error>Cancelled!</error>');
    }
}
        

Question Helper

ProgressBar Helper

Conclusion

For your next workflow, state machine, semaphores and locks in parallel processing and a bunch more standard concepts, check if you find a suitable Symfony component.

Thank you!







@dbu