Symfony: config to prod

This chapter is the suite of Symfony: config file secret

since the default is in dev env, how could we change to prod env?

That’s dig out:

Step 1 Chang env file

go to the root of your project, directly open the

.env file, and change 




Step 2 clear cache of Symfony

you need to clear cache in Symfony, go to terminal and type:

$ ./bin/console cache:clear

you should be able see follow screen:

in this step you reload back your browser, you should be not see the debug bar as showed in dev env:

Step 3 Change the content

go to template/article/homepage.html

that’s change the French Fries :

line 65, changed to French Fries to Prod:

<p><span class="advertisement-text">New:</span> French Fries to Prod!</p>

and reload, you will see this is not changed at all, this is special in symfony which you had to clear catch each time once change env,

so go to terminal : $ ./bin/console cache:clear

then back your browser, yes!!!! you will able to see it does change:

Key point: in symfony 4, recommand to use: ./bin/console cache:warmup, here is the doc

voila, and once you want to go back dev env,
follow the same procedure: env:dev-> $ ./bin/console cache:warmup -> refresh your browser then you could see your debug_bar is back :

Symfony twig template for usage 2

well, this is just the extend this chapter
This is basic the same logical except we had the menu link and related page data load

That’s add the menu part: about

so basic what like to do here:

1 we like to click this menu and go to about page by this path:

2 Inside about page, we like the list the heading and content part

output result:

so that’s start:

Step 1 Add MenuController
go to src/Controller add this file: MenuController.php

the logic is the same, we need the route has /about, so add this part in symfony notation:

 * @Route("/about", name="app_aboutpage")

and write a aboutpage function, this function has define variable called $headings, which has title and content
then we rendre the twig template and $heading variable :

namespace App\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class MenuController extends AbstractController
     * @Route("/about", name="app_aboutpage")
    public function aboutpage()
        $headings = [
            'burger1' => 'I ate a normal rock once. It did NOT taste like bacon!',
            'burger2' => 'Woohoo! I\'m going on an all-asteroid diet!',
            'burger3' => 'I like bacon too! Buy some from my site!',
        return $this->render('article/aboutpage.html.twig', array(
            'headings' => $headings,

Step 2 Add twig template

go to template/article
add a twig template called: aboutpage.html.twig

we merge the extends base and write the layout between body block:
{% extends ‘base.html.twig’ %}
{% block body %}
{% endblock %}

Step 3 Called the data from MenuController

use twig for filtre, and us your variable $headings(key, value) to show the heading and content part:

<div class="row">
    {% for key, heading in headings %}
    <div class="col-lg-4">
        <img class="rounded-circle" src="{{ asset('images/asteroid.jpeg') }}" alt="Generic placeholder image" width="140" height="140">
        <h2>{{ key }}</h2>
        <p>{{ heading }}</p>
        <p><a class="btn btn-secondary" href="#" role="button">View details &raquo;</a></p>
    </div><!-- /.col-lg-4 -->
    {% endfor %}
</div><!-- /.row -->

Step 4 update the link path
go to templates/base.html.twig
change about link href part:

<a style="color: #fff;" class="nav-link" href="{{ path('app_aboutpage') }}">About</a>

Go to your page, then you should be able the see the output as show above

here is the github commit link

Symfony: config file secret

That’s explore more Symfony config directory doing here

Go to config file, you will see there’s basic 2 files: packages, routes, and others files:

as symfony is a set of routes & services , config file is actually configure those services

and before this, that’s dig first Symfony environment

there’s 2 env by default: dev and prod , and you could have test too if you like to add other env

And, how env work?

Go to see public/ index.php

line 18

$env = $_SERVER['APP_ENV'] ?? 'dev';

This env variable is set to either have APP_ENV or dev

And it pass to Kernel class:

$kernel = new Kernel($env, $debug);

so find out Kernel class, which is in src/Kernel.php

look 3 methods:
registerBundles(), configureContainer() and configureRoutes()

this method is once you had installed the new bundles, it will loads to config/bundles.php file:

return [
    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
    Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
    Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
    Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
    Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
    Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
    Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],

and some are load to all, some load to dev, or test env:

Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],

And 2 method: configureContainer()

this is package file loading, which load the into config/packages file or config/service.yaml or config/service_xxx.yaml:

with CONFIG_EXTS constant:

const CONFIG_EXTS = '.{php,xml,yaml,yml}';

it’s load any PHP, XML, YAML. YML files

if it has to load to packages file, it will load into dev, prod or test env by bundles.php definition

And 3rd method: configureRoutes()
basiclly do the same thing, except to the routes file:

protected function configureRoutes(RouteCollectionBuilder $routes)
    $confDir = $this->getProjectDir().'/config';

    $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
    $routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
    $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');

So here it is the core bundle: services ( tools ) where path to go and set to which env by Symfony

and why do we know about this?

well, it will be happend that you might need to change those bundles from dev env to prod env, so if you know those core concept it will get easier to change the env as it is required

Symfony: installed your first bundle

Here you will learn how to installed bundles

what is bundle in symfony?
bundle is like a plugin, which provide service, and remember: service == tools

so there’s lot buddle to use, mostly you could found in this github page

so which bundle you should install and in what circumstance?
Honestly I do not very clair ideal either, what you should do is go to the link and read the document

and try it!!

Step 1 install one bundle

I found the basic usage bundle called: Monolog – Logging for PHP

here is github link

Go to the document page
And go to your terminal and type :

$ composer require logger

once installed you should be see the changed in your composer.json file :

"symfony/monolog-bundle": "^3.2",

Step 2 check the autowiring

go back to terminal

./bin/console debug:autowiring

then you should be able see you had add alias to monolog.logger

great, basic we had installed successful

Step 3 Injection class to test

go to your src/Controller/ArticleController.php

tried in function toggleArticleStar to inject LoggerInterface, give the varialbel called $logger

public function toggleArticleStar($slug, LoggerInterface $logger)

then return the message:so show the loggerInterface

$logger->notice('so show the loggerInterface');

go to your endPoint star part and click, then go to this file:


So yes!!! you you see the log is right here

This is just one of example bundle usage, and my first too, I hope you guys could get the point from this chapter and me too, way long to learn


Symfony twig template for usage

For iterate data there’s happend quiet often to use for each

Extra: how to use symfony twig for?

that’s take example in our previous chapter:

Remember we had planter a article view page which has user’s comments below ?

what we like to do here, is make the output should be like follow:

to make load the names and comments load dynamic with for loop twig

that’s do it:

step 1 add data in controller
go to src/Controller/ArticleController.php

in public show function
modified the variable comments data with key value, which key == name, value == comment

 $comments = [
            'tess hsu' => 'I ate a normal rock once. It did NOT taste like bacon!',
            'Stephan' => 'Woohoo! I\'m going on an all-asteroid diet!',
            'Alexandre Frank' => 'I like bacon too! Buy some from my site!',

So here we had name to assign the comment with

step 2 Add for method in twig tag

go to template/article/show.html.twig

find the div has comment list:

{% for comment in comments %}
    <div class="row">
        <div class="col-sm-12">
            <img class="comment-img rounded-circle" src="{{ asset('images/alien-profile.png') }}">
            <div class="comment-container d-inline-block pl-3 align-top">
                <span class="commenter-name">Mike Ferengi</span>
                <span class="comment"> {{ comment }}</span>
                <p><a href="#">Reply</a></p>
{% endfor %}

And changed Iterating over Keys and Values

{% for key, comment in comments %}
    <div class="row">
        <div class="col-sm-12">
            <img class="comment-img rounded-circle" src="{{ asset('images/alien-profile.png') }}">
            <div class="comment-container d-inline-block pl-3 align-top">
                <span class="commenter-name"> {{ key }}</span>
                <span class="comment"> {{ comment }}</span>
                <p><a href="#">Reply</a></p>
{% endfor %}

and go to see your page, it should be show correctly

github commit here

Symfony service

Services is the fundamental part of Symfony

That’s make the definition much simple: service like an object ( class, method) that allow to access more functionalités like sending email, sending data or logger messages, so the basic concept for services == tools

So beside the basic Symfony elements: router, twig and logger object, you could always get more tricks to do more stuff by service

so that’s review back what is basic Symfony:

Allright, then we go to further to add service, but where could we find out those services available ?

go to terminal, type:

$  php bin/console debug:autowiring

how does those use in the symfony?

well, take example what we had done in last couple tutorials,

Step 1 find the service

go to src/Controller/ArticleController.php

in the top of page:

Yes, you will find :

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;

and this are actually in the list of Autowirable Services:



Step 2 inject service in your class parametre

public function toggleArticleStar($slug, LoggerInterface $logger)

type logger it will autowriting LoggerInterface, and name an object called logger

as typing there’s already auto-writing lists of functions:


$logger->info('this is been rating');

Stop the server running, you should be able to see this message in terminal:


Voila, this is the first service usage!!

Here is the github commit part



Symfony add Js & Ajax

Now next, that’s make more reaction between page and users

Remember what is the article page looks like ?

look at the start icon, that’s allow user rating the article

so we need to make user click the start and add the numbers of clicks,

to make it work, it require :

1. Jquery onclick event

2 Send an Ajax to an API endpoint to count start

So that’s start:

Step 1 Add Jquery

go to templates/base.html.twig

Add the jquery library on the footer:

{% block javascripts %}
    <script src="" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
    <script src="" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
    <script src="" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
{% endblock %}

then In the public/ directory, create a new js/ directory and a file inside called show_rating.js.

Add follow code:

$(document).ready(function() {
    $('.js-like-article').on('click', function(e) {
        var _self = this;

use toggleClass to bind the icon start change, so far we finish the start change color binding event part,

and final remember since you just want this action use this js file, go to


in the footer add follow:

{% block javascripts %}
    {{ parent() }}
    <script src="{{ asset('js/show_rating.js') }}"></script>
{% endblock %}

we need to inhirent the parent js file too,

{{ parent() }} do this work

This will print the parent template’s block content first, and then it should be work:

click start:

Step 2 Get A Json encode Star object ( Serializer)

To do this we could add a function called toggleArticleHeart, and this funtion will return new json response

Go to src/Controller/ArticleController.php

 * @Route("/news/{slug}/heart", name="article_toggle_star", methods={"POST"})
public function toggleArticleStar($slug)
    return new JsonResponse(['hearts' => rand(5, 100)]);

what doing here is add Route url, and path name as article_toggle_star, method is poste

inside the toogleArticleStar, it has return the Json Response with starts data

To check if the send method is updated,

use this comment in terminal:

./bin/console debug:route

as you could see article_toggle_star function is POST and Path is :


in order to check the json object is available, change GET methode instead, and add JsonResponse in the header of ArticleController.php

use Symfony\Component\HttpFoundation\JsonResponse;


 * @Route("/news/{slug}/star", name="article_toggle_star", methods={"POST"})
public function toggleArticleStar($slug)
    return new JsonResponse(['starts' => rand(5, 100)]);

Go to template/article/show.html.twig

find your star icon code and change href path:


Go back your browser re-run with this path:{slug}/star

you should got follow page like:

Great!! you could now use this json object and send Ajax in Jquery

Step 3 Send Ajax endpoint

this step is you need to send ajax called

so first go to template/article/show.html.twig
and add this right after star icon class

<span class="js-like-article-count"></span>

give this number a class

this is for js binding with ajax done promise:

    method: 'POST',
    url: $(this).attr('href')
}).done(function(data) {

here once click star icon, it will also called ajax called with POST method, once finished it will update stars value, which is randon number between 5-100


once you had done, go to your browser you should be able see:


here is github code commit differ here


Symfony Assets function for css & Js

What next now, it’s decorate your web page, and some animation or dynamical binding events

so here we need inject css and javascript

that’s start

Step 1 put your front end file in public directory

well, front end file means: css, fonts, images

so here you could create any style you like, put under public directory

Step 2 find the stylesheets block and add a link tag

Normally you could add link with follow:

But it’s much better do this with symfony web pack, which called asset() function,
asset() function will give us more flexibility to version our assets or store them on a CDN
so you could easily replace with follow code:

<link rel="stylesheet" href="{{ asset('css/font-awesome.css') }}">
<link rel="stylesheet" href="{{ asset('css/styles.css') }}">

reload the page, and oppsssss, you will see the error:

don’t worry, that install asset

Step 3 Install asset
go to terminal and install:

$composer require asset

Viola, and personalise your page style, here is example:

Here is github code

Symphony Debug tool

Once we had template twig to easy our web page work, debug tool is necessary,

Fatal Error

Remember this is quiet often as we try to look debug message? but never got the point easily, so symphony has think of this part too

that’s start:

Step 1 install profiler-pack

Profile-pack is like the web debug toolbar with a fusion reactor taped onto it
type this command:
$ composer require profiler –dev

you should be able to see follow screen, then you are done:

In composer.json

"require-dev": {
    "symfony/dotenv": "^4.0",
    "symfony/profiler-pack": "^1.0"

you could see that profile rendre dev env for debug pack, once run again and go back your browser

you will found follow under your page:

from this bar, you can also get detailed info about caching, routing and events

step 2 inject debug function

More cool thing is you could add native function that really easy to get debug mode:


So here you could add follow:

public function show($slug)
        dump($slug, $this);
        $comments = [
            'I ate a normal rock once. It did NOT taste like bacon!',
            'Woohoo! I\'m going on an all-asteroid diet!',
            'I like bacon too! Buy some from my site!',
        return $this->render('article/show.html.twig', [
            'title' => ucwords(str_replace('-', ' ', $slug)),
            'comments' => $comments,

And go back the browser, you should be able see this:

Also you could go to the debug page:

click the debug_bar the page name part:

then you should be able to view this page:

here has all the information you need, like Performance, Logs, Events, Routing etc

And that”s it, here you could see the all the related container class, file path, which is really useful if you need to debug

that’s try out, in show.html.twig file, make title part syntax error,

then go to the browser:

voila, here you had really good interface to list your error from
This is pretty big help!!


symfony Twig template basic set up

This is going to more fun part: Twig template

The basic concept to use Twig because as develop web we need to return lot html result ( yes, view part)

basiclly Twig syntag only follow 3 of those:

More we use Controller to build to bridge between Model and View part

but in symfony the most key is Controller and route, remember ?

Ok, cut it short, that’s start

Step 1  Installed Twing

go to terminal ( keep in your project directory) , then type

composer require twig

you should able see it is installed successful:

And from file directory, you could see what had add and changed ( red part) because of this installation ( thanks phpStorm)

Step 2  Controller part

go to src/Controller/ArticleController.php

Add a function called show and return an article title and comments

Key: a controller can return anything

here is the code:

     * @Route("/news/{slug}")
    public function show($slug)
        $comments = [
            'I ate a normal rock once. It did NOT taste like bacon!',
            'Woohoo! I\'m going on an all-asteroid diet!',
            'I like bacon too! Buy some from my site!',
        return $this->render('article/show.html.twig', [
            'title' => ucwords(str_replace('-', ' ', $slug)),
            'comments' => $comments,

And it is important to add extend for your class:

class ArticleController extends AbstractController

this gives you shortcut methods! The one we want is return $this->render(). show function inside render function Pass it a template filename: article/show.html.twig to be consistent with the controller name. The second argument is an array of variables that you want to pass into your template

Step 3 your template twig file

go to templates/article, create file called: show.html.twig

it should be create this directory once you installed twig, if not create one

And first we need to extends base.html.twig ( this is the default file you will get once installed twig)

with {% ….. %} , it means do something

It’s always has endblock

And go to show.html.twig file


{% extends 'base.html.twig' %}

And we want show title and comments

<h1>{{ title }}</h1>

for comments part, you could use loop by for in :

    {% for comment in comments %}
        <li>{{ comment }}</li>
    {% endfor %}

Here is all the file:

{% extends 'base.html.twig' %}
{% block title %}Read: {{ title }}{% endblock %}
{% block body %}
    <h1>{{ title }}</h1>
            Bacon ipsum dolor amet filet mignon picanha kielbasa jowl hamburger shankle biltong chicken turkey pastrami cupim pork chop. Chicken andouille prosciutto capicola picanha, brisket t-bone. Tri-tip pig pork chop short ribs frankfurter pork ham. Landjaeger meatball meatloaf, kielbasa strip steak leberkas picanha swine chicken pancetta pork loin hamburger pork.
            Kielbasa pork belly meatball cupim burgdoggen chuck turkey buffalo ground round leberkas cow shank short loin bacon alcatra. Leberkas short loin boudin swine, ham hock bresaola turducken tail pastrami picanha pancetta andouille rump landjaeger bacon. Pastrami swine rump meatball filet mignon turkey alcatra. Picanha filet mignon ground round tongue ham hock ball tip tri-tip, prosciutto leberkas kielbasa short loin short ribs drumstick. Flank pig kielbasa short loin jerky ham hock turducken prosciutto t-bone salami pork jowl.
            Pastrami short loin pork chop, chicken kielbasa swine turducken jerky short ribs beef. Short ribs alcatra shoulder, flank pork chop shankle t-bone. Tail rump pork chop boudin pig, chicken porchetta. Shank doner biltong, capicola brisket sausage meatloaf beef ribs kevin beef rump ribeye t-bone. Shoulder cupim meatloaf, beef kevin frankfurter picanha bacon. Frankfurter bresaola chuck kevin buffalo strip steak pork loin beef ribs prosciutto picanha shankle. Drumstick prosciutto pancetta beef ribs.
    <h2>Comments ({{ comments|length }})</h2>
        {% for comment in comments %}
            <li>{{ comment }}</li>
        {% endfor %}
{% endblock %}


your web should be look like follow:

Next we will go through debug tool by symfony