Nous avons vu dans les article précédents comment
    initialiser un projet Symfony 6 + Sonata 5 avec les médias
    et les utilisateurs dans un admin sécurisé. Nous
    avons vu ensuite comment gérer les localisations de
    l’utilisateur.
Nous allons voir maintenant comment
    installer et gérer les classifications.
On procède à l’installation de la dernière version en date.
php8.1 composer.phar require  sonata-project/classification-bundle:5.x-dev
Visiblement, nous avons une erreur de configuration.
Unrecognized option "media" under "sonata_classification.class". Available   
!!    options are "category", "collection", "context", "tag".      
On retire la section médias de la configuration sonata_classification.yaml
sonata_classification:
    class:
        category: App\Entity\SonataClassificationCategory
        collection: App\Entity\SonataClassificationCollection
        context: App\Entity\SonataClassificationContext
        tag: App\Entity\SonataClassificationTag
        #media: App\Entity\SonataMediaMedia
Nous avons ensuite une nouvelle erreur.
PHP Fatal error:  Type of App\Entity\SonataClassificationCategory::$children must be Doctrine\Common\Collections\Collection (as in class Sonata\ClassificationBundle\Model\Category) in /src/Entity/SonataClassificationCategory.php on line 18
Ce n’est pas grave, on va tout configurer pour que ça
    passe du premier coup.
On va déjà
    implémenter nos entity dans un répertoire autre que
    src/app histoire de ne pas polluer notre application avec les
    surcharges de nos bundles. Tout comme UserBundle et MediaBundle,
    on met ça dans
    src/Application/Sonata/ClassificationBundle/Entity et on va
    créer nos 4
    fichiers.
src/Application/Sonata/ClassificationBundle/Entity/SonataClassificationCategory.php
<?php
declare(strict_types=1);
namespace App\Application\Sonata\ClassificationBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\ClassificationBundle\Entity\BaseCategory;
/**
 * @ORM\Entity
 * @ORM\Table(name="classification__category")
 */
class SonataClassificationCategory extends BaseCategory
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    protected $id;
    
    public function getId(): ?int
    {
        return $this->id;
    }
}
?>
src/Application/Sonata/ClassificationBundle/Entity/SonataClassificationCollection.php
<?php 
declare(strict_types=1);
namespace App\Application\Sonata\ClassificationBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\ClassificationBundle\Entity\BaseCollection;
/**
 * @ORM\Entity
 * @ORM\Table(name="classification__collection")
 */
class SonataClassificationCollection extends BaseCollection
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    protected $id;
    
    public function getId(): ?int
    {
        return $this->id;
    }
}
?>
src/Application/Sonata/ClassificationBundle/Entity/SonataClassificationContext.php
<?php 
declare(strict_types=1);
namespace App\Application\Sonata\ClassificationBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\ClassificationBundle\Entity\BaseContext;
/**
 * @ORM\Entity
 * @ORM\Table(name="classification__context")
 */
class SonataClassificationContext extends BaseContext
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="string", length=64, nullable=false)
     */
     protected ?string $id = null;
    
    public function getId(): ?string
    {
        return $this->id;
    }
}
?>
src/Application/Sonata/ClassificationBundle/Entity/SonataClassificationTag.php
<?php
declare(strict_types=1);
namespace App\Application\Sonata\ClassificationBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\ClassificationBundle\Entity\BaseTag;
/**
 * @ORM\Entity
 * @ORM\Table(name="classification__tag")
 */
class SonataClassificationTag extends BaseTag
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    protected $id;
    
    public function getId(): ?int
    {
        return $this->id;
    }
}
Ensuite, il nous faut donner les path de nos classes dans config/packages/sonata_classification.yaml
sonata_classification:
    class:
        category: App\Application\Sonata\ClassificationBundle\Entity\SonataClassificationCategory
        collection: App\Application\Sonata\ClassificationBundle\Entity\SonataClassificationCollection
        context: App\Application\Sonata\ClassificationBundle\Entity\SonataClassificationContext
        tag: App\Application\Sonata\ClassificationBundle\Entity\SonataClassificationTag
   
Il faut aussi que l’on ajoute le path de la classe catégorie dans la définition des médias du fichier config/packages/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
        category: App\Application\Sonata\ClassificationBundle\Entity\SonataClassificationCategory
On ajoute notre bundle dans 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\UserBundle:
                is_bundle: false
                dir: '%kernel.project_dir%/src/Application/Sonata/UserBundle/Entity'
                prefix: 'App\Application\Sonata\UserBundle\Entity'
                alias: App\Application\Sonata\UserBundle
            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
            App\Application\Sonata\ClassificationBundle:
                is_bundle: false
                dir: '%kernel.project_dir%/src/Application/Sonata/ClassificationBundle/Entity'
                prefix: 'App\Application\Sonata\ClassificationBundle\Entity'
                alias: App\Application\Sonata\ClassificationBundle
                
            translatable:
                type: annotation # or attribute
                alias: Gedmo
                prefix: Gedmo\Translatable\Entity
                # make sure vendor library location is correct
                dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Entity"
        filters:
            softdeleteable:
                class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
On crée le schéma de la base de données.
 php8.1 bin/console doctrine:schema:update --force
 
    On ajoute nos interfaces dans l’admin dans le fichier config/packages/sonata_admin.yaml
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:
            runroom:
#                label: Base
#                items:
#                    - Runroom\SeoBundle\Admin\MetaInformationAdmin
#                    - Runroom\BasicPageBundle\Admin\BasicPageAdmin
#                    - Runroom\TranslationBundle\Admin\TranslationAdmin
#                    - Runroom\RedirectionBundle\Admin\RedirectAdmin
#                    - label: Cookies
#                      route: admin_runroom_cookies_cookiespage_edit
#                      route_params: { id: 1 }
            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
                    
            classification:
                label: Classification
                icon: <i class="fa fa-tags"></i>
                items:
                    - sonata.classification.admin.category
                    - sonata.classification.admin.tag
                    - sonata.classification.admin.collection
                    - sonata.classification.admin.context
                    
Et tout devrait fonctionner normalement.
 
    On passe une commande de migration pour mettre à jour tous
    les éléments avec le contexte par
    défaut.
A priori on a pas beaucoup
    d’éléments à migrer à ce stade.
php8.1 bin/console sonata:classification:fix-context
 
     
        