Abbiamo visto in precedenti articoli come inizializzare un progetto Symfony 6 + Sonata 5 con media e utenti in un'amministrazione sicura. Abbiamo poi esaminato come gestire le localizzazioni degli utenti.
Ora vedremo come installare e gestire le classificazioni.
Procediamo con l'installazione dell'ultima versione disponibile al momento.
php8.1 composer.phar require sonata-project/classification-bundle:5.x-dev
Sembra che ci sia un errore di configurazione.
Unrecognized option "media" under "sonata_classification.class". Available
!! options are "category", "collection", "context", "tag".
Rimuoviamo la sezione dei media dalla configurazione 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
In seguito incontriamo un nuovo errore.
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
Non è un grosso problema; configureremo tutto affinché funzioni al primo tentativo.
Prima implementeremo le nostre entità in una directory diversa da src/app per non ingombrare la nostra applicazione con le sovraccariche dai nostri bundle. Proprio come per UserBundle e MediaBundle, le posizioniamo in src/Application/Sonata/ClassificationBundle/Entity e creeremo i nostri 4 file.
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;
}
}
In seguito, dobbiamo fornire i percorsi delle nostre classi in 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
Dobbiamo inoltre aggiungere il percorso della classe categoria alle definizioni dei media nel file 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
Aggiungiamo il nostro bundle in 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
Creiamo lo schema del database.
php8.1 bin/console doctrine:schema:update --force
Aggiungiamo le nostre interfacce all'amministrazione nel file 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
E tutto dovrebbe funzionare normalmente.
Lanciamo un comando di migrazione per aggiornare tutti gli elementi con il contesto predefinito.
Sembra che non abbiamo molti elementi da migrare in questa fase.
php8.1 bin/console sonata:classification:fix-context