Make categories and project categories be related many-to-many in db

This commit is contained in:
2025-10-01 15:38:50 +02:00
parent 617196c66b
commit 423f0efcc6
5 changed files with 169 additions and 9 deletions
+82
View File
@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20251001132155 extends AbstractMigration
{
public function getDescription(): string
{
return 'Set and populate the `category` and `project_category` fields.';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
CREATE TABLE category (
id VARCHAR(255) NOT NULL,
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE project_category (
project_id INT NOT NULL,
category_id VARCHAR(255) NOT NULL,
INDEX IDX_3B02921A166D1F9C (project_id),
INDEX IDX_3B02921A12469DE2 (category_id),
PRIMARY KEY(project_id, category_id)
) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE
project_category
ADD
CONSTRAINT FK_3B02921A166D1F9C FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE
project_category
ADD
CONSTRAINT FK_3B02921A12469DE2 FOREIGN KEY (category_id) REFERENCES category (id) ON DELETE CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE project DROP category
SQL);
$this->addSql(<<<'SQL'
INSERT INTO category (id) VALUES ('education');
INSERT INTO category (id) VALUES ('culture');
INSERT INTO category (id) VALUES ('journalism');
INSERT INTO category (id) VALUES ('democracy');
INSERT INTO category (id) VALUES ('rural-development');
INSERT INTO category (id) VALUES ('health-and-cares');
INSERT INTO category (id) VALUES ('science-and-technology');
INSERT INTO category (id) VALUES ('sustainability');
INSERT INTO category (id) VALUES ('social-economy');
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE project_category DROP FOREIGN KEY FK_3B02921A166D1F9C
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE project_category DROP FOREIGN KEY FK_3B02921A12469DE2
SQL);
$this->addSql(<<<'SQL'
DROP TABLE category
SQL);
$this->addSql(<<<'SQL'
DROP TABLE project_category
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE project ADD category VARCHAR(255) NOT NULL
SQL);
}
}
@@ -13,7 +13,6 @@ use App\Dto\ProjectCreationDto;
use App\Dto\ProjectUpdationDto;
use App\Entity\Project\Project;
use App\Entity\Project\ProjectCalendar;
use App\Entity\Project\ProjectCategory;
use App\Entity\Project\ProjectDeadline;
use App\Entity\Project\ProjectStatus;
use App\Entity\Project\ProjectVideo;
@@ -109,11 +108,11 @@ class ProjectApiResource
public ProjectCalendar $calendar;
/**
* One of the available categories.
* A list of the available categories most relevant to this Project.
*/
#[Assert\NotBlank()]
#[API\ApiFilter(filterClass: SearchFilter::class, strategy: 'exact')]
public ProjectCategory $category;
public array $categories;
/**
* ISO 3166 data about the Project's territory of interest.
+19
View File
@@ -0,0 +1,19 @@
<?php
namespace App\Entity;
use App\Repository\CategoryRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: CategoryRepository::class)]
class Category
{
#[ORM\Id]
#[ORM\Column(length: 255)]
private ?string $id = null;
public function getId(): ?string
{
return $this->id;
}
}
+23 -6
View File
@@ -3,6 +3,7 @@
namespace App\Entity\Project;
use App\Entity\Accounting\Accounting;
use App\Entity\Category;
use App\Entity\Interface\AccountingOwnerInterface;
use App\Entity\Interface\LocalizedEntityInterface;
use App\Entity\Interface\UserOwnedInterface;
@@ -64,8 +65,11 @@ class Project implements UserOwnedInterface, AccountingOwnerInterface, Localized
#[ORM\Embedded(class: ProjectCalendar::class)]
private ?ProjectCalendar $calendar = null;
#[ORM\Column(enumType: ProjectCategory::class)]
private ?ProjectCategory $category = null;
/**
* @var Collection<int, Category>
*/
#[ORM\ManyToMany(targetEntity: Category::class)]
private Collection $categories;
/**
* Project's territory of interest.
@@ -145,6 +149,7 @@ class Project implements UserOwnedInterface, AccountingOwnerInterface, Localized
$this->budgetItems = new ArrayCollection();
$this->updates = new ArrayCollection();
$this->supports = new ArrayCollection();
$this->categories = new ArrayCollection();
}
public function getId(): ?int
@@ -219,14 +224,26 @@ class Project implements UserOwnedInterface, AccountingOwnerInterface, Localized
return $this;
}
public function getCategory(): ?ProjectCategory
/**
* @return Collection<int, Category>
*/
public function getCategories(): Collection
{
return $this->category;
return $this->categories;
}
public function setCategory(ProjectCategory $category): static
public function addCategory(Category $category): static
{
$this->category = $category;
if (!$this->categories->contains($category)) {
$this->categories->add($category);
}
return $this;
}
public function removeCategory(Category $category): static
{
$this->categories->removeElement($category);
return $this;
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace App\Repository;
use App\Entity\Category;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Category>
*/
class CategoryRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Category::class);
}
// /**
// * @return Category[] Returns an array of Category objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('c.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?Category
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}