Skip to content

[Laravel] BelongsTo Link is not working #6930

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

Closed
llei4 opened this issue Jan 28, 2025 · 1 comment
Closed

[Laravel] BelongsTo Link is not working #6930

llei4 opened this issue Jan 28, 2025 · 1 comment
Labels

Comments

@llei4
Copy link

llei4 commented Jan 28, 2025

API Platform version(s) affected: 4.0.16

Description
When creating a SubResource for a HasMany Realation on a Model Link Fails.
How to reproduce

Possible Solution
Having 2 Models:

GrandFather

<?php

namespace App\Models;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Link;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

#[ApiResource()]
#[ApiResource(
    uriTemplate: '/grand_sons/{id_grand_son}/grand_father',
    uriVariables: [
        'id_grand_son' => new Link(
            fromClass: GrandSon::class, 
            fromProperty: 'grandfather'
            )
    ],
    operations: [new Get()]
)]
class GrandFather extends Model
{
    protected $table = 'grand_fathers';
    protected $primaryKey = 'id_grand_father';
    protected $fillable = ['name','sons'];

    #[ApiProperty(genId: false, identifier: true)]
    private ?int $id_grand_father;

    private ?string $name = null;

    private ?Collection $sons = null;

    /**
     * @return HasMany
     */
    public function sons(): HasMany
    {
        return $this->hasMany(GrandSon::class,'grand_father_id','id_grand_father');
    }

}

GrandSon

<?php

namespace App\Models;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Link;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

#[ApiResource()]
#[ApiResource(
    uriTemplate: '/grand_fathers/{id_grand_father}/grand_sons',
    uriVariables: [
        'id_grand_father' => new Link(
            fromClass: GrandFather::class, 
            fromProperty: 'sons'
            )
    ],
    operations: [new GetCollection()]
)]
class GrandSon extends Model
{
    protected $table = 'grand_sons';
    protected $primaryKey = 'id_grand_son';
    protected $fillable = ['name','grand_father_id','grandfather'];

    #[ApiProperty(genId: false, identifier: true)]
    private ?int $id_grand_son;
    
    private ?string $name = null;

    private ?GrandFather $grandfather= null;

    /**
     * @return BelongsTo
     */
    public function grandfather(): BelongsTo
    {
        return $this->belongsTo(GrandFather::class,'grand_father_id','id_grand_father');
    }
}

Created Using Following Migrations:

GrandFather:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('grand_fathers', function (Blueprint $table) {
            $table->increments('id_grand_father');
            $table->string('name');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('grand_fathers');
    }
};

GrandSon:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('grand_sons', function (Blueprint $table) {
            $table->increments('id_grand_son');
            $table->string('name');
            $table->unsignedInteger('grand_father_id')->nullable();
            $table->timestamps();
            $table->foreign('grand_father_id')->references('id_grand_father')->on('grand_fathers');

        });

    }

    public function down(): void
    {
        Schema::dropIfExists('grand_sons');
    }
};

Creates 2 Endpoints:

  1. /api/grand_fathers/{id_grand_father}/grand_sons

Calling:

curl -X 'GET' \
  'http://localhost:8008/api/grand_fathers/1/grand_sons?page=1' \
  -H 'accept: application/ld+json'

Works Properly and returns all GrandSons belonging to GrandFather with id_grand_father = {id_grand_father}

  1. /api/grand_sons/{id_grand_son}/grand_father

Carlling:

curl -X 'GET' \
  'http://localhost:8008/api/grand_sons/1/grand_father' \
  -H 'accept: application/ld+json'

Returns Error:

"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'grand_sons.grand_father_id' in 'where clause' (Connection: mysql, SQL: select * from `grand_fathers` where `grand_sons`.`grand_father_id` = 1 limit 1)"`

As you can see, the query is missformed.

Possible Solution

I think commit 5818e80 fixed BelongsToMany Relation but still is not manageing BelongsTo Relations.

My suggestion is adding the following code after managing BelonsToMany Relations here

EDIT

The correct code should be:

...
            // BelongsTo Relation
            if(method_exists($relation->{$from}(), 'dissociate')) 
            {    
                return $builder->getModel()->where($builder->getModel()->getQualifiedKeyName(), $identifier);
            }
...
Copy link

stale bot commented Mar 30, 2025

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 Mar 30, 2025
@stale stale bot closed this as completed Apr 7, 2025
@soyuka soyuka added bug and removed stale labels Apr 8, 2025
@soyuka soyuka reopened this Apr 8, 2025
soyuka added a commit to soyuka/core that referenced this issue Apr 10, 2025
soyuka added a commit to soyuka/core that referenced this issue Apr 10, 2025
soyuka added a commit that referenced this issue Apr 10, 2025
soyuka added a commit to soyuka/core that referenced this issue Apr 10, 2025
@soyuka soyuka closed this as completed Apr 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants