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

[Eloquent] Add basic data provider / persister #4197

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

alanpoulain
Copy link
Member

@alanpoulain alanpoulain commented Apr 8, 2021

Q A
Branch? main
Bug fix? no
New feature? yes
Deprecations? yes/no
Tickets N/A
License MIT
Doc PR TODO

First step of having an Eloquent support in API Platform. No filter and extension (no pagination) for now.

Eloquent support is based on the great WouterJEloquentBundle.

Some inspiration has been taken from EloquentSerializer.

In order to list the properties of the resource (since Eloquent models don't have this information), this PR brings two possibilities:

  • using directly Eloquent models as resources and using a protected $apiProperties class property,
  • using Eloquent models as "data models" and link them to classical resources.

Being "magic" by retrieving the properties in the table, like it's done for instance in larastan, could be done afterwards (but there are some issues, for instance the migrations need to have been executed beforehand).
Related library: https://github.com/spatie/laravel-model-info

Only crud.feature and relation.feature are tested for now, the aim is to cover all the Behat tests in the end.

Using Eloquent models as resources with $apiProperties class property

Example:

<?php

declare(strict_types=1);

namespace App\Model;

use ApiPlatform\Core\Annotation\ApiResource;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;

#[ApiResource(
    normalizationContext: ['groups' => ['read']]
)]
class Dummy extends Model
{
    public $timestamps = false;

    protected $apiProperties = [
        'name',
        'description' => ['groups' => 'read'],
        'relatedDummy' => ['relation' => RelatedDummy::class, 'groups' => 'read'],
    ];

    public function relatedDummy(): HasOne
    {
        return $this->hasOne(RelatedDummy::class);
    }
}

Using Eloquent models as "data models" and link them to classical resources

The Eloquent data model should look like this:

<?php

declare(strict_types=1);

namespace App\Model;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;

class Dummy extends Model
{
    public $timestamps = false;

    public static $snakeAttributes = false;

    public function relatedDummy(): HasOne
    {
        return $this->hasOne(RelatedDummy::class);
    }
}

Notice the usage of snakeAttributes in order to avoid issue when normalizing / denormalizing the Eloquent model.

The resource should look like this:

<?php

declare(strict_types=1);

namespace App\Resource;

use ApiPlatform\Core\Annotation\ApiResource;
use App\Model\DummyModel;
use Symfony\Component\Serializer\Annotation\Groups;

#[ApiResource(
    dataModel=DummyModel::class,
    normalizationContext: ['groups' => ['read']],
)]
class Dummy
{
    public int $id;

    public ?string $name = null;

    #[Groups(['read'])]
    public ?string $description = null;

    #[Groups(['read'])]
    public ?RelatedDummy $relatedDummy = null;
}

This data model mapping has been thought to be compatible with all the providers. It should be compatible with Doctrine too (not tested yet).

@soyuka

This comment has been minimized.

@alanpoulain

This comment has been minimized.

@soyuka

This comment has been minimized.

@alanpoulain

This comment has been minimized.

@divine

This comment has been minimized.

@alanpoulain

This comment has been minimized.

@dunglas

This comment has been minimized.

@divine

This comment has been minimized.

@alanpoulain

This comment has been minimized.

@alanpoulain

This comment has been minimized.

@dunglas

This comment has been minimized.

@divine

This comment has been minimized.

@alanpoulain alanpoulain force-pushed the feat/eloquent-data-provider branch from df6515b to c43187e Compare May 7, 2021 16:32
@wouterj
Copy link

wouterj commented May 11, 2021

Just my 2 cents: Back in 5.x days of Laravel, supporting Eloquent outside the Laravel framework was indeed very difficult and required quite a lot of hacking. Since the introduction of semver in Laravel 6.0, I've found adding support for newer versions to be much much easier. I even changed the version constraints from a specific minor to a specific major in my bundle.

Upgrading from major to major has been smooth sailing as well:

In other words: I'm quite positive about maintaining support for the newer Eloquent versions once the implementation is build (and respect to @alanpoulain for going through the initial work on that!).

@alanpoulain
Copy link
Member Author

Hello @wouterj. Thanks for your input. It's great to know that the Laravel ecosystem is becoming more professional since the introduction of semver and that the bundle will follow the future Eloquent versions as well!

@alanpoulain alanpoulain force-pushed the feat/eloquent-data-provider branch 6 times, most recently from 458973a to e305079 Compare May 20, 2021 16:43
@stale
Copy link

stale bot commented Nov 14, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 14, 2022
@soyuka soyuka added this to the 4.0 milestone Nov 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants