Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(metadata) Load external PHP file resources #7017

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

loic425
Copy link
Contributor

@loic425 loic425 commented Mar 13, 2025

Q A
Branch? main
Tickets
License MIT
Doc PR api-platform/docs#...

The idea of this PoC is to allow configuring resources and their operations with external PHP files instead of XML/YAML files, which will be useful for projects such as Sylius.

This PR is not ready to merge, there are no PHPUnit tests, I've just used a minimalist Symfony app to test it.
The goal of this PR is to open discussions and make an ADR later.

I already know there are also some discussions about customizing the existing operations but that could be based on this PHP file resource extractor. (I already made a PoC about that too in a CustomResourceMetadataCollectionFactory on the Sylius resource side).

api_platform:
    title: Hello API Platform
    version: 1.0.0
    defaults:
        stateless: true
        cache_headers:
            vary: ['Content-Type', 'Authorization', 'Origin']
    mapping:
        imports:
            - '%kernel.project_dir%/config/api_platform/resources'
        paths:
            - '%kernel.project_dir%/src/Entity'

The main issue is that we cannot load PHP files that are in the autoloader, cause it will throw an error, indicating the class already exist. That's the reason I added an "imports" part to the mapping configuration to solve the issue for the PoC.

<?php
// config/api_platform/resources/speaker.php
declare(strict_types=1);

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Operations;
use ApiPlatform\Metadata\Post;
use App\Entity\Speaker;

return (new ApiResource())
    ->withClass(Speaker::class)
    ->withOperations(new Operations([
        new Post(),
        new Get(),
        new GetCollection(),
    ]))
;

we instanciate the ApiResource, so it's the same DX as we already have when configuring the entity with the attributes.

<?php
// src/Entity/Conference.php
declare(strict_types=1);

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use App\Repository\ConferenceRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: ConferenceRepository::class)]
#[ApiResource]
class Conference
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;
    
    // ...
}

Here, it's just to show the current implementation with attributes still works.

image
We both have our Conference Entity with the ApiResource attribute and our Speaker entity configured with an external PHP file.

image

I've tried to get the collection and to add a new speaker and it works perfectly.

@loic425 loic425 marked this pull request as draft March 13, 2025 16:39
@loic425 loic425 force-pushed the feat/external-php-file branch from e44b66c to 10224da Compare March 14, 2025 10:11
@soyuka
Copy link
Member

soyuka commented Mar 14, 2025

@dunglas thoughts ? I quite like the idea.

As folluw-up you'd be able to overwrite sylius resources using something like this:

return $syliusProductResource->withShortName('overriden'); 

?

@dunglas
Copy link
Member

dunglas commented Mar 14, 2025

I like the idea too!

@loic425 loic425 force-pushed the feat/external-php-file branch from 10224da to 0d3b24a Compare March 14, 2025 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants