2. ¿Que es Sonata?
Sonata fue creado por el entusiasta symfonyano Thomas Rabaix.
La meta del proyecto Sonata es proveer una solución e-commerce basado en Sf2. Pensado como un
conjunto de herramientas para hacer e-commerce de una manera fácil.
● Admin Bundle : Un bundle para generar una interface robusta y amistosa para el usuario.
● Media Bundle : Un bundle para manejar datos multimedia, la multimedia se refiere a archivos,
videos,imagenes.
● Page Bundle : Un bundle para transformar las acciones de Sf2 en un CMS.
3. Instalando y configurando
Añadir lo siguiente a tu archivo composer.json:
$ php composer.phar update
{
"require": {
...
"sonata-project/admin-bundle": "dev-master",
"friendsofsymfony/user-bundle": "dev-master",
"sonata-project/user-bundle": "dev-master",
"sonata-project/doctrine-orm-admin-bundle": "dev-master"
...
}
}
4. Registramos los bundles en app/AppKernel.php
// ...
public function registerBundles()
{
$bundles = array(
// ...
new FOSUserBundleFOSUserBundle(),
new SonatajQueryBundleSonatajQueryBundle(),
new SonataAdminBundleSonataAdminBundle(),
new SonataBlockBundleSonataBlockBundle(),
new SonataDoctrineORMAdminBundleSonataDoctrineORMAdminBundle(),
new KnpBundleMenuBundleKnpMenuBundle(),
new SonataUserBundleSonataUserBundle('FOSUserBundle'),
new SonataEasyExtendsBundleSonataEasyExtendsBundle(),
// ...
);
// ...
}
5. Editar los archivos config.yml, security.yml según la
configuración definida en:
http://blog.dayo.fr/2012/12/symfony2-1-sonata-admin-
sonata-user-fos-userbundle-en/
6. Listado de campos:
<?php
namespace SonataNewsBundleAdmin;
use SonataAdminBundleAdminAdmin;
use SonataAdminBundleFormFormMapper;
use SonataAdminBundleDatagridDatagridMapper;
use SonataAdminBundleDatagridListMapper;
use SonataAdminBundleShowShowMapper;
class PostAdmin extends Admin
{
protected function configureListFields (ListMapper $listMapper )
{
$listMapper
->addIdentifier ('title')
->add('author')
->add('enabled')
->add('tags')
->add('commentsEnabled' )
// add custom action links
->add('_action', 'actions', array(
'actions' => array(
'view' => array(),
'edit' => array(),)
));
}
}
7. Tipos disponibles:
● boolean
● datetime
● decimal
● identifier
● integer
● many_to_one : a link will be added to the related edit action
● string
● text
● date
● time
8. Acciones en el listado:
<?php
$listMapper ->add('_action', 'actions', array(
'actions' => array(
'view' => array(),
'edit' => array(),
)
))
Podemos editar y quitar las acciones. Podemos especificar las templates de renderizado
<?php
$listMapper ->add('_action', 'actions', array(
'actions' => array(
'view' => array(),
'edit' => array(),
'delete' => array('template' => 'MyBundle:MyController:my_partial.html.twig' ),
)
))
9. Mostrar sub entidades:
<?php
namespace AcmeAcmeBundleAdmin;
use SonataAdminBundleAdminAdmin;
use SonataAdminBundleFormFormMapper;
use SonataAdminBundleDatagridDatagridMapper;
use SonataAdminBundleDatagridListMapper;
use SonataAdminBundleShowShowMapper;
class UserAdmin extends Admin
{
protected function configureListFields (ListMapper $listMapper )
{
$listMapper
->addIdentifier ('id')
->addIdentifier ('firstName' )
->addIdentifier ('lastName')
->addIdentifier ('address.street' )
->addIdentifier ('address.ZIPCode' )
->addIdentifier ('address.town' )
;
}
}
10. Personalizando Templates
<?php
namespace SonataMediaBundleAdmin;
use SonataAdminBundleAdminAdmin;
use SonataAdminBundleFormFormMapper;
use SonataAdminBundleDatagridDatagridMapper;
use SonataAdminBundleDatagridListMapper;
use SonataAdminBundleShowShowMapper;
class MediaAdmin extends Admin
{
protected function configureListFields (ListMapper $listMapper )
{
$listMapper
->addIdentifier ('id')
->add('image', 'string', array('template' => 'SonataMediaBundle:MediaAdmin:list_image.html.twig' )
->add('custom', 'string', array('template' => 'SonataMediaBundle:MediaAdmin:list_custom.html.twig'
;
}
}
12. Redefinir el controlador CRUD
<?php
// src/Tutorial/BlogBundle/Controller/CommentAdminController.php
namespace TutorialBlogBundleController;
use SonataAdminBundleControllerCRUDController as Controller;
class CommentAdminController extends Controller
{
}
13. DoctrineFixturesBundle
Los accesorios se utilizan para cargar en una base de datos un juego de datos controlado. Puedes
utilizar estos datos para pruebas o podrían ser los datos iniciales necesarios para ejecutar la
aplicación sin problemas. Symfony2 no tiene integrada forma alguna de administrar accesorios, pero
Doctrine2 cuenta con una biblioteca para ayudarte a escribir accesorios para el ORM u ODM de
Doctrine.
14. Instalando y configurando
Añadir lo siguiente a tu archivo composer.json:
{
"require": {
"doctrine/doctrine-fixtures-bundle": "dev-
master"
}
}
$ php composer.phar update
Actualizar el composer
15. Por último, registramos el paquete DoctrineFixturesBundle en app/AppKernel.php
// ...
public function registerBundles()
{
$bundles = array(
// ...
new DoctrineBundleFixturesBundleDoctrineFixturesBundle(),
// ...
);
// ...
}
16. Escribiendo fixtures:
Los fixtures de Doctrine2 son clases PHP que pueden crear y persistir objetos a la base de datos. Al
igual que todas las clases en Symfony2, los fixtures deben estar alojado dentro de uno de los
paquetes de tu aplicación.
Para un paquete situado en src/Acme/HelloBundle, las clasesed los fixtures deben estar dentro de
src/Acme/HelloBundle/DataFixtures/ORM o src/Acme/HelloBundle/DataFixtures/MongoDB, para ORM
y ODM respectivamente, esta guía asume que estás utilizando el ORM — pero, los accesorios se
pueden agregar con la misma facilidad si estás utilizando ODM.
17. // src/Acme/HelloBundle/DataFixtures/ORM/LoadUserData.php
namespace AcmeHelloBundleDataFixturesORM;
use DoctrineCommonDataFixturesFixtureInterface;
use DoctrineCommonPersistenceObjectManager;
use AcmeHelloBundleEntityUser;
class LoadUserData implements FixtureInterface
{
/**
* {@inheritDoc}
*/
public function load(ObjectManager $manager)
{
$userAdmin = new User();
$userAdmin->setUsername('admin');
$userAdmin->setPassword('test');
$manager->persist($userAdmin);
$manager->flush();
}
}
18. Cargando los fixtures
php app/console doctrine:fixtures:load
php app/console doctrine:mongodb:fixtures:load
La tarea buscará dentro del directorio DataFixtures/ORM (o DataFixtures/MongoDB paraODM) de
cada paquete y ejecutará cada clase que implemente la FixtureInterface.
Ambas órdenes vienen con unas cuantas opciones:
● --fixtures=/ruta/al/accesorio — Usa esta opción para especificar manualmente el directorio de
donde se deben cargar las clases accesorio;
● --append — Utiliza esta opción para añadir datos en lugar de eliminarlos antes de cargarlos
(borrar primero es el comportamiento predeterminado);
● --em=manager_name — Especifica manualmente el gestor de la entidad a utilizar para cargar
los datos.
19. Compartiendo objetos entre fixtures
Si tenemos varias clases de fixtures y queremos referir a los datos cargados en otras clases.
Deberemos.
// src/Acme/HelloBundle/DataFixtures/ORM/LoadUserData.php
namespace AcmeHelloBundleDataFixturesORM;
use DoctrineCommonDataFixturesAbstractFixture;
use DoctrineCommonDataFixturesOrderedFixtureInterface;
use DoctrineCommonPersistenceObjectManager;
use AcmeHelloBundleEntityUser;
class LoadUserData extends AbstractFixture implements OrderedFixtureInterface
{
public function load(ObjectManager $manager)
{
$userAdmin = new User();
$userAdmin->setUsername('admin');
$userAdmin->setPassword('test');
$manager->persist($userAdmin);
$manager->flush();
$this->addReference('admin-user', $userAdmin);
}
public function getOrder()
{
return 1; // el orden en el cual serán cargados los accesorios
20. // src/Acme/HelloBundle/DataFixtures/ORM/LoadUserGroupData.php
namespace AcmeHelloBundleDataFixturesORM;
use DoctrineCommonDataFixturesAbstractFixture;
use DoctrineCommonDataFixturesOrderedFixtureInterface;
use DoctrineCommonPersistenceObjectManager;
use AcmeHelloBundleEntityUserGroup;
class LoadUserGroupData extends AbstractFixture implements OrderedFixtureInterface
{
public function load(ObjectManager $manager)
{
$userGroupAdmin = new UserGroup();
$userGroupAdmin->setUser($this->getReference('admin-user'));
$userGroupAdmin->setGroup($this->getReference('admin-group'));
$manager->persist($userGroupAdmin);
$manager->flush();
}
public function getOrder()
{
return 3;
}
}
21. Los fixtures ahora se ejecutan en orden ascendente del valor devuelto por getOrder(). Cualquier
objeto que se establece con el método setReference() se puede acceder a través de getReference()
en las clases accesorio que tienen un orden superior.
22. JsRoutingBundle:
Instalando y configurando
Añadir lo siguiente a tu archivo composer.json:
{
"require": {
"friendsofsymfony/jsrouting-bundle": "dev-
master"
}
}
$ php composer.phar update friendsofsymfony/jsrouting-bundle
Actualizar el composer
23. Registramos en el app/AppKernel.php
// ...
public function registerBundles()
{
$bundles = array(
// ...
new FOSJsRoutingBundleFOSJsRoutingBundle(),
// ...
);
// ...
}
24. # app/config/routing.yml
fos_js_routing:
resource: "@FOSJsRoutingBundle/Resources/config/routing/routing.xml"
$ php app/console assets:install --symlink web
Agregamos las siguientes líneas que apuntan al javascript edl bundle
<script src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script>
<script src="{{ path('fos_js_routing_js', {"callback": "fos.Router.setData"}) }}"></script>
Para usar agregamos en donde se debe especificar la url:
Routing.generate('route_id', /* your params */).
26. Routing.generate('my_route_to_expose', { id: 10 });
// will result in /foo/10/bar
Routing.generate('my_route_to_expose', { id: 10, foo: "bar" });
// will result in /foo/10/bar?foo=bar
$.get(Routing.generate('my_route_to_expose', { id: 10, foo: "bar" }));
// will call /foo/10/bar?foo=bar
Routing.generate('my_route_to_expose_with_defaults');
// will result in /blog/1
Routing.generate('my_route_to_expose_with_defaults', { id: 2 });
// will result in /blog/2
Routing.generate('my_route_to_expose_with_defaults', { foo: "bar" });
// will result in /blog/1?foo=bar
Routing.generate('my_route_to_expose_with_defaults', { id: 2, foo: "bar" });
// will result in /blog/2?foo=bar