Symfony(2)Tour - Views Controllers Bundles
1. Twig Twig Twig
http://twig.sensiolabs.org/documentation
A Twig template is a text file that can generate any type of content (HTML, CSS, JavaScript, XML, CSV…)
{# array( ‘user’ => array(’name’ => ‘Fabien’)) #}
{{ user.name }}
or
{{ user[’name’] }}
{# array(‘user’ => new User(‘Fabien')) #}
{{ user.name }}
{{ user.getName() }}
Decorating Templates
layout.html.twig
<div>
{% block content %}
{% endblock %}
</div>
hello.html.twig
{% extends “AcmeDemoBundle::layout.html.twig” %}
{% block content %}
<h1>Hello {{ name }} !</h1>
{% endblock %}
Using Tags, Filters, and Functions
{{ article.title|trim|capitalize }}
This is really powerful, Embedding other Controllers
{# index.html.twig #}
{{ render(controller(“AcmeDemoBundle:Demo:topArticles”, {’num’: 10})) }}
Creating Links between Pages
<a href=“{{ path(‘_demo_hello’, { ’name’ : ‘Carl’ }) }}”>Go and have Fun!</a>
That name _demo_hello will match the name of the annotation in routing.
Including Assets: Images, JavaScripts and Stylesheets
<link rel="icon" sizes="16x16" href="{{ asset('favicon.ico') }}" />
<link rel="stylesheet" href="{{ asset('bundles/acmedemo/css/demo.css') }}" />
2. The Controller
Using Formats
Change the annotation as follow:
/**
* @Route("/hello/{name}", defaults={"_format"="xml"}, name="_demo_hello")
* @Template()
*/
public function helloAction($name)
{
return array('name' => $name);
}
Directly write some codes in the Twig template
<hello>
<name>{{ name }}</name>
</hello>
If we plan to support multiple format at one time, we need to add parameter in the routing.
The Routing annotation will changes as follow:
/**
* @Route(
* "/hello/{name}.{_format}",
* defaults={"_format"="html"},
* requirements = { "_format" = "html|xml|json"},
* name="_demo_hello")
* @Template()
*/
Redirecting and Forwarding
return $this->redirect($this->generateUrl(‘_demo_hello’, array(‘name’ =>”Sillycat’) ) );
return $this->forward(‘AcmeDemoBundle:Hello:index’, array(
‘name’ => $name,
‘color’ => ‘green'
));
Displaying Error Pages
404
throw $this->createNotFoundException();
500
throw new \Exception('Something went wrong!’);
It is very important to put \ before Exception.
Getting Information from the Request
If our action has an argument that type is Symfony\Component\HttpFoundation\Request, we can have the Request info.
use Symfony\Component\HttpFoundation\Request;
public function someAction(Request $request){
$request->isXmlHttpRequest(); //is it an Ajax request?
$request->query->get(‘page’); //get a $_GET parameter
$request->request->get(‘page’); //get a $_POST parameter
}
In the template, we can also access the variables in $request like this.
{{ app.request.query.get(‘page’) }}
{{ app.request.parameter(‘page’) }}
Persisting Data in the Session
HTTP protocol is stateless, between 2 requests, Symfony2 stores the attributes in a cookie by using native PHP sessions.
public function someAction(Request $request){
$session = $this->request->getSession();
$session->set(‘username’, ‘Carl’);
$username = $session->get(‘username’);
$username = $session->get(‘username’, ’DefaultName’); //get with default value
}
Before redirecting, we can store the Error Message/Successful Message in “Flash Messages”.
$session->getFlashBag()->add(‘’notice’,’congratulations,your action is succeeded!’);
In the template
<div> {{ app.session.flashbag.get(‘notice’) }} </div>
Caching Resources
Put that in the annotation right after @Template()
/**
* @Route(…)
* @Template()
* @Cache(maxage=“86400”)
*/
The unit for that cache configuration is second, 86400 is a day.
3. The Architecture
app - application configuration
src
vendor - the third-party dependencies
web - web root
3.1 How the PHP Controller Start
Controller will load the app/AppKernel.php, In side the AppKernel.php, it will provide at least 2 methods.
public function registerBundles()
{
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
);
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
$bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
}
return $bundles;
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
3.2 Understanding the Bundle System
Bundle is a plugin, it is called bundle because everything is a bundle in Symfony2. You can use pre-built features packaged in third-party bundles or distribute your own bundles.
Registering a Bundle
AppKernel — registerBundles()
Each bundle is a directory that contains a single Bundle class that describes it.
For example, in the src directory, we have Acme\DemoBundle\AcmeDemoBundle.php
<?php
namespace Acme\DemoBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AcmeDemoBundle extends Bundle
{
}
Then we have this line in the AppKernel.php
$bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
For the third party Bundle
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
vendor/symfony/symfony/src/Symfony/Bundle
Configuring a Bundle
Look at app/config/config.yml.
imports:
- { resource: parameters.yml }
- { resource: security.yml }
framework:
#esi: ~
#translator: { fallback: "%locale%" }
secret: "%secret%”
…snip…
# Twig Configuration
twig:
debug: "%kernel.debug%”
framework configures FrameworkBundle, twig configures TwigBundle.
DEV environment loads config_dev.yml and overwrites the config.yml.
Extending a Bundle
Logical File Names
@BUNDLE_NAME/path/to/file;
@AcmeDemoBundle/Controller/SecuredController.php
Logical Controller Names
BUNDLE_NAME:CONTROLLER_NAME:ACTION_NAME, for example, AcmeDemoBundle:Welcome:index
Logical Template Names
AcmeDemoBundle:Welcome:index.html.twig ——> src/Acme/DemoBundle/Resources/views/Welcome/index.html.twig
Extending Bundles
http://symfony.com/doc/current/cookbook/bundles/inheritance.html
Using Vendors
Symfony2 loads a lot of yaml and XML, we only do parse at the first request and then cache the plain PHP codes in app/cache. In the DEV environment, Symfony2 will flush the cache when we change a file.
But in the production environment, we take the responsibility to clear the cache.
app/logs/
Using the Command Line Interface
>php app/console --help
>php app/console -V
Symfony version 2.4.5 - app/dev/debug
>php app/console --env=dev server:run
This command default run PHP built-in server based on development environment.
Go further, read this book http://symfony.com/doc/current/book/index.html
References:
http://symfony.com/doc/current/quick_tour/the_view.html
http://symfony.com/doc/current/cookbook/bundles/inheritance.html
http://symfony.com/doc/current/book/index.html