Slide 1

Slide 1 text

OVERRIDING SYMFONY IN A MILLION WAYS Sarah Khalil

Slide 2

Slide 2 text

WHO AM I? ➤ Head of the ➤ Trainer and developer ➤ Enjoying sharer ➤ @saro0h

Slide 3

Slide 3 text

WHO AM I? ➤ Head of the ➤ Trainer and developer ➤ Enjoying sharer ➤ @saro0h @catlannister

Slide 4

Slide 4 text

ANY PLAN TODAY? ➤ Symfony Full Stack ➤ Override the structure ➤ Override everything in a bundle

Slide 5

Slide 5 text

GLOBALLY Override the Symfony default directory structure (and a little more)

Slide 6

Slide 6 text

➤ AppKernel ➤ Cache directory ➤ Log directory ➤ Web directory ➤ Vendor directory ➤ src directory ➤ bin directory ➤ environment parameters ➤ charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 7

Slide 7 text

AppKernel ➤ Cache directory ➤ Log directory ➤ Web directory ➤ Vendor directory ➤ src directory ➤ bin directory ➤ environment parameters ➤ charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 8

Slide 8 text

« Override "app"

Slide 9

Slide 9 text

« Override "app"

Slide 10

Slide 10 text

CHANGE THE NAME THE KERNEL // Symfony\Component\HttpKernel\Kernel public function getName() { if (null === $this->name) { $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir)); } return $this->name; } Change the name of the original app directory + requires statements in the front controllers. 1/4

Slide 11

Slide 11 text

CHANGE THE NAME THE KERNEL Change the prefix of the original appKernel class. 2/4

Slide 12

Slide 12 text

CHANGE THE NAME THE KERNEL In the composer.son file: 4/4 { "extra": { "symfony-app-dir": "ezpublish", "incenteev-parameters": { "file": "ezpublish/config/parameters.yml" } } }

Slide 13

Slide 13 text

AppKernel Cache directory ➤ Log directory ➤ Web directory ➤ Vendor directory ➤ src directory ➤ bin directory ➤ environment parameters ➤ charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 14

Slide 14 text

OVERRIDE THE CACHE DIRECTORY The cache sits in the app/cache folder. In the app/AppKernel class, you need to implement the getCacheDir(). // Symfony\Component\HttpKernel\Kernel public function getCacheDir() { return $this->rootDir.'/cache/'.$this->environment; }

Slide 15

Slide 15 text

AppKernel Cache directory Log directory ➤ Web directory ➤ Vendor directory ➤ src directory ➤ bin directory ➤ environment parameters ➤ charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 16

Slide 16 text

OVERRIDE THE LOG DIRECTORY The cache sits in the app/logs folder. In the app/AppKernel class, you need to implement the getLogDir(). // Symfony\Component\HttpKernel\Kernel public function getLogDir() { return $this->rootDir.'/logs'; }

Slide 17

Slide 17 text

AppKernel Cache directory Log directory Web directory ➤ Vendor directory ➤ src directory ➤ bin directory ➤ environment parameters ➤ charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 18

Slide 18 text

OVERRIDE THE WEB DIRECTORY 1. Make sure that the path to the app/ directory of your application is correct for the required files in your front controller (app.php|app_dev.php) 2. Change extra.symfony-web-dir in the composer.son file your application: 1/3 $loader = require_once __DIR__.'/../app/bootstrap.php.cache'; require_once __DIR__.'/../app/AppKernel.php'; { ... "extra": { ... "symfony-web-dir": "my_new_web_dir" } } http://symfony.com/doc/current/cookbook/configuration/override_dir_structure.html#override-the-web-directory

Slide 19

Slide 19 text

OVERRIDE THE WEB DIRECTORY (WITH A SHARED HOST) Option a: Override the web folder of your application to the one that is exposed by the shared host (www | public_html folder). Option b : Create a symbolic link from the web directory to the directory that is « exposed » by the shared host (www | public_html folder). 2/3 http://symfony.com/doc/current/cookbook/configuration/override_dir_structure.html#override-the-web-directory

Slide 20

Slide 20 text

OVERRIDE THE WEB DIRECTORY (WITH ASCETIC USED) You also need to override the assetic.read_from configuration parameter to target the new web directory you changed: 3/3 assetic: # ... read_from: "%kernel.root_dir%/../../public_html" Don’t forget to clear the cache!

Slide 21

Slide 21 text

AppKernel Cache directory Log directory Web directory Vendor directory ➤ src directory ➤ bin directory ➤ environment parameters ➤ charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 22

Slide 22 text

OVERRIDE THE VENDOR DIRECTORY 1. Override the config.vendor-dir in the composer.json file. 2.Override the path to the vendor directory in the app/autoload.php: { ... "config": { ... "vendor-dir": "/some/dir/vendor" }, ... } $loader = require '/some/dir/vendor/autoload.php';

Slide 23

Slide 23 text

« This modification can be of interest if you are working in a virtual environment and cannot use NFS. Ex: if you're running a Symfony application using Vagrant/VirtualBox in a guest operating system. -Symfony documentation

Slide 24

Slide 24 text

AppKernel Cache directory Log directory Web directory Vendor directory src directory ➤ bin directory ➤ environment parameters ➤ charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 25

Slide 25 text

CHANGE BUNDLES’ FOLDER Originally: Override: { "autoload": { "psr-0": { "": "src/" } } } { "autoload": { "psr-4": { "": "src/" } } } { "autoload": { "psr-0": { "": "newFolder/" } } } { "autoload": { "psr-4": { "": "newFolder/" } } } $ composer dumpautoload

Slide 26

Slide 26 text

AppKernel Cache directory Log directory Web directory Vendor directory src directory bin directory ➤ environment parameters ➤ charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 27

Slide 27 text

CHANGE THE BIN FOLDER Originally: Override: { "config": { "bin-dir": "bin" } } { "config": { "bin-dir": "exec" } }

Slide 28

Slide 28 text

AppKernel Cache directory Log directory Web directory Vendor directory src directory bin directory Environment parameters ➤ charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 29

Slide 29 text

OVERRIDE THE ENVIRONMENT VARIABLES ➤ All environment variables begin with SYMFONY__ ➤ In the app/AppKernel class, implement getEnvParameters (call the parent first). // Symfony\Component\HttpKernel\Kernel protected function getEnvParameters() { $parameters = array(); foreach ($_SERVER as $key => $value) { if (0 === strpos($key, 'SYMFONY__')) { $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value; } } return $parameters; }

Slide 30

Slide 30 text

AppKernel Cache directory Log directory Web directory Vendor directory src directory bin directory Environment parameters Charset ➤ session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 31

Slide 31 text

CHANGE THE CHARSET ➤ In the app/AppKernel class, you need to implement the getCharset(). // Symfony\Component\HttpKernel\Kernel public function getCharset() { return 'UTF-8'; }

Slide 32

Slide 32 text

AppKernel Cache directory Log directory Web directory Vendor directory src directory bin directory Environment parameters Charset Session folder ➤ config files https://www.flickr.com/photos/rotscher/

Slide 33

Slide 33 text

OVERRIDE THE SESSION STORAGE FOLDER Originally: Override: framework: session: handler_id: session.handler.native_file save_path: "%kernel.cache_dir%/sessions" framework: session: handler_id: session.handler.native_file save_path: "%kernel.root_dir%/sessions"

Slide 34

Slide 34 text

AppKernel Cache directory Log directory Web directory Vendor directory src directory bin directory Environment parameters Charset Session folder Config files https://www.flickr.com/photos/rotscher/

Slide 35

Slide 35 text

OVERRIDE THE CONFIGURATION FILE Override the folder, the name of the file… // app/config/AppKernel.php public function registerContainerConfiguration(LoaderInterface $loader) { $loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml'); }

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

OVERRIDE BUNDLE Override everything you can find in a bundle.

Slide 41

Slide 41 text

➤ Routes ➤ Templates ➤ Controllers ➤ Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 42

Slide 42 text

➤ Routes ➤ Templates ➤ Controllers ➤ Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 43

Slide 43 text

Routes ➤ Templates ➤ Controllers ➤ Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 44

Slide 44 text

Routes ➤ Templates ➤ Controllers ➤ Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 45

Slide 45 text

« You have 2 options.

Slide 46

Slide 46 text

LET’S SAY YOU NEED TO OVERRIDE THE ROUTES OF THE FOSUSERBUNDLE FOR YOUR OWN BUNDLE

Slide 47

Slide 47 text

EASIEST WAY ➤Don’t import the routes of the FOSUserBundle in your app/ config/routing.yml file. ➤Copy / Paste all the routes from FOSUserBundle in your app/config/routing.yml file and modify if directly. Option 1 http://symfony.com/doc/current/cookbook/bundles/override.html#routing

Slide 48

Slide 48 text

« WORKING WITH RESOURCES » WAY 1. Import the routes of the FOSUserBundle in your app/ config/routing.yml file. 2. Create a new routing file following this pattern: •app/Resources/BundleName/path/to/routing/file/to/override.extension •exemple : in app/Resources/FosUserBundle/config/routing/all.xml 3. In there, override the routes you need to. Option 2 # app/config/routing.yml fos_user: resource: "@FOSUserBundle/Resources/config/routing/all.xml" If you refer to resources without using the @BundleName shortcut, they can't be overridden in this way.

Slide 49

Slide 49 text

Routes Templates ➤ Controllers ➤ Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 50

Slide 50 text

Routes Templates ➤ Controllers ➤ Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 51

Slide 51 text

OVERRIDE A TEMPLATE Let’s say you need to override the following file: vendor/Symfony/…/TwigBundle/Resources/ views/Exception/error.html.twig

Slide 52

Slide 52 text

« You have 2 options.

Slide 53

Slide 53 text

OVERRIDE A TEMPLATE You need to create the following file: app/Resources/TwigBundle/views/Exception/ error.html.twig

Slide 54

Slide 54 text

HOW IT WORKS? (« WORKING WITH RESOURCES WAY ») Create: app/Resources/TwigBundle/views/Exception/error.html.twig Option 1

Slide 55

Slide 55 text

HOW IT WORKS? (« WORKING WITH RESOURCES WAY ») When calling the AcmeBlogBundle:Blog:index.html.twig logical path, Symfony looks in the following places (respectively): 1.app/Resources/TwigBundle/views/Exception/error.html.twig 2.[…]/TwigBundle/Resources/Exception/Exceptions/ error.html.twig Option 1 http://symfony.com/doc/current/book/templating.html#overriding-bundle-templates

Slide 56

Slide 56 text

OVERRIDE A TEMPLATE (USING BUNDLE INHERITANCE) 1. Implement the method getParent() in the bundle class. 2. Recreate the file under the same arborescence: Option 2 // src/AppBundle/AppBundle.php public function getParent() { return 'TwigBundle'; } src/AppBundle/Resources/views/Exception/error.html.twig http://symfony.com/doc/current/cookbook/bundles/inheritance.html#overriding-resources-templates-routing-etc

Slide 57

Slide 57 text

Routes Templates Controllers ➤ Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 58

Slide 58 text

Routes Templates Controllers ➤ Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 59

Slide 59 text

OVERRIDE A CONTROLLER ➤ Let’s say you need to override the showAction of the TwigBundle: // Symfony\Bundle\TwigBundle\Controller\ExceptionController public function showAction( Request $request, FlattenException $exception, DebugLoggerInterface $logger = null ){ // Some logic and returns a response }

Slide 60

Slide 60 text

OVERRIDE A CONTROLLER (USING THE BUNDLE INHERITANCE) 1. Implement the method getParent() in your bundle class. 2. Create the src/AppBundle/Controller/ExceptionController.php with the showAction. 3. (Optional) Extends from the ExceptionController to be able to call the parent::showAction(), get the response and modify it as you need. // src/AppBundle/AppBundle.php public function getParent() { return 'TwigBundle'; }

Slide 61

Slide 61 text

To be able to override the controller that way, it must be referenced as the following: TwigBundle:Exception:show

Slide 62

Slide 62 text

Routes Templates Controllers Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 63

Slide 63 text

Routes Templates Controllers Services ➤ Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 64

Slide 64 text

4 OPTIONS…

Slide 65

Slide 65 text

4 OPTIONS… And no, I won’t show you all of them ;)

Slide 66

Slide 66 text

COMPILER PASS http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html 1

Slide 67

Slide 67 text

DECORATION OF SERVICE 2

Slide 68

Slide 68 text

DECORATION OF SERVICE bar: public: false class: stdClass decorates: foo arguments: ["@bar.inner"] http://symfony.com/doc/current/components/dependency_injection/advanced.html#decorating-services

Slide 69

Slide 69 text

Routes Templates Controllers Services Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 70

Slide 70 text

Routes Templates Controllers Services Configuration ➤ Forms ➤ Validation ➤ Translation

Slide 71

Slide 71 text

« You have 2 options.

Slide 72

Slide 72 text

OVERRIDE THE CONFIGURATION The config_[your_env].yml is imported in the registerContainerConfiguration() method in the app/appKernel class. It is read from top to bottom. If a configuration variable is declared, you can override it after it. That’s basically what it is done with the config.yml file and the config_[your_env].yml Option 1

Slide 73

Slide 73 text

OVERRIDE THE CONFIGURATION 1. Create a compiler pass. 2. As you get the containerBuilder, you can use the method setParameter($name, $value). Option 2

Slide 74

Slide 74 text

Routes Templates Controllers Services Configuration Forms ➤ Validation ➤ Translation

Slide 75

Slide 75 text

Routes Templates Controllers Services Configuration Forms ➤ Validation ➤ Translation

Slide 76

Slide 76 text

OVERRIDE A TYPE (REPLACE IT) You need to declare the original type as a service, that way, you can override it as explained in the service chapter. Option 1

Slide 77

Slide 77 text

OVERRIDE A TYPE (DYNAMIQUE INHERITANCE) Option 2 namespace AppBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; class RegistrationFormType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('name'); $builder->remove('surname'); } public function getParent() { return 'fos_user_registration'; } public function getName() { return 'app_user_registration'; } }

Slide 78

Slide 78 text

Routes Templates Controllers Services Configuration Forms Validation ➤ Translation

Slide 79

Slide 79 text

Routes Templates Controllers Services Configuration Forms Validation ➤ Translation

Slide 80

Slide 80 text

OVERRIDE THE VALIDATION OF A FIELD ➤Symfony loads all validation configuration files from every bundle and combines them into one validation metadata tree. ➤This means you are able to add new constraints to a property, but you cannot override them. http://symfony.com/doc/2.3/cookbook/bundles/override.html#validation-metadata

Slide 81

Slide 81 text

OVERRIDE A VALIDATION CONFIGURATION Add new validation constraint in the bundle that is overriding the original with the same validation group.

Slide 82

Slide 82 text

FOS\UserBundle\Model\User: properties: plainPassword: - NotBlank: groups: [Registration] - Length: min: 6 minMessage: fos_user.password.short groups: [Registration]

Slide 83

Slide 83 text

Routes Templates Controllers Services Configuration Forms Validation Translation

Slide 84

Slide 84 text

Routes Templates Controllers Services Configuration Forms Validation Translation

Slide 85

Slide 85 text

« You have 2 options.

Slide 86

Slide 86 text

OVERRIDE A TRANSLATION FILE It’s all about domains! (messages.en.xlf) 1.All you need to do is to recreate the translation file in YourBundle/Resources/translations. 2.Make sure that your bundle is loaded before the original bundle (no bundle inheritance). Option 1

Slide 87

Slide 87 text

OVERRIDE A TRANSLATION FILE Translation files are resources! Create the same file in the app/Resources/translations folder. Option 2

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

REMARKS

Slide 90

Slide 90 text

➤You can use event listeners|subscribers to override controllers (kernel.controller). ➤You can use the app/autoload.php file to override classes. ➤You could use other options according to the thing you need to override…

Slide 91

Slide 91 text

PARICON2015.SYMFONY.COM

Slide 92

Slide 92 text

Thank you! @saro0h speakerdeck.com/saro0h/ This is a zero guys! saro0h