Đây là các lệnh để khởi tạo một dự án Symfony với quản trị an toàn.
Để chạy Symfony 6, chúng ta cần cài đặt php8.0 hoặc php8.1
Đối với php8.0
sudo apt-get install php8.0-cli libapache2-mod-php8.0 php8.0-common php8.0-opcache php8.0-igbinary php8.0-imagick  php8.0-msgpack php8.0-readline  php8.0-memcached  php8.0-xml php8.0-mbstring php8.0-gd php8.0-mysql php8.0-curl php8.0-intl php8.0-memcache php8.0-memcached  memcached libapache2-mod-php8.0 php8.0-zip php8.0-mysql
 Đối với php8.1
sudo apt-get install php8.1-cli libapache2-mod-php8.1 php8.1-common php8.1-opcache php8.1-igbinary php8.1-imagick  php8.1-msgpack php8.1-readline  php8.1-memcached  php8.1-xml php8.1-mbstring php8.1-gd php8.1-mysql php8.1-curl php8.1-intl php8.1-memcache php8.1-memcached  memcached libapache2-mod-php8.1 php8.1-zip php8.1-mysql
 Sau đó, chúng ta cài đặt khung sườn của dự án.
php8.1 composer.phar create-project symfony/skeleton:"6.0.x-dev" skeleton-sf6
cp composer.phar skeleton-sf6/
cd skeleton-sf6
php8.1 composer.phar require webapp
 Lúc này, chúng ta kiểm tra xem mọi thứ có hoạt động không bằng cách khởi chạy máy chủ web tích hợp của PHP.
php8.1 -S localhost:8000 -t public
 Điều này cung cấp cho chúng ta URL sau trong trình duyệt: http://localhost:8000/
 
    
    Tiếp theo, chúng ta cài đặt user-bundle, là cần thiết cho quản trị Sonata. Nó sẽ cài đặt tất cả các phụ thuộc cần thiết, bao gồm Sonata/admin.
Chúng ta chú ý hạ cấp Symfony/translation vì nó quá mới trong khung sườn của chúng ta cho Sonata tại thời điểm này.
php8.1 composer.phar require symfony/translation-contracts:2.5
php8.1 composer.phar require sonata-project/user-bundle:5.x-dev
php8.1 bin/console assets:install
 Chúng ta gặp phải vấn đề đầu tiên:
 The child config "resetting" under "sonata_user" must be configured. 
 Đối với điều này, chúng ta cần thêm cấu hình mặc định trong /config/packages/sonata_user.yaml
#####/config/packages/sonata_user.yaml
sonata_user:
    class:
        user: App\Entity\User
    resetting:
        email:
            address: "test@test.com"
            sender_name: Backoffice
 Và thực hiện lệnh console/bin cache:clear
php8.1 bin/console cache:clear
 Sau đó, chúng ta cài đặt Sonata/admin. Bằng cách cài đặt doctrine-orm-admin-bundle, chúng ta sẽ tự động cài đặt admin-bundle, tránh mọi xung đột.
php8.1 composer.phar require sonata-project/doctrine-orm-admin-bundle
php8.1 bin/console assets:install
 Chúng ta kiểm tra trang web của mình từ máy chủ web.
php8.1 -S localhost:8000 -t public
 Chúng ta nên nhận được lỗi sau:
An exception has been thrown during the rendering of a template ("Asset manifest file "/public/build/manifest.json" does not exist.").
 
Il faudra installer webpack
 
yarn add --dev @symfony/webpack-encore
yarn add webpack-notifier --dev
yarn encore dev
 Sonata admin đã được cài đặt đúng. Xác thực chưa được cấu hình, và chúng ta vẫn thiếu quản lý media và phân loại (chúng ta sẽ xem xét phân loại trong một bài viết tương lai).
 
    Chúng ta cài đặt và cấu hình ACLs.
php8.1 composer.phar require symfony/acl-bundle
 Chúng ta cấu hình sonata_user.yml
#####/config/packages/sonata_user.yaml
sonata_user:
    class:
        user: App\Entity\User
    resetting:
        email:
            address: "test@test.com"
            sender_name: Backoffice
            
    security_acl: true
    manager_type: orm # can be orm or mongodb
 Chúng ta cấu hình security.yaml
#####/config/packages/security.yaml
security:
    enable_authenticator_manager: true
    password_hashers:
        Sonata\UserBundle\Model\UserInterface:
            algorithm: auto
    providers:
        sonata_user_bundle:
            id: sonata.user.security.user_provider
    access_decision_manager:
        strategy: unanimous   
    
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        admin:
            lazy: true
            pattern: /admin(.*)
            provider: sonata_user_bundle
            context: user
            switch_user: true
            form_login:
                login_path: sonata_user_admin_security_login
                check_path: sonata_user_admin_security_check
                default_target_path: sonata_admin_dashboard
            logout:
                path: sonata_user_admin_security_logout
                target: sonata_user_admin_security_login
            remember_me:
                #secret: "%env(APP_SECRET)%"
                secret: "123456"
                lifetime: 2629746
                path: /admin
    
    access_control:
        - { path: ^/admin/login$, role: PUBLIC_ACCESS }
        - { path: ^/admin/logout$, role: PUBLIC_ACCESS }
        - { path: ^/admin/login_check$, role: PUBLIC_ACCESS }
        - { path: ^/admin/request$, role: PUBLIC_ACCESS }
        - { path: ^/admin/check-email$, role: PUBLIC_ACCESS }
        - { path: ^/admin/reset/.*$, role: PUBLIC_ACCESS }
        - { path: ^/admin/, role: ROLE_ADMIN }    
    
    role_hierarchy:
        ROLE_ADMIN:
            - ROLE_USER
            - ROLE_SONATA_ADMIN
            - ROLE_SONATA_USER_ADMIN_USER_VIEW
        ROLE_SUPER_ADMIN:
            - ROLE_ADMIN
            - ROLE_ALLOWED_TO_SWITCH        
   
 Chúng ta thêm các tuyến đường admin.
#####/config/route.yaml
sonata_user_admin_security:
    resource: '@SonataUserBundle/Resources/config/routing/admin_security.xml'
    prefix: /admin
sonata_user_admin_resetting:
    resource: '@SonataUserBundle/Resources/config/routing/admin_resetting.xml'
    prefix: /admin/resetting
 Chúng ta tạo ra thực thể người dùng của mình.
#/src/Entity/User.php
<?php 
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\UserBundle\Entity\BaseUser;
/**
 * @ORM\Entity
 * @ORM\Table(name="user__user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    protected $id;
}
 Chúng ta cập nhật sơ đồ cơ sở dữ liệu và tạo người dùng admin của mình.
php8.1 bin/console doctrine:schema:update --force
php8.1 bin/console sonata:user:create admin admin@test.com admin123456
php8.1 bin/console sonata:user:promote --super-admin admin
 Chúng ta khởi động lại máy chủ của mình và kiểm tra URL: http://localhost:8000/admin/dashboard
php8.1 -S localhost:8000 -t public
 Chúng ta được chuyển hướng chính xác đến màn hình đăng nhập.
 
    Người dùng được phép nhập vào quản trị.
 
    Bây giờ, chúng ta cấu hình quản lý media.
Chúng ta tạo 3 thực thể: Gallery, GalleryItem, và Media trong một cấu trúc thư mục riêng biệt để không làm lộn xộn ứng dụng của chúng ta. Chúng ta sẽ làm tương tự cho UserBundle và ClassificationBundle.
Chúng ta sẽ đặt tất cả trong src/Application/Sonata/MediaBundle/Entity
<?php
declare(strict_types=1);
namespace App\Application\Sonata\MediaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\MediaBundle\Entity\BaseGallery;
/**
 * @phpstan-extends BaseGallery<GalleryItem>
 *
 * @ORM\Entity
 * @ORM\Table(name="media__gallery")
 */
class Gallery extends BaseGallery
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;
    public function getId(): ?int
    {
        return $this->id;
    }
}
 
<?php
declare(strict_types=1);
namespace App\Application\Sonata\MediaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\MediaBundle\Entity\BaseGalleryItem;
/**
 * @ORM\Entity
 * @ORM\Table(name="media__gallery_media")
 */
class GalleryItem extends BaseGalleryItem
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;
    public function getId(): ?int
    {
        return $this->id;
    }
}
 
<?php
declare(strict_types=1);
namespace App\Application\Sonata\MediaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\MediaBundle\Entity\BaseMedia;
use App\Application\Sonata\ClassificationBundle\Entity\SonataClassificationCategory as SonataClassificationCategory;
/**
 * @ORM\Entity
 * @ORM\Table(name="media__media")
 */
class Media extends BaseMedia
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;
    
    /**
     * @var SonataClassificationCategory|null
     */
    protected ?object $category = null;
    public function getId(): ?int
    {
        return $this->id;
    }
    
    
    public function getCategory(): ?object
    {
        return $this->category;
    }
    
    public function setCategory(?object $category = null): void
    {
        $this->category = $category;
    }
}
 Chúng ta thêm cấu hình trong sonata_media.yaml
sonata_media:
    class:
        media: App\Application\Sonata\MediaBundle\Entity\Media
        gallery: App\Application\Sonata\MediaBundle\Entity\Gallery
        gallery_item: App\Application\Sonata\MediaBundle\Entity\GalleryItem
    default_context: default
    db_driver: doctrine_orm
    providers:
        file:
            allowed_extensions: [jpg, png, jpeg, pdf, ogv, mp4, webm]
            allowed_mime_types:
                - image/pjpeg
                - image/jpeg
                - image/png
                - image/x-png
                - application/pdf
                - application/x-pdf
                - application/ogg
                - video/mp4
                - video/webm
    contexts:
        default:
            providers:
                - sonata.media.provider.dailymotion
                - sonata.media.provider.youtube
                - sonata.media.provider.image
                - sonata.media.provider.file
                - sonata.media.provider.vimeo
            formats:
                small: { width: 100 , quality: 70}
                big:   { width: 500 , quality: 70}
    cdn:
        server:
            path: /upload/media
    filesystem:
        local:
            # Directory for uploads should be writable
            directory: "%kernel.project_dir%/public/upload/media"
            create: false
 Chúng ta thêm cấu trúc ghi đè của chúng ta cho MediaBundle trong config/packages/doctrine.yaml
doctrine:
    dbal:
        url: '%env(resolve:DATABASE_URL)%'
        # IMPORTANT: You MUST configure your server version,
        # either here or in the DATABASE_URL env var (see .env file)
        #server_version: '13'
    orm:
        auto_generate_proxy_classes: true
        naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
        auto_mapping: true
        mappings:
            App:
                is_bundle: false
                dir: '%kernel.project_dir%/src/Entity'
                prefix: 'App\Entity'
                alias: App
            App\Application\Sonata\MediaBundle:
                is_bundle: false
                dir: '%kernel.project_dir%/src/Application/Sonata/MediaBundle/Entity'
                prefix: 'App\Application\Sonata\MediaBundle\Entity'
                alias: App\Application\Sonata\MediaBundle
 
        filters:
            softdeleteable:
                class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
 Chúng ta cập nhật sơ đồ cơ sở dữ liệu.
php8.1 bin/console doctrine:schema:update --force
 Chúng ta cấu hình sonata_admin.yml mặc định của chúng ta.
sonata_admin:
    title: Backoffice
    title_logo: /bundles/sonataadmin/images/logo_title.png
    show_mosaic_button: false
    security:
        handler: sonata.admin.security.handler.role
    options:
        default_admin_route: edit
        html5_validate: false
    global_search:
        admin_route: edit
    breadcrumbs:
        child_admin_route: edit
    dashboard:
        groups:
            users:
                label: Users
                icon: <i class="fa fa-users"></i>
                on_top: true
                items:
                    - sonata.user.admin.user
            media:
                label: Media
                icon: <i class="fa fa-photo"></i>
                on_top: true
                items:
                    - sonata.media.admin.media
 Và mọi thứ hoạt động.
 
    