workshop: symfony2 intruduction: (controller, routing, model)
DESCRIPTION
Slides from workshop: Symfony2 Intruduction at eZ Publish STRANSCRIPT
![Page 1: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/1.jpg)
Workshop: Symfony2 introduction
Antonio Perić-Mažar, CEOLuka Vidoš, Frontend Dev
04.09.2013, eZ Publish Summer Camp
![Page 2: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/2.jpg)
Who we are?
• locastic – since 2010• Web and mobile development• UI/UX design
• Located in Split, Croatia• 9 team members
• www.locastic.com• [email protected]
![Page 3: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/3.jpg)
Our works?
![Page 4: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/4.jpg)
Speakers?
• Antonio Perić-Mažar, mag. ing. comp.
• CEO and partner @ locastic• Last 6 years developing
custom web apps• Last 3 years developing
custom apps with Symfony
• www.locastic.com• [email protected]• twitter: @antonioperic
![Page 5: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/5.jpg)
Speakers?
• Luka Vidoš, mag. Diz.• Frontend Dev @ locastic● Last 13 years designing, slicing
and implementing beautiful web design into various web apps
● In love with Symfony for last 3 years
• www.locastic.com• [email protected]• twitter: @lukavidos
![Page 6: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/6.jpg)
Symfony is project● PHP framework● Philosophy● Community
• Fabien Potencier, SensioLabs (France)
• 2005. first version was relased• 2007. symfony 1.0• 2011. Symfony2• ATM Symfony 2.3.4 (LTS)
![Page 7: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/7.jpg)
10 criteria for choosing the correct framework1. Popularity and community size2. Philosophy3. Sustainability4. Support5. Technique6. Security7. Documentation ( always can be better )8. License (free)9. Availability of resources on the market10. Try it out!
![Page 8: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/8.jpg)
6 good reasons to use Symfony
1. Reputation2. Permanence3. References (Yahoo!, Dailymotion, Opensky.com, Exercise.com, phpBB, Drupal,
eZPublish, Youporn :) )
4. Innovation5. Resources6. Interoperability
![Page 9: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/9.jpg)
The technological benefits of Symfony in 6 easy lessons1. Faster and less greedy2. Unlimited flexibility3. Expandable4. Stable and sustainable5. The joy of developing6. Ease of use
![Page 10: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/10.jpg)
Symfony2 community
• Github – 10 000+ commits, 5 branches, 50 releases, 746 contributors
● 1898 open source Bundles (http://knpbundles.com/)
• Symfony2 CMF (Content Management Framework), eZpublish, Drupal, Sylius
![Page 11: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/11.jpg)
What are we going to do today?
![Page 12: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/12.jpg)
What are we going to do today?
![Page 13: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/13.jpg)
What are we going to do today?
![Page 14: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/14.jpg)
To do list app
● Creating unlimited number of task lists● Creating, deleting and updating lists● Creating, deleting and updating tasks inside of
lists
![Page 15: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/15.jpg)
Let's go... How to install Sf2?
![Page 16: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/16.jpg)
Instalation: Option A
http://getcomposer.org/
> php -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));"
> php composer.phar> php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony 2.3.0
![Page 17: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/17.jpg)
Instalation: Option B
Download, Extract, Start
![Page 18: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/18.jpg)
Done!
![Page 19: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/19.jpg)
What is inside?
![Page 20: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/20.jpg)
What is inside?
> php app/console
![Page 21: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/21.jpg)
Standalone Tools: The Symfony2 ComponentsHttpFoundation - Contains the Request and Response classes, as well as other classes for handling
sessions and file uploads;
Routing - Powerful and fast routing system that allows you to map a specific URI (e.g. /contact) to some information about how that request should be handled (e.g. execute the contactAction() method);
Form - A full-featured and flexible framework for creating forms and handling form submissions;
Validator A system for creating rules about data and then validating whether or not user-submitted data follows those rules;
ClassLoader An autoloading library that allows PHP classes to be used without needing to manually require the files containing those classes;
Templating A toolkit for rendering templates, handling template inheritance (i.e. a template is decorated with a layout) and performing other common template tasks;
Security - A powerful library for handling all types of security inside an application;
Translation A framework for translating strings in your application.
![Page 22: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/22.jpg)
Coding standardStructure
● Add a single space after each comma delimiter;● Add a single space around operators (==, &&, ...);● Add a comma after each array item in a multi-line array, even after the last one;● Add a blank line before return statements, unless the return is alone inside a statement-group (like an if
statement);● Use braces to indicate control structure body regardless of the number of statements it contains;● Define one class per file - this does not apply to private helper classes that are not intended to be instantiated
from the outside and thus are not concerned by the PSR-0 standard;● Declare class properties before methods;● Declare public methods first, then protected ones and finally private ones;● Use parentheses when instantiating classes regardless of the number of arguments the constructor has;● Exception message strings should be concatenated using sprintf.
![Page 23: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/23.jpg)
Coding standardNaming Conventions
● Use camelCase, not underscores, for variable, function and method names, arguments;● Use underscores for option names and parameter names;● Use namespaces for all classes;● Prefix abstract classes with Abstract. Please note some early Symfony2 classes do not follow this convention and
have not been renamed for backward compatibility reasons. However all new abstract classes must follow this naming convention;
● Suffix interfaces with Interface;● Suffix traits with Trait;● Suffix exceptions with Exception;● Use alphanumeric characters and underscores for file names;● Don't forget to look at the more verbose Conventions document for more subjective naming considerations.
![Page 24: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/24.jpg)
Coding standardService Naming Conventions
● A service name contains groups, separated by dots;● The DI alias of the bundle is the first group (e.g. fos_user);● Use lowercase letters for service and parameter names;● A group name uses the underscore notation;● Each service has a corresponding parameter containing the class name, following the SERVICE
NAME.class convention.
Documentation
● Add PHPDoc blocks for all classes, methods, and functions;● Omit the @return tag if the method does not return anything;● The @package and @subpackage annotations are not used.
![Page 25: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/25.jpg)
Coding standardnamespace Acme;
/**
* Coding standards demonstration.
*/
class FooBar
{
const SOME_CONST = 42;
private $fooBar;
...
![Page 26: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/26.jpg)
Coding standard /**
* @param string $dummy Some argument description
*/
public function __construct($dummy)
{
$this->fooBar = $this->transformText($dummy);
}
![Page 27: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/27.jpg)
Coding standard
/** * @param string $dummy Some argument
description * @param array $options * * @return string|null Transformed input */ private function transformText($dummy,
array $options = array()) { $mergedOptions = array_merge( $options, array( 'some_default' => 'values', 'another_default' => 'more values', ) );
![Page 28: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/28.jpg)
Coding standard if (true === $dummy) {
return;
}
if ('string' === $dummy) {
if ('values' === $mergedOptions['some_default']) {
return substr($dummy, 0, 5);
}
return ucwords($dummy);
}
throw new \RuntimeException(sprintf('Unrecognized dummy option "%s"', $dummy));
}
}
![Page 29: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/29.jpg)
Creating Pages in Symfony2
Creating a new page in Symfony2 is a simple two-step process:
● Create a route: A route defines the URL (e.g. /about) to your page and specifies a controller (which is a PHP function) that Symfony2 should execute when the URL of an incoming request matches the route path;
● Create a controller: A controller is a PHP function that takes the incoming request and transforms it into the Symfony2 Response object that's returned to the user.
● Environment: ● Prod, dev, test
![Page 30: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/30.jpg)
But before... bundles :)
● Bundle is everything in Symfony2 :) - first-class citizens
● Directory that houses everything related to a specific feature ( configuration, PHP, JS, CSS...)
● We can compare it with modul or plugin● Flexible, independent, powerful
> php app/console generate:bundle
![Page 31: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/31.jpg)
Creating Pages in Symfony2
Step1: Create route# app/config/routing.yml
acme_hello:
resource: "@AcmeHelloBundle/Resources/config/routing.yml"
prefix: /
# src/Acme/HelloBundle/Resources/config/routing.yml
hello:
path: /hello/{name}
defaults: { _controller: AcmeHelloBundle:Hello:index }
![Page 32: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/32.jpg)
Creating Pages in Symfony2
Step2: Create controller// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($name)
{
return new Response('<html><body>Hello '.$name.'!</body></html>');
}
}
![Page 33: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/33.jpg)
Creating Pages in Symfony2
Step3: Create template// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class HelloController extends Controller
{
public function indexAction($name)
{
return $this->render(
'AcmeHelloBundle:Hello:index.html.twig',
array('name' => $name)
);
}
}
![Page 34: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/34.jpg)
Creating Pages in Symfony2
Practice #1:- create controller that receives some integer as
parameter from route and returns template with that number squared.
Time: 5 minutes
![Page 35: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/35.jpg)
Controller• Request -> Response● The response could be an HTML page, an XML document,
a serialized JSON array, an image, a redirect, a 404 error or anything else you can dream up.
● The controller contains whatever arbitrary logic your application needs to render the content of a page.
use Symfony\Component\HttpFoundation\Response;
public function helloAction(){ return new Response('Hello world!');}
![Page 36: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/36.jpg)
Requests, Controller, Response Lifecycle
![Page 37: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/37.jpg)
Simple Controller// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($name)
{
return new Response('<html><body>Hello '.$name.'!</body></html>');
}
}
![Page 38: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/38.jpg)
Mapping url to a Controller# app/config/routing.yml
hello:
path: /hello/{first_name}/{last_name}
defaults: { _controller: AcmeHelloBundle:Hello:index, color: green }
// order of arguments does not metter
public function indexAction($first_name, $color, $last_name)
{
// ... do whatever logic and return Response
}
![Page 39: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/39.jpg)
The Request as Controller Argumentuse Symfony\Component\HttpFoundation\Request;
public function updateAction(Request $request)
{
$form = $this->createForm(...);
$form->handleRequest($request);
// ...
}
![Page 40: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/40.jpg)
The Base Controller Class// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController extends Controller
{
// ... do whatever logic and return Response
}
By extending this Controller class, you can take advantage of several helper methods.
![Page 41: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/41.jpg)
Common Controller Tasks// redirecting
public function indexAction()
{
return $this->redirect($this->generateUrl('homepage'));
}
public function indexAction()
{
return $this->redirect($this->generateUrl('homepage'), 301);
}
Shortcut for:
use Symfony\Component\HttpFoundation\RedirectResponse;
return new RedirectResponse($this->generateUrl('homepage'));
![Page 42: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/42.jpg)
Common Controller Tasks// forwarding
public function indexAction($name)
{
$response = $this->forward('AcmeHelloBundle:Hello:fancy', array(
'name' => $name,
'color' => 'green',
));
// ... further modify the response or return it directly
return $response;
}
public function fancyAction($name, $color)
{
// ... create and return a Response object
}
![Page 43: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/43.jpg)
Common Controller TasksShortcut for:
$httpKernel = $this->container->get('http_kernel');
$response = $httpKernel->forward(
'AcmeHelloBundle:Hello:fancy',
array(
'name' => $name,
'color' => 'green',
)
);
![Page 44: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/44.jpg)
Common Controller Tasks// rendering templates
use Symfony\Component\HttpFoundation\Response;
$content = $this->renderView(
'AcmeHelloBundle:Hello:index.html.twig',
array('name' => $name)
);
return new Response($content);
return $this->render(
'AcmeHelloBundle:Hello:index.html.twig',
array('name' => $name)
);
![Page 45: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/45.jpg)
Common Controller TasksShortcut for:$templating = $this->get('templating');
$content = $templating->render(
'AcmeHelloBundle:Hello:index.html.twig',
array('name' => $name)
);
$templating->render(
'AcmeHelloBundle:Hello/Greetings:index.html.twig',
array('name' => $name)
);
![Page 46: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/46.jpg)
404 errorpublic function indexAction(){ // retrieve the object from database $product = ...; if (!$product) { throw $this->createNotFoundException('The product does not exist'); }
return $this->render(...);}
Error 500throw new \Exception('Something went wrong!');
![Page 47: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/47.jpg)
Accessing other Services$request = $this->getRequest();
$templating = $this->get('templating');
$router = $this->get('router');
$mailer = $this->get('mailer');
![Page 48: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/48.jpg)
Accessing other Services$request = $this->getRequest();
$templating = $this->get('templating');
$router = $this->get('router');
$mailer = $this->get('mailer');
> php app/console container:debug
![Page 49: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/49.jpg)
Managing the Session$session = $this->getRequest()->getSession();
// store an attribute for reuse during a later user request$session->set('foo', 'bar');
// in another controller for another request$foo = $session->get('foo');
// use a default value if the key doesn't exist$filters = $session->get('filters', array());
![Page 50: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/50.jpg)
Flash Messagespublic function updateAction(){ $form = $this->createForm(...);
$form->bind($this->getRequest()); if ($form->isValid()) { // do some sort of processing
$this->get('session')->getFlashBag()->add('notice', 'Your changes were saved!');
return $this->redirect($this->generateUrl(...)); }
return $this->render(...);}
![Page 51: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/51.jpg)
Flash Messages{% for flashMessage in app.session.flashbag.get('notice') %} <div class="flash-notice"> {{ flashMessage }} </div>{% endfor %}
![Page 52: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/52.jpg)
The Response ObjectThe only requirement for a controller is to return a Response object. The Response class is a PHP abstraction around the HTTP response - the text-based message filled with HTTP headers and content that's sent back to the client:
use Symfony\Component\HttpFoundation\Response;
// create a simple Response with a 200 status code (the default)$response = new Response('Hello '.$name, 200);
// create a JSON-response with a 200 status code$response = new Response(json_encode(array('name' => $name)));$response->headers->set('Content-Type', 'application/json');
![Page 53: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/53.jpg)
The Response Object - JSONuse Symfony\Component\HttpFoundation\Response;
$response = new Response();$response->setContent(json_encode(array( 'data' => 123,)));$response->headers->set('Content-Type', 'application/json');
---
use Symfony\Component\HttpFoundation\JsonResponse;
$response = new JsonResponse();$response->setData(array( 'data' => 123));
![Page 54: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/54.jpg)
The Response Object - FILEuse Symfony\Component\HttpFoundation\ResponseHeaderBag;
$d = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, 'foo.pdf');
$response->headers->set('Content-Disposition', $d);
---
use Symfony\Component\HttpFoundation\BinaryFileResponse
$file = 'path/to/file.txt';$response = new BinaryFileResponse($file);
![Page 55: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/55.jpg)
The Request Object$request = $this->getRequest();
$request->isXmlHttpRequest(); // is it an Ajax request?
$request->getPreferredLanguage(array('en', 'fr'));
$request->query->get('page'); // get a $_GET parameter
$request->request->get('page'); // get a $_POST parameter
![Page 56: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/56.jpg)
Render static pageNo need for controller!!!
acme_privacy:
path: /privacy
defaults:
_controller: FrameworkBundle:Template:template
template: 'AcmeBundle:Static:privacy.html.twig'
![Page 57: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/57.jpg)
ControllerPractice #2:● send numbers via $_GET parameter (numA and numB). Get these two
numbers in controller from Request Object (using $_GET[] is forbidden). Send Request object as action's parameter.
If numA*numB > 100 redirect to some custom controller's action;
If numA < 0 and numB < 0 throw 404 error;
If numA+numB > 10 return JSON Response with result;
else return template with result numA-numB;
Time: 10 minutes
![Page 58: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/58.jpg)
Routing <3index.php?article_id=57 -> don't like this/i-like/symfony-routing
One of the most powerfull Symfony2 component. Very flexible!!!
Route = map form url to controllerPosition of route is important!!!
![Page 59: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/59.jpg)
Routing <3// example (sylius):
locastic_product_review_list:
pattern: /review-for-product/{productId}
defaults:
_controller: locastic.controller.frontend.product_review:listReviewsForProductAction
locastic_product_review_add:
pattern: /add-review-for-product/{productId}
defaults:
_controller: locastic.controller.frontend.product_review:addReviewAction
_format: json
sylius_product_show:
pattern: /p/{slug}
defaults:
_controller: sylius.controller.product:showAction
_sylius:
template: SyliusWebBundle:Frontend/Product:show.html.twig
criteria: {slug: $slug}
![Page 60: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/60.jpg)
Routing <3
// 4 ways of defining routes1.YAML2.XML3.PHP4.Annotations
![Page 61: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/61.jpg)
Routing - YAML# app/config/routing.ymlblog_show: path: /blog/{slug} defaults: { _controller: AcmeBlogBundle:Blog:show }
![Page 62: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/62.jpg)
Routing - XML<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="blog_show" path="/blog/{slug}"> <default key="_controller">AcmeBlogBundle:Blog:show</default> </route></routes>
![Page 63: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/63.jpg)
Routing - PHP// app/config/routing.phpuse Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\Route;
$collection = new RouteCollection();$collection->add('blog_show', new Route('/blog/{slug}', array( '_controller' => 'AcmeBlogBundle:Blog:show',)));
return $collection;
![Page 64: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/64.jpg)
Routing - Annotations/** * @Route("/blog/{slug}", name=”blog_show”) */public function showAction($slug){
// do whatever logic and return Response}
![Page 65: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/65.jpg)
Routing :)
![Page 66: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/66.jpg)
Basic Route Configuration_welcome: path: / defaults: { _controller: AcmeDemoBundle:Main:homepage }
<?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="_welcome" path="/"> <default key="_controller">AcmeDemoBundle:Main:homepage</default> </route></routes>
![Page 67: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/67.jpg)
Routing with placeholderblog_show:
path: /blog/{slug}
defaults: { _controller: AcmeBlogBundle:Blog:show }
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="blog_show" path="/blog/{slug}">
<default key="_controller">AcmeBlogBundle:Blog:show</default>
</route>
</routes>
![Page 68: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/68.jpg)
Required and Optional Placeholderblog:
path: /blog
defaults: { _controller: AcmeBlogBundle:Blog:index }
blog:
path: /blog/{page}
defaults: { _controller: AcmeBlogBundle:Blog:index }
blog:
path: /blog/{page}
defaults: { _controller: AcmeBlogBundle:Blog:index, page: 1 }
![Page 69: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/69.jpg)
Required and Optional Placeholderblog:
path: /blog/{page}
defaults: { _controller: AcmeBlogBundle:Blog:index, page: 1 }
/blog {page} = 1
/blog/1 {page} = 1
/blog/2 {page} = 2
![Page 70: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/70.jpg)
Adding Requirementsblog:
path: /blog/{page}
defaults: { _controller: AcmeBlogBundle:Blog:index, page: 1 }
blog_show:
path: /blog/{slug}
defaults: { _controller: AcmeBlogBundle:Blog:show }
URL route parameters
/blog/2 blog {page} = 2
/blog/my-blog-post blog {page} = my-blog-post
![Page 71: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/71.jpg)
Adding Requirementsblog:
path: /blog/{page}
defaults: { _controller: AcmeBlogBundle:Blog:index, page: 1 }
requirements:
page: \d+
URL route parameters
/blog/2 blog {page} = 2
/blog/my-blog-post blog_show {slug} = my-blog-post
![Page 72: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/72.jpg)
Earlier Routes always Win!!!
What this all means is that the order of the routes is very important. If the blog_show route were placed above the blog route, the URL /blog/2 would match blog_show instead of blog since the {slug} parameter of blog_show has no requirements. By using proper ordering and clever requirements, you can accomplish just about anything.
![Page 73: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/73.jpg)
Adding Requirementshomepage:
path: /{culture}
defaults: { _controller: AcmeDemoBundle:Main:homepage, culture: en }
requirements:
culture: en|fr
/ {culture} = en
/en {culture} = en
/fr {culture} = fr
/es won't match this route
![Page 74: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/74.jpg)
Adding HTTP Method Requirementscontact:
path: /contact
defaults: { _controller: AcmeDemoBundle:Main:contact }
methods: [GET]
contact_process:
path: /contact
defaults: { _controller: AcmeDemoBundle:Main:contactProcess }
methods: [POST]
![Page 75: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/75.jpg)
Advanced Routing Examplearticle_show:
path: /articles/{culture}/{year}/{title}.{_format}
defaults: { _controller: AcmeDemoBundle:Article:show, _format: html }
requirements:
culture: en|fr
_format: html|rss
year: \d+
/articles/en/2010/my-post
/articles/fr/2010/my-post.rss
/articles/en/2013/my-latest-post.html
![Page 76: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/76.jpg)
Including External Routing Resources# app/config/routing.yml
acme_hello:
resource: "@AcmeHelloBundle/Resources/config/routing.yml"
# src/Acme/HelloBundle/Resources/config/routing.yml
acme_hello:
path: /hello/{name}
defaults: { _controller: AcmeHelloBundle:Hello:index }
![Page 77: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/77.jpg)
Prefixing Imported Routes# app/config/routing.yml
acme_hello:
resource: "@AcmeHelloBundle/Resources/config/routing.yml"
prefix: /admin
![Page 78: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/78.jpg)
Visualizing & Debugging RoutesWhile adding and customizing routes, it's helpful to be able to visualize and get
detailed information about your routes. A great way to see every route in your application is via the router:debug console command. Execute the command by running the following from the root of your project.
> php app/console router:debug
![Page 79: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/79.jpg)
Generating URLs
class MainController extends Controller
{
public function showAction($slug)
{
// ...
$url = $this->generateUrl( // helper method
'blog_show',
array('slug' => 'my-blog-post')
);
}
}
![Page 80: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/80.jpg)
Generating URLs
$params = $this->get('router')->match('/blog/my-blog-post');
// array(
// 'slug' => 'my-blog-post',
// '_controller' => 'AcmeBlogBundle:Blog:show',
// )
$uri = $this->get('router')->generate('blog_show', array('slug' => 'my-blog-post'));
// /blog/my-blog-post
$this->get('router')->generate('blog_show', array('slug' => 'my-blog-post'), true);
// http://www.example.com/blog/my-blog-post
![Page 81: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/81.jpg)
Generating URLs
// with query string
$this->get('router')->generate('blog', array('page' => 2, 'category' => 'Symfony'));
// /blog/2?category=Symfony
// from template
<a href="{{ path('blog_show', {'slug': 'my-blog-post'}) }}">
Read this blog post.
</a>
<a href="{{ url('blog_show', {'slug': 'my-blog-post'}) }}">
Read this blog post.
</a>
![Page 82: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/82.jpg)
Routing :)Practice #3:
- create route for AcmeDemoBundle:Hello:list, that accepts parameters:
- category (string with no numbers)
- page number (integer)
- only GET method
In template list: category, slug and page number like this:
If url is: /ez-publish-summer-camp/3
Category slug: ez-publish-summer-camp
Page number: 3
Use YAML format for routing!
Time: 5 minutes
![Page 83: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/83.jpg)
MODELORM Doctrine 2
parameters.yml → Config.yml
> php app/console doctrine:database:create
![Page 84: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/84.jpg)
MODEL - metadata// src/Acme/StoreBundle/Entity/Product.phpnamespace Acme\StoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/** * @ORM\Entity * @ORM\Table(name="product") */class Product{ /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id;
...
![Page 85: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/85.jpg)
MODEL - metadata..
/** * @ORM\Column(type="string", length=100) */ protected $name;
/** * @ORM\Column(type="decimal", scale=2) */ protected $price;
/** * @ORM\Column(type="text") */ protected $description;}
![Page 86: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/86.jpg)
MODEL – metadata - YAML# src/Acme/StoreBundle/Resources/config/doctrine/Product.orm.yml
Acme\StoreBundle\Entity\Product:
type: entity
table: product
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 100
price:
type: decimal
scale: 2
description:
type: text
![Page 87: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/87.jpg)
MODEL – metadata - XML<!-- src/Acme/StoreBundle/Resources/config/doctrine/Product.orm.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Acme\StoreBundle\Entity\Product" table="product">
<id name="id" type="integer" column="id">
<generator strategy="AUTO" />
</id>
<field name="name" column="name" type="string" length="100" />
<field name="price" column="price" type="decimal" scale="2" />
<field name="description" column="description" type="text" />
</entity>
</doctrine-mapping>
![Page 88: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/88.jpg)
MODEL A bundle can accept only one metadata definition format. For example, it's not possible to mix YAML metadata definitions with annotated PHP entity class definitions.
Be careful that your class name and properties aren't mapped to a protected SQL keyword (such as group or user).
Create getters and setters > php app/console doctrine:generate:entities Acme/StoreBundle/Entity/Product
> php app/console doctrine:schema:update –force
![Page 89: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/89.jpg)
Persist object to database// src/Acme/StoreBundle/Controller/DefaultController.php
// ...use Acme\StoreBundle\Entity\Product;use Symfony\Component\HttpFoundation\Response;
public function createAction(){ $product = new Product(); $product->setName('A Foo Bar'); $product->setPrice('19.99'); $product->setDescription('Lorem ipsum dolor');
$em = $this->getDoctrine()->getManager(); $em->persist($product); $em->flush();
return new Response('Created product id '.$product->getId());}
![Page 90: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/90.jpg)
Fetching Objects from the Databasepublic function showAction($id){ $product = $this->getDoctrine() ->getRepository('AcmeStoreBundle:Product') ->find($id);
if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$id ); }
// ... do something, like pass the $product object into a template}
![Page 91: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/91.jpg)
Repository Basic// query by the primary key (usually "id")$product = $repository->find($id);
// dynamic method names to find based on a column value$product = $repository->findOneById($id);$product = $repository->findOneByName('foo');
// find *all* products$products = $repository->findAll();
// find a group of products based on an arbitrary column value$products = $repository->findByPrice(19.99);
![Page 92: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/92.jpg)
Repository Basic// query for one product matching be name and price$product = $repository->findOneBy(array('name' => 'foo', 'price' => 19.99));
// query for all products matching the name, ordered by price$products = $repository->findBy( array('name' => 'foo'), array('price' => 'ASC'));
![Page 93: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/93.jpg)
How many queries?
![Page 94: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/94.jpg)
Updating an Objectpublic function updateAction($id){ $em = $this->getDoctrine()->getManager(); $product = $em->getRepository('AcmeStoreBundle:Product')->find($id);
if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$id ); }
$product->setName('New product name!'); $em->flush();
return $this->redirect($this->generateUrl('homepage'));}
![Page 95: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/95.jpg)
Deleting on object$em->remove($product);$em->flush();
![Page 96: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/96.jpg)
Querying for Object with DQL $em = $this->getDoctrine()->getManager();$query = $em->createQuery( 'SELECT p FROM AcmeStoreBundle:Product p WHERE p.price > :price ORDER BY p.price ASC')->setParameter('price', '19.99');
$products = $query->getResult();
![Page 97: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/97.jpg)
Using Doctrine's Query Builder$repository = $this->getDoctrine() ->getRepository('AcmeStoreBundle:Product');
$query = $repository->createQueryBuilder('p') ->where('p.price > :price') ->setParameter('price', '19.99') ->orderBy('p.price', 'ASC') ->getQuery();
$products = $query->getResult();
![Page 98: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/98.jpg)
Custom Repository Classes// using annotations
// src/Acme/StoreBundle/Entity/Product.php
namespace Acme\StoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="Acme\StoreBundle\Entity\ProductRepository")
*/
class Product
{
//...
}
![Page 99: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/99.jpg)
Custom Repository Classes// using YAML
#src/Acme/StoreBundle/Resources/config/doctrine/Product.orm.yml
Acme\StoreBundle\Entity\Product:
type: entity
repositoryClass: Acme\StoreBundle\Entity\ProductRepository
# ...
![Page 100: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/100.jpg)
Custom Repository Classes// using XML
<!-- src/Acme/StoreBundle/Resources/config/doctrine/Product.orm.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Acme\StoreBundle\Entity\Product"
repository-class="Acme\StoreBundle\Entity\ProductRepository">
<!-- ... -->
</entity>
</doctrine-mapping>
![Page 101: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/101.jpg)
Custom Repository Classes// src/Acme/StoreBundle/Entity/ProductRepository.php
namespace Acme\StoreBundle\Entity;
use Doctrine\ORM\EntityRepository;
class ProductRepository extends EntityRepository
{
public function findAllOrderedByName()
{
return $this->getEntityManager()
->createQuery(
'SELECT p FROM AcmeStoreBundle:Product p ORDER BY p.name ASC'
)
->getResult();
}
}
![Page 102: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/102.jpg)
Custom Repository Classes$em = $this->getDoctrine()->getManager();
$products = $em->getRepository('AcmeStoreBundle:Product')
->findAllOrderedByName();
![Page 103: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/103.jpg)
MODEL – custom repository public function updateGallery($photoId, $galleryId) { $qb = $this->createQueryBuilder('p'); $query = $qb ->update() ->set('p.gallery', $galleryId) ->where('p.id = :id') ->setParameter('id', $photoId);
return $query->getQuery()->execute(); }
![Page 104: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/104.jpg)
Relationship Mapping Metadata// src/Acme/StoreBundle/Entity/Category.php
// ...
use Doctrine\Common\Collections\ArrayCollection;
class Category
{
// ...
/**
* @ORM\OneToMany(targetEntity="Product", mappedBy="category")
*/
protected $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
}
Product (n) <- (1) Category
![Page 105: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/105.jpg)
Relationship Mapping Metadata<!-- src/Acme/StoreBundle/Resources/config/doctrine/Category.orm.xml -->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Acme\StoreBundle\Entity\Category">
<!-- ... -->
<one-to-many field="products"
target-entity="Product"
mapped-by="category"
/>
<!--
don't forget to init the collection in
the __construct() method of the entity
-->
</entity>
</doctrine-mapping>
Product (n) <- (1) Category
![Page 106: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/106.jpg)
Relationship Mapping Metadata#src/Acme/StoreBundle/Resources/config/doctrine/Category.orm.yml
Acme\StoreBundle\Entity\Category:
type: entity
# ...
oneToMany:
products:
targetEntity: Product
mappedBy: category
# don't forget to init the collection in the __construct() method of the entity
Product (n) <- (1) Category
![Page 107: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/107.jpg)
Relationship Mapping Metadata// src/Acme/StoreBundle/Entity/Product.php
// ...
class Product
{
// ...
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="products")
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
protected $category;
}
Product (n) <- (1) Category
![Page 108: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/108.jpg)
Relationship Mapping Metadata# src/Acme/StoreBundle/Resources/config/doctrine/Product.orm.yml
Acme\StoreBundle\Entity\Product:
type: entity
# ...
manyToOne:
category:
targetEntity: Category
inversedBy: products
joinColumn:
name: category_id
referencedColumnName: id
Product (n) <- (1) Category
![Page 109: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/109.jpg)
Relationship Mapping Metadata<!-- src/Acme/StoreBundle/Resources/config/doctrine/Product.orm.xml -->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Acme\StoreBundle\Entity\Product">
<!-- ... -->
<many-to-one field="category"
target-entity="Category"
inversed-by="products"
join-column="category"
>
<join-column
name="category_id"
referenced-column-name="id"
/>
</many-to-one>
</entity>
</doctrine-mapping>
Product (n) <- (1) Category
![Page 110: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/110.jpg)
Relationship Mapping Metadata
![Page 111: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/111.jpg)
Saving related entities// ...
use Acme\StoreBundle\Entity\Category;
use Acme\StoreBundle\Entity\Product;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
public function createProductAction()
{
$category = new Category();
$category->setName('Main Products');
$product = new Product();
$product->setName('Foo');
$product->setPrice(19.99);
// relate this product to the category
$product->setCategory($category);
$em = $this->getDoctrine()->getManager();
$em->persist($category);
$em->persist($product);
$em->flush();
return new Response(
'Created product id: '.$product->getId().' and category id: '.$category->getId()
);
}
}
![Page 112: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/112.jpg)
Fetching related Objectspublic function showAction($id)
{
$product = $this->getDoctrine()
->getRepository('AcmeStoreBundle:Product')
->find($id);
$categoryName = $product->getCategory()->getName();
// ...
}
![Page 113: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/113.jpg)
Fetching related Objects
![Page 114: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/114.jpg)
Fetching related Objectspublic function showProductAction($id)
{
$category = $this->getDoctrine()
->getRepository('AcmeStoreBundle:Category')
->find($id);
$products = $category->getProducts();
// ...
}
![Page 115: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/115.jpg)
Doctrine Field Types Reference Strings
string (used for shorter strings)
text (used for larger strings)
Numbers
integer
smallint
bigint
decimal
float
Dates and Times (use a DateTime object for these fields in PHP)
date
time
datetime
Other Types
boolean
object (serialized and stored in a CLOB field)
array (serialized and stored in a CLOB field)
![Page 116: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/116.jpg)
Some advanced stuff Events and lifecycle callbacks
preRemove
postRemove
prePersist
postPersist
preUpdate
postUpdate
postLoad
LoadClassMetadata
Doctrine Extensions: Timestampable, Sluggable, etc.
![Page 117: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/117.jpg)
MODELPractice #3:
- Create entities for schema bellow and create empty custom repository for each, use XML
Time: 15 minutes
![Page 118: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/118.jpg)
Download
PPT: Www.locastic.com/ez2013/index.htmlOr bitly.com/ez2013
Views And templatesWww.locastic.com/ez2013/view.zip
![Page 119: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/119.jpg)
CRUD→ create bundle
![Page 120: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/120.jpg)
CRUD→ create bundle→ create entity
![Page 121: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/121.jpg)
CRUD→ create bundle→ create entity→ create full CRUD* with routes, controllers and templates
![Page 122: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/122.jpg)
CRUD→ create bundle→ create entity→ create full CRUD with routes, controllers and templates→ use console :)
![Page 123: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/123.jpg)
FORMS AND VALIDATION
Workshop: Symfony2 Forms – tomorrow 09:00amBernhard Schussek
The Symfony2 Form component helps you to build powerful forms with little code. This workshop shows you how to use the component in your daily life.
![Page 124: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/124.jpg)
Template
Twig!!! FTW!!!
Skipper: Luka Vidoš
![Page 125: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/125.jpg)
![Page 126: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/126.jpg)
Questions?
![Page 127: Workshop: Symfony2 Intruduction: (Controller, Routing, Model)](https://reader036.vdocuments.mx/reader036/viewer/2022062511/54c69aba4a79593b258b463f/html5/thumbnails/127.jpg)
Thank you