«Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте.»
Стив Макконнелл
Ровно год назад я, впервые, устанавливал
и настраивал эту связку на одном из
проектов. Тогда, во время процесса
установки, постоянно возникали трудности
в виде различных ошибок, хотя следовал
я официальным документациям.
Несколько
дней назад перед мной снова стала эта
задача, я не стал копировать готовые
конфиги из предыдущих проектов, а решил
поднять эту связку заново на свеже
вышедшей версии Symfony 2.5.0.
К сожалению, спустя год, ничего не изменилось, во время установки сталкиваешься с теми же проблемами, поэтому я решил собрать всё воедино и написать правильную последовательность действий.
Все действия выполнялись на голом, только что установленном, Symfony 2.5.0.
Для начала, необходимо прописать вот
такие зависимости в файл composer.json:
{
....... "require": {
......
"friendsofsymfony/user-bundle": "~1.3", "sonata-project/core-bundle": "dev-master",
"sonata-project/admin-bundle": "dev-master",
"sonata-project/doctrine-orm-admin-bundle": "dev-master",
"sonata-project/easy-extends-bundle": "dev-master",
"sonata-project/user-bundle": "dev-master",
"sonata-project/datagrid-bundle": "dev-master"
}
}
php composer.phar updateИли просто "composer update" если composer установлен глобально в системе.
Активируем установленные бандлы, плюс бандлы, которые подтянулись как зависимости, обязательно надо активировать все следующие бандлы:
<?php
// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Sonata\CoreBundle\SonataCoreBundle(),
new Sonata\BlockBundle\SonataBlockBundle(),
new Knp\Bundle\MenuBundle\KnpMenuBundle(),
new Sonata\DoctrineORMAdminBundle\SonataDoctrineORMAdminBundle(),
new Sonata\AdminBundle\SonataAdminBundle(),
new Sonata\EasyExtendsBundle\SonataEasyExtendsBundle(),
new FOS\UserBundle\FOSUserBundle(),
new Sonata\UserBundle\SonataUserBundle('FOSUserBundle'),
);
}
Теперь пропишем конфиги для бандлов в app/config/config.yml:
# app/config/config.yml
# активируем поддержку многоязычности
framework:
translator: ~
sonata_block:
default_contexts: [cms]
blocks:
# Enable the SonataAdminBundle block
sonata.admin.block.admin_list:
contexts: [admin]
sonata.user.block.menu: # used to display the menu in profile pages
sonata.user.block.account: # used to display menu option (login option)
sonata.block.service.text: # used to if you plan to use Sonata user routes
sonata_user:
#security_acl: true # Uncomment for ACL support
manager_type: orm # can be orm or mongodb
fos_user:
db_driver: orm # can be orm or odm
firewall_name: main
user_class: Sonata\UserBundle\Entity\BaseUser
group:
group_class: Sonata\UserBundle\Entity\BaseGroup
group_manager: sonata.user.orm.group_manager
service:
user_manager: sonata.user.orm.user_manager
# app/config/config.yml doctrine:
dbal:
types:
json: Sonata\Doctrine\Types\JsonType
orm:
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
default:
auto_mapping: true
# app/config/config.yml
doctrine:
dbal:
types:
json: Sonata\Doctrine\Types\JsonType
orm:
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
default:
mappings:
#ApplicationSonataUserBundle: ~
SonataUserBundle: ~
FOSUserBundle: ~
Настроим security component в файле app/config/security.yml:
#app/config/security.yml
security:
# Uncomment for ACL support
#acl:
# connection: default
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_SONATA_ADMIN]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
SONATA:
- ROLE_SONATA_PAGE_ADMIN_PAGE_EDIT # comment it when using acl
providers:
fos_userbundle:
id: fos_user.user_provider.username
encoders:
FOS\UserBundle\Model\UserInterface: sha512
firewalls:
# -> custom firewall for the admin area of the URL
admin:
pattern: /admin(.*)
context: user
form_login:
provider: fos_userbundle
login_path: /admin/login
use_forward: false
check_path: /admin/login_check
failure_path: null
logout:
path: /admin/logout
anonymous: true
# -> end custom configuration
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
logout: true
anonymous: true
access_control:
# URL of FOSUserBundle which need to be available to anonymous users
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
# Admin login page needs to be access without credential
- { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY }
# Secured part of the site
# This config requires being logged for the whole site # and having the admin role for the admin part.
# Change these rules to adapt them to your needs
- { path: ^/admin/, role: [ROLE_ADMIN, ROLE_SONATA_ADMIN] }
- { path: ^/.*, role: IS_AUTHENTICATED_ANONYMOUSLY }
Добавляем рутинги бандлов app/config/routing.yml:
#app/config/routing.yml
# FOSUserBundle's routing
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
fos_user_profile:
resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
prefix: /profile
fos_user_register:
resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
prefix: /register
fos_user_resetting:
resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
prefix: /resetting
fos_user_change_password:
resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
prefix: /profile
# Admin's routing
sonata_user:
resource: '@SonataUserBundle/Resources/config/routing/admin_security.xml'
prefix: /admin
admin:
resource: '@SonataAdminBundle/Resources/config/routing/sonata_admin.xml'
prefix: /admin
_sonata_admin:
resource: .
type: sonata_admin
prefix: /admin
Теперь надо создать бандл, который будет расширять функциональность юзера, выполним следующую команду:
php app/console sonata:easy-extends:generate SonataUserBundle -d src
// app/AppKernel.php
class AppKernel {
public function registerbundles()
{
return array(
// ...
new Application\Sonata\UserBundle\ApplicationSonataUserBundle(),
)
}
}
# app/config/config.yml
fos_user:
db_driver: orm # can be orm or odm
firewall_name: main
user_class: Application\Sonata\UserBundle\Entity\User
group:
group_class: Application\Sonata\UserBundle\Entity\Group
group_manager: sonata.user.orm.group_manager
service:
user_manager: sonata.user.orm.user_manager
# app/config/config.yml
doctrine:
dbal:
types:
json: Sonata\Doctrine\Types\JsonType
orm:
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
default:
mappings:
ApplicationSonataUserBundle: ~
SonataUserBundle: ~
FOSUserBundle: ~
Устанавливаем ресурсы бандлов, чистим кеш и обновляем схему БД:
php app/console assets:install web
php app/console cache:clear
php app/console doctrine:schema:update --force
Всё, админка уже работает и доступна по адресу http://yoursite.dev/app_dev.php/admin
fos:user:create [--super-admin] [--inactive] username email passwordПосле этого входим в админку:
php app/console fos:user:create --super-admin admin admin@yoursite.dev qwerty
<?php
// src/Acme/BlogBundle/Admin/PostAdmin.php
namespace SW\BlogBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Show\ShowMapper;
class PostAdmin extends Admin
{
/**
* Конфигурация формы редактирования записи
*
* @param \Sonata\AdminBundle\Form\FormMapper $formMapper
*/
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('title', null, array('label' => 'Заголовок', 'attr' => array('style' => 'width:583px')))
->add('short_text', null, array('label' => 'Короткий текст', 'attr' => array('class' => 'foreditor', 'style' => 'width:569px;height:100px;')))
->add('text', null, array('label' => 'Текст', 'attr' => array('class' => 'foreditor', 'style' => 'width:569px;height:200px;')))
->add('tags', 'sonata_type_model', array('label' => 'Теги', 'by_reference' => false, 'multiple' => true, 'expanded' => true));
}
/**
* Конфигурация списка записей
*
* @param \Sonata\AdminBundle\Datagrid\ListMapper $listMapper
*/
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id')
->addIdentifier('title', null, array('label' => 'Заголовок'))
->add('slug', null, array('label' => 'URL'));
}
/**
* Поля, по которым производится поиск в списке записей
*
* @param \Sonata\AdminBundle\Datagrid\DatagridMapper $datagridMapper
*/
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('title', null, array('label' => 'Заголовок'));
}
}
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme.admin.post" class="Acme\BlogBundle\Admin\PostAdmin">
<tag name="sonata.admin" manager_type="orm" group="Посты" label="Посты"/>
<argument/>
<argument>Acme\BlogBundle\Entity\Blog\Post</argument>
<argument>SonataAdminBundle:CRUD</argument>
</service>
</services>
</container>
# app/config/config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: @AcmeBlogBundle/Resources/config/admin.xml }