Download - The Naked Bundle - Symfony Live London 2014
![Page 2: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/2.jpg)
What's it all about?
![Page 3: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/3.jpg)
An actual naked bundle
![Page 4: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/4.jpg)
I could've called it
BundleLitetm
The No Code Bundle
The Clean Bundle
![Page 5: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/5.jpg)
But “naked” is catchy and controversial
![Page 6: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/6.jpg)
The official view on bundles
![Page 7: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/7.jpg)
First-class citizensDocumentation » The Quick Tour » The Architecture
![Page 8: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/8.jpg)
Importance
Your code is more important than the framework,
which is an implementation detail
![Page 9: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/9.jpg)
Reuse
![Page 10: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/10.jpg)
Nice!
![Page 11: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/11.jpg)
All your code lives in a bundleDocumentation » The Book » Creating Pages in Symfony2
![Page 12: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/12.jpg)
Reuse
“All your code in a bundle” contradicts the promise of reuse
![Page 13: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/13.jpg)
Everything lives inside a bundleDocumentation » Glossary
![Page 14: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/14.jpg)
Not really true
Many things live inside libraries
(the Symfony components are libraries too!)
![Page 15: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/15.jpg)
Which is good!
![Page 16: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/16.jpg)
But you probably know that already
![Page 17: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/17.jpg)
“libraries first”
![Page 18: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/18.jpg)
What about...● Controllers
● Entities
● Templates
● ...
![Page 19: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/19.jpg)
They just need to be in a bundle
Or do they?
![Page 20: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/20.jpg)
Don't get me wrong
I love Symfony!
![Page 21: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/21.jpg)
But a framework is just a framework● Quickstarter for your projects
● Prevents and solves big security issues for you
● Has a community you can rely on
![Page 22: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/22.jpg)
A framework is there for you
![Page 23: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/23.jpg)
Your code doesn't need a framework
![Page 24: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/24.jpg)
Noback's Principle
Code shouldn't rely on something
it doesn't truly need
![Page 25: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/25.jpg)
Bundle conventions
Things in a bundle often rely on conventions to work
![Page 26: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/26.jpg)
Conventions aren't necessary at all
![Page 27: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/27.jpg)
So according to Noback's Principle,code shouldn't rely on bundle conventions too
![Page 28: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/28.jpg)
Naming conventionsControllers:
● *Controller classes
● *action methods
Templates:
● in /Resources/views
● name: Controller/Action.html.twig
![Page 29: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/29.jpg)
Structural conventionsController:
● Extends framework Controller class
● Is ContainerAware
![Page 30: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/30.jpg)
Behavioral conventionsController:
● Is allowed to return an array
● Actions can type-hint to objects which will be fetched based on route parameters (??)
![Page 31: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/31.jpg)
Configuration conventions
Use lots of annotations!
/** * @Route("/{id}") * @Method("GET") * @ParamConverter("post", class="SensioBlogBundle:Post") * @Template("SensioBlogBundle:Annot:show.html.twig") * @Cache(smaxage="15", lastmodified="post.getUpdatedAt()") * @Security("has_role('ROLE_ADMIN')") */public function showAction(Post $post){}
![Page 32: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/32.jpg)
These conventions are what makes an application a Symfony2 application
![Page 33: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/33.jpg)
A Year With Symfony
![Page 34: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/34.jpg)
About bundles
![Page 35: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/35.jpg)
A bundle exposes resources
![Page 36: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/36.jpg)
Resources● Service definitions
● Controllers
● Routes
● Templates
● Entities
● Form types
● Event listeners
● Translations
● ...
![Page 37: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/37.jpg)
No need for them to be inside a bundle
![Page 38: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/38.jpg)
When placed outside the bundlethe resources could be reused separately
![Page 39: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/39.jpg)
The bundle would be really small
![Page 40: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/40.jpg)
And could just as well be a:Laravel package,
Zend or Drupal module,CakePHP plugin,
...
![Page 41: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/41.jpg)
So the challenge is to
Make the bundle as clean as possible
![Page 42: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/42.jpg)
Move the “misplaced” things to● a library
● with dependencies
● but not symfony/frameworkbundle ;)
![Page 43: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/43.jpg)
Being realistic
Practical reusability
![Page 44: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/44.jpg)
Reuse within the Symfony family
Think: Silex, Laravel, etc.
![Page 45: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/45.jpg)
Allowed dependency
HttpFoundation● Request● Response
● Exceptions● etc.
![Page 46: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/46.jpg)
What do we rely on
HttpKernelnamespace Symfony\Component\HttpKernel;
use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;
interface HttpKernelInterface{ /** * Handles a Request to convert it to a Response. */ public function handle(Request $request, ...);}
![Page 47: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/47.jpg)
Why? My secret missions
“Let's rebuild the application, but this time we use Zend4 instead of Symfony2”
![Page 48: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/48.jpg)
And of course
Education
![Page 49: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/49.jpg)
You need a strong coupling radar
![Page 50: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/50.jpg)
Explicit dependencies● Function calls
● Imported classes (“use”)
● Included files
● ...
![Page 51: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/51.jpg)
Implicit dependencies● File locations
● File, class, method names
● Structure of return values
● ...
![Page 52: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/52.jpg)
There we go!
![Page 53: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/53.jpg)
use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/** * @Route(“/article”) */class ArticleController extends Controller{
/** * @Route(“/edit”) * @Template() */function editAction(...){
...}
}
Controller
![Page 54: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/54.jpg)
TODO✔ Don't rely on things that may not
be there in another context:✔ Parent Controller class
✔ Routing, template, annotations, etc.
![Page 55: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/55.jpg)
class ArticleController{
function editAction(...){
...}
}
Nice and clean ;)
![Page 56: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/56.jpg)
use Symfony\Component\HttpFoundation\Request;
class ArticleController{ public function editAction(Request $request) { $em = $this>get('doctrine')>getManager(); ...
if (...) { throw $this>createNotFoundException(); }
...
return array( 'form' => $form>createView() ); }}
Zooming in a bit
![Page 57: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/57.jpg)
TODO✔ Inject dependencies
✔ Don't use helper methods
✔ Render the template manually
✔ Keep using Request (not really a TODO)
![Page 58: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/58.jpg)
use Doctrine\ORM\EntityManager;
class ArticleController{
function __construct(EntityManager $em,
) {$this>em = $em;
}
...}
Inject dependencies
![Page 59: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/59.jpg)
Inline helper methodsuse Symfony\Component\HttpKernel\Exception\NotFoundHttpException
class ArticleController{ ...
public function newAction(...) { ... throw new NotFoundHttpException(); ... }}
![Page 60: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/60.jpg)
use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Templating\EngineInterface;
class ArticleController{
function __construct(..., EngineInterface $templating) {}
public function newAction(...){
...return new Response(
$this>templating>render('@MyBundle:Article:new.html.twig',array(
'form' => $form>createView())
));
}}
Render the template manually
![Page 61: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/61.jpg)
Dependencies are explicit now
use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Templating\EngineInterface;use Doctrine\ORM\EntityManager;
Also: no mention of a “bundle” anywhere!
![Page 62: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/62.jpg)
Dependency overflowuse Symfony\Component\HttpFoundation\Response;use Symfony\Component\Templating\EngineInterface;
class ArticleController{
function __construct(EntityManager $entityManager,EngineInterface $templating,TranslatorInterface $translator,ValidatorInterface $validator,Swift_Mailer $mailer,RouterInterface $router
) {...
}
...}
![Page 63: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/63.jpg)
The cause?
Convention
![Page 64: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/64.jpg)
One controller, many actions
one action!
![Page 65: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/65.jpg)
__invoke()
namespace MyLibrary\Controller\Article;
class New{
function __construct(...) {
// only what's necessary for this “action”}
public function __invoke(...){
...}
}
![Page 66: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/66.jpg)
Nice!
└─Controller └─Article ├─New.php ├─Edit.php ├─Archive.php └─Delete.php
![Page 67: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/67.jpg)
TODO✔ Set up routing
✔ Create a service and provide the right arguments
![Page 68: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/68.jpg)
Bundle stuff: services.xml<! in MyBundle/Resources/config/services.xml →
<?xml version="1.0" ?><container><services>
<service id="new_article_controller" class="MyBundle\Controller\Article\New"> <argument type="service" id="doctrine.orm.default_entity_manager" /> <argument type="service" id="templating" /></service>
</services></container>
![Page 69: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/69.jpg)
Bundle stuff: routing.xml<! in MyBundle/Resources/config/routing.xml →
<?xml version="1.0" encoding="UTF8" ?><routes>
<route id="new_article" path="/article/new"> <default key="_controller"> new_article_controller:__invoke </default></route>
</routes>
Pull request by Kevin Bond allows you to leave out the “:__invoke” part!
![Page 70: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/70.jpg)
Controller – Achievements● Can be anywhere
● No need to follow naming conventions (“*Controller”, “*action”)
● Dependency injection, no service location
● Reusable in any application using HttpFoundation
![Page 71: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/71.jpg)
Next up: Entities
![Page 72: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/72.jpg)
namespace My\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class Article{ ...
/** * @ORM\Column(type=”string”) */ private $title;}
Entity conventions
![Page 73: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/73.jpg)
What's wrong with annotations?
namespace My\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class Article{ ...
/** * @ORM\Column(type=”string”) */ private $title;}
![Page 74: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/74.jpg)
Annotations are classes
![Page 75: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/75.jpg)
use Doctrine\Common\Annotations\AnnotationReader;
$reader = new AnnotationReader();
$class = new \ReflectionClass('Article');
$reader>getClassAnnotations($class);
BANG
Class Doctrine\ORM\Mapping\Column
not found
![Page 76: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/76.jpg)
Well, uhm, yes, but...
![Page 77: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/77.jpg)
Are you ever going to use anything else than Doctrine ORM?
![Page 78: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/78.jpg)
Well...Think about Doctrine MongoDB ODM, Doctrine CouchDB ODM, etc.namespace My\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;use Doctrine\ODM\CouchDB\Mapping\Annotations as CoucheDB;
class Article{ /** * @ORM\Column * @MognoDB\Field * @CoucheDB\Field */ private $title;}
![Page 79: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/79.jpg)
TODO✔ Remove annotations
✔ Find another way to map the data
![Page 80: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/80.jpg)
namespace My\Bundle\Entity;
class Article{ private $id; private $title;}
Nice and clean
A true POPO, the ideal of the data mapper pattern
![Page 81: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/81.jpg)
Use XML for mapping metadata<doctrinemapping>
<entity name=”My\Bundle\Entity\Article”> <id name="id" type="integer" column="id"> <generator strategy="AUTO"/> </id> <field name=”title” type=”string”></entity> </doctrinemapping>
![Page 82: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/82.jpg)
Conventions for XML metadata● For MyBundle\Entity\Article
● Put XML here: @MyBundle/Resources/config/doctrine/ Article.orm.xml
![Page 83: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/83.jpg)
We don't want it in the bundle!There's a nice little trick
![Page 84: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/84.jpg)
You need DoctrineBundle >=1.2
{ "require": { ..., "doctrine/doctrinebundle": "~1.2@dev" }}
![Page 85: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/85.jpg)
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\ DoctrineOrmMappingsPass;
class MyBundle extends Bundle{ public function build(ContainerBuilder $container) { $container>addCompilerPass( $this>buildMappingCompilerPass() ); }
private function buildMappingCompilerPass() { $xmlPath = '%kernel.root_dir%/../src/MyLibrary/Doctrine'; $namespacePrefix = 'MyLibrary\Model';
return DoctrineOrmMappingsPass::createXmlMappingDriver( array($xmlPath => $namespacePrefix) ); }}
![Page 86: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/86.jpg)
Now:● For MyLibrary\Model\Article
● Put XML here: src/MyLibrary/Doctrine/Article.orm.xml
![Page 87: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/87.jpg)
Entities - Achievements● Entity classes can be anywhere● Mapping metadata can be
anywhere and in different formats● Entities are true POPOs
![Page 88: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/88.jpg)
Finally: Templates
![Page 89: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/89.jpg)
Conventions● In /Resources/views/[Controller]
● Filename: [Action].[format].[engine]
![Page 90: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/90.jpg)
The difficulty with templatesThey can have all kinds of implicit dependencies:
● global variables, e.g. {{ app.request }}
● functions, e.g. {{ path(...) }}
● parent templates, e.g. {% extends “::base.html.twig” %}
![Page 91: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/91.jpg)
Still, we want them out!
And it's possible
![Page 92: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/92.jpg)
# in config.ymltwig: ... paths: "%kernel.root_dir%/../src/MyLibrary/Views": MyLibrary
Twig namespacesDocumentation » The Cookbook » Templating » How to use and Register namespaced Twig Paths
// in the controllerreturn $this>templating>render('@MyLibrary/Template.html.twig');
![Page 93: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/93.jpg)
Get rid of absolute paths
Using Puli, created by Bernhard Schüssek (Symfony Forms, Validation)
![Page 94: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/94.jpg)
What Puli does
Find the absolute paths of resources in a project
![Page 95: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/95.jpg)
use Webmozart\Puli\Repository\ResourceRepository;
$repo = new ResourceRepository();$repo>add('/mylibrary/views', '/absolute/path/to/views/*');
/my-library/views /index.html.twig
/absolute/path/to/views /index.html.twig
echo $repo>get('/mylibrary/views/index.html.twig')>getRealPath();
// => /absolute/path/to/views/index.html.twig
![Page 96: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/96.jpg)
Register “prefixes”
Manually, or using the Puli Composer plugin
// in the composer.json file of a package or project{ "extra": { "resources": { "/mylibrary/views": "src/MyLibrary/Views" } }}
![Page 97: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/97.jpg)
Twig templates// in composer.json{ "extra": { "resources": { "/mylibrary/views": "src/MyLibrary/Views" } }}
// in the controllerreturn $this>templating >render('/mylibrary/views/index.html.twig');
Puli Twig extension
![Page 98: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/98.jpg)
Many possibilities● Templates
● Translation files
● Mapping metadata
● Service definitions
● And so on!
![Page 99: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/99.jpg)
The future is bright● Puli is not stable yet
● But I expect much from it:
![Page 100: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/100.jpg)
Puli will be the ultimate tool
![Page 101: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/101.jpg)
to create NAKED BUNDLES
![Page 102: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/102.jpg)
and to enable reuse of many kinds of resources
![Page 103: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/103.jpg)
not limited byproject,
framework,even language
boundaries!
![Page 104: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/104.jpg)
But even without Puli
There's a whole lot you can do to make your code not rely on the framework
![Page 105: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/105.jpg)
Remember
The framework is for youYour code doesn't need it
![Page 106: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/106.jpg)
Questions?
![Page 107: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/107.jpg)
Get a $7,50 discount:http://leanpub.com/a-year-with-symfony/c/SymfonyLiveLondon2014
![Page 108: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/108.jpg)
Get a $10,00 introduction discount:http://leanpub.com/principles-of-php-package-design/c/SymfonyLiveLondon2014
![Page 109: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/109.jpg)
Thank you
Feedback: joind.in/11553
Talk to me: @matthiasnoback
![Page 110: The Naked Bundle - Symfony Live London 2014](https://reader035.vdocuments.us/reader035/viewer/2022081413/5476dd1bb4af9fae028b4787/html5/thumbnails/110.jpg)
Images
Sally MacKenzie: www.amazon.com