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