By Fran Moreno / @franmomu
Symfony2 is a reusable set of standalone, decoupled, and cohesive PHP components that solve common web development problems
Then, based on these components, Symfony2 is also a full-stack web framework
HTTP y MVC Framework
3 Millones de visitas al día - Imagen: dotmmo
200 millones de páginas vistas al día
use Symfony\Component\Finder\Finder;
$finder = new Finder();
$iterator = $finder
->files()
->name('*.php')
->depth(0)
->size('>= 1K')
->in(__DIR__);
foreach ($iterator as $file) {
print $file->getRealpath()."n";
}
$s3 = new Zend_Service_Amazon_S3($key, $secret);
$s3->registerStreamWrapper("s3");
$finder = new Finder();
$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
foreach ($finder->in('s3://bucket-name') as $file) {
print $file->getFilename()."n";
}
<services>
<service id="betabeers.entity.user_manager"
class="Foo\BetaBeersBundle\Entity\UserManager">
<argument type="service" id="doctrine" />
<argument type="service" id="betabeers.mailer.manager" />
</service>
</services>
$userManager = $container->get('betabeers.entity.user_manager');
A bundle is a directory that has a well-defined structure and can host anything from classes to controllers and web resources.
# Descarga composer.phar
$ curl -s https://getcomposer.org/installer | php
{
"require": {
"symfony/framework-standard-edition": "2.1.7",
"liip/imagine-bundle": "dev-master",
}
}
$ php composer.phar install
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="bb_user")
* @ORM\Entity()
*/
class User
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(name="first_name", type="string", length=50)
*/
private $firstname;
/**
* @ORM\OneToMany(targetEntity="Foo\BarBundle\Entity\Address",
mappedBy="user")
*/
private $addresses;
}
$em = $container->get('doctrine')->getManager();
for($i = 0; $i < 1000; $i++) {
$user = new User();
$user->setFirstname($names[$i]);
//...
$em->persist($user);
}
$em->flush();
$dql = "SELECT u
FROM FooBarBundle:User u
LEFT JOIN u.addresses a
WHERE a.country = :country";
$query = $em->createQuery($dql);
$query->setParameter("country", "Spain");
$spanishUsers = $query->getResult();
{% for user in users %}
* {{ user.name }}
{% else %}
No user have been found.
{% endfor %}
<?php echo $var ?>
<?php echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>
{{ var }}
{{ var|e }}
<?php echo $user->isEnabled() ?>
{{ user.enabled }}
{# Filtros #}
{% set names = ["pepe", "juan", "maría"] %}
{{ names|join(", ") }} {# output: pepe, juan, maría #}
{{ names|sort|join("-") }} {# output: juan-maría-pepe #}
{{ post.publishedAt|date('d-m-Y') }} {# output: 21-02-2013 #}
{% macro input(name, value, type, size) %}
<input type="{{ type|default('text') }}" name="{{ name }}"
value="{{ value|e }}" size="{{ size|default(20) }}" />
{% endmacro %}
<p>{{ forms.input('username') }}</p>
Documentación Twig
{% javascripts '@AcmeFooBundle/Resources/public/js/*' filter='yui_js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
{% image '@AcmeFooBundle/Resources/public/images/example.jpg'
filter='jpegoptim' output='/images/example.jpg' %}
<img src="{{ asset_url }}" alt="Example"/>
{% endimage %}
$ php composer.phar create-project
symfony/framework-standard-edition betabeers/ 2.1.7
# Permisos
$ sudo chmod +a "www-data allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs
$ sudo chmod +a "`whoami` allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs
├── app
│ ├── Resources
│ ├── cache
│ ├── config
│ │ ├── routing.yml
│ │ ├── security.yml
│ │ ├── config.yml
│ │ ├── parameters.yml
│ ├── logs
│ ├── AppKernel.php
│ └── console
├── src
├── vendor
├── web
│ ├── app.php
│ ├── app_dev.php
│ └── config.php
├── composer.json
└── composer.lock
$ php app/console generate:bundle
Bundle namespace: FranMoreno/BetabeersBundle
Bundle name [FranMorenoBetabeersBundle]: BetabeersBundle
Target directory [/Users/franmoreno/projects/betabeers/src]:
Configuration format (yml, xml, php, or annotation) [annotation]:
Do you want to generate the whole directory structure [no]? yes
Do you confirm generation [yes]?
Generating the bundle code: OK
Checking that the bundle is autoloaded: OK
Confirm automatic update of your Kernel [yes]?
Enabling the bundle inside the Kernel: OK
Confirm automatic update of the Routing [yes]?
Importing the bundle routing resource: OK
src/FranMoreno/BetabeersBundle
├── Controller
│ └── DefaultController.php
├── DependencyInjection
├── Resources
│ ├── config
│ │ └── services.xml
│ ├── doc
│ ├── public
│ │ ├── css
│ │ ├── images
│ │ └── js
│ ├── translations
│ └── views
│ └── Default
│ └── index.html.twig
├── Tests
└── BetabeersBundle.php
class User
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(name="firstname", type="string", length=50)
* @Assert\NotBlank()
*/
private $firstname;
/**
* @ORM\ManyToOne(targetEntity="FranMoreno\BetabeersBundle\Entity\Country")
* @ORM\JoinColumn(name="coutry_id", referencedColumnName="id")
* @Assert\NotNull()
*/
private $country;
/**
* @ORM\OneToOne(targetEntity="FranMoreno\BetabeersBundle\Entity\Profile", mappedBy="user")
*/
private $profile;
/**
* @ORM\OneToMany(targetEntity="FranMoreno\BetabeersBundle\Entity\Address", mappedBy="user")
*/
private $addresses;
}
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstname')
->add('country', 'entity', array(
'class' => 'FranMoreno\BetabeersBundle\Entity\Country'
))
->add('profile', new ProfileType())
->add('addresses', 'collection', array(
'type' => new AddressType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'FranMoreno\BetabeersBundle\Entity\User'
));
}
public function getName()
{
return 'user';
}
}
/**
* @Route("/user")
*/
class UserController extends Controller
{
/**
* @Route("/new", name="user_new")
* @Template()
*/
public function newAction(Request $request)
{
$entity = new User();
$form = $this->createForm(new UserType(), $entity);
if ($request->isMethod("POST")) {
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('user_show', array(
'id' => $entity->getId()
)));
}
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
{% extends '::base.html.twig' %}
{% block javascripts %}
{{ parent() }}
<script src="{{ asset('bundles/betabeers/js/validation.js') }}"></script>
{% endblock %}
{% block content %}
<h1>User creation</h1>
<form action="{{ path('user_new') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<p>
<button type="submit">Create</button>
</p>
</form>
<a href="{{ path('homepage') }}">Back to the list</a>
{% endblock %}
php app/console doctrine:generate:crud
The Entity shortcut name: BetabeersBundle:User
Do you want to generate the "write" actions [no]? yes
Configuration format (yml, xml, php, or annotation) [annotation]:
Routes prefix [/user]:
Do you confirm generation [yes]?
Generating the CRUD code: OK
Generating the Form code: OK
src/FranMoreno/BetabeersBundle
├── Controller
│ └── UserController.php
├── Entity
│ └── User.php
├── Form
│ └── UserType.php
├── Resources
│ └── views
│ └── User
│ ├── edit.html.twig
│ ├── index.html.twig
│ ├── new.html.twig
│ └── show.html.twig
└── Tests
└── Controller
└── UserControllerTest.php