laravel-json-api / laravel

JSON:API for Laravel applications
MIT License
550 stars 42 forks source link

Conditional Relationships in API Resource breaks relationship endpoints #130

Closed helmroos closed 2 years ago

helmroos commented 3 years ago

Using Conditional Relationships in a API Resource class breaks the relationship self/related endpoints.

How to repro

  1. Have two related models, e.g. Users and Team
  2. In your UserSchema.php add the Team relationship like
    
    use LaravelJsonApi\Eloquent\Fields\Relations\BelongsTo;

class UserSchema extends Schema { public function fields(): array { return [ ... BelongsTo::make('team'), ... ]; } }

3. Setup routes, the following endpoints should now work:
  - `/users/:id?include=team`
  - `/users/:id/team`
  - `/users/:id/relationships/team`
4. Now define a **UserResource.php** like so

use Illuminate\Http\Request; use LaravelJsonApi\Core\Resources\JsonApiResource;

class UserResource extends JsonApiResource {

...

public function relationships($request): iterable
{
    return [
        $this->relation('team')),
    ];
}

}

5. Try the three endpoints again, they should still work (3)
6. Now make the relationships in the UserResource conditional:

return [ $this->when(1===1, $this->relation('team')), ];

7. Try the endpoints again, the relationship ones are now broken:
  - `/users/:id?include=team` => ✅ 200 OK
  - `/users/:id/team` => ☠️ 500 INTERNAL SERVER ERROR
  - `/users/:id/relationships/team` => ☠️500 INTERNAL SERVER ERROR

### Stacktrace

[2021-10-07 10:15:21] local.ERROR: Call to undefined method LaravelJsonApi\Core\Resources\ConditionalField::fieldName() {"userId":"2f667dda-026e-4c8a-9acf-9e48523a2059","exception":"[object] (Error(code: 0): Call to undefined method LaravelJsonApi\Core\Resources\ConditionalField::fieldName() at /var/www/html/vendor/laravel-json-api/core/src/Core/Resources/JsonApiResource.php:262) [stacktrace]

0 /var/www/html/vendor/laravel-json-api/core/src/Core/Responses/Internal/RelatedResourceResponse.php(108): LaravelJsonApi\Core\Resources\JsonApiResource->relationship()

1 /var/www/html/vendor/laravel-json-api/core/src/Core/Responses/Internal/RelatedResourceResponse.php(97): LaravelJsonApi\Core\Responses\Internal\RelatedResourceResponse->metaForRelationship()

2 /var/www/html/vendor/laravel-json-api/core/src/Core/Responses/Internal/RelatedResourceResponse.php(81): LaravelJsonApi\Core\Responses\Internal\RelatedResourceResponse->allMeta()

3 /var/www/html/vendor/laravel-json-api/core/src/Core/Responses/RelatedResponse.php(110): LaravelJsonApi\Core\Responses\Internal\RelatedResourceResponse->toResponse()

4 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(776): LaravelJsonApi\Core\Responses\RelatedResponse->toResponse()

5 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(763): Illuminate\Routing\Router::toResponse()

6 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(695): Illuminate\Routing\Router->prepareResponse()

7 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\Routing\Router->Illuminate\Routing\{closure}()

8 /var/www/html/vendor/laravel-json-api/laravel/src/Http/Middleware/BootJsonApi.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

9 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): LaravelJsonApi\Laravel\Http\Middleware\BootJsonApi->handle()

10 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

11 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Routing\Middleware\SubstituteBindings->handle()

12 /var/www/html/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php(44): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

13 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Auth\Middleware\Authenticate->handle()

14 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

15 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle()

16 /var/www/html/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

17 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\View\Middleware\ShareErrorsFromSession->handle()

18 /var/www/html/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

19 /var/www/html/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\Session\Middleware\StartSession->handleStatefulRequest()

20 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Session\Middleware\StartSession->handle()

21 /var/www/html/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

22 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle()

23 /var/www/html/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

24 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Cookie\Middleware\EncryptCookies->handle()

25 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

26 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(697): Illuminate\Pipeline\Pipeline->then()

27 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(672): Illuminate\Routing\Router->runRouteWithinStack()

28 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(636): Illuminate\Routing\Router->runRoute()

29 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(625): Illuminate\Routing\Router->dispatchToRoute()

30 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(166): Illuminate\Routing\Router->dispatch()

31 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}()

32 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

33 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle()

34 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull->handle()

35 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

36 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle()

37 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\TrimStrings->handle()

38 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

39 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle()

40 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

41 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle()

42 /var/www/html/vendor/fruitcake/laravel-cors/src/HandleCors.php(52): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

43 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Fruitcake\Cors\HandleCors->handle()

44 /var/www/html/vendor/fideloper/proxy/src/TrustProxies.php(57): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

45 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Fideloper\Proxy\TrustProxies->handle()

46 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()

47 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(141): Illuminate\Pipeline\Pipeline->then()

48 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(110): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter()

49 /var/www/html/public/index.php(52): Illuminate\Foundation\Http\Kernel->handle()

50 /var/www/html/server.php(21): require_once('...')

51 {main}

"}


### Response

500 INTERNAL SERVER ERROR

{ "jsonapi": { "version": "1.0" }, "errors": [ { "detail": "Call to undefined method LaravelJsonApi\Core\Resources\ConditionalField::fieldName()", "meta": { "exception": "Error", "file": "/var/www/html/vendor/laravel-json-api/core/src/Core/Resources/JsonApiResource.php", "line": 262, "trace": [ { "file": "/var/www/html/vendor/laravel-json-api/core/src/Core/Responses/Internal/RelatedResourceResponse.php", "line": 108, "function": "relationship", "class": "LaravelJsonApi\Core\Resources\JsonApiResource", "type": "->" }, { "file": "/var/www/html/vendor/laravel-json-api/core/src/Core/Responses/Internal/RelatedResourceResponse.php", "line": 97, "function": "metaForRelationship", "class": "LaravelJsonApi\Core\Responses\Internal\RelatedResourceResponse", "type": "->" }, { "file": "/var/www/html/vendor/laravel-json-api/core/src/Core/Responses/Internal/RelatedResourceResponse.php", "line": 81, "function": "allMeta", "class": "LaravelJsonApi\Core\Responses\Internal\RelatedResourceResponse", "type": "->" }, { "file": "/var/www/html/vendor/laravel-json-api/core/src/Core/Responses/RelatedResponse.php", "line": 110, "function": "toResponse", "class": "LaravelJsonApi\Core\Responses\Internal\RelatedResourceResponse", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", "line": 776, "function": "toResponse", "class": "LaravelJsonApi\Core\Responses\RelatedResponse", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", "line": 763, "function": "toResponse", "class": "Illuminate\Routing\Router", "type": "::" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", "line": 695, "function": "prepareResponse", "class": "Illuminate\Routing\Router", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 128, "function": "Illuminate\Routing\{closure}", "class": "Illuminate\Routing\Router", "type": "->" }, { "file": "/var/www/html/vendor/laravel-json-api/laravel/src/Http/Middleware/BootJsonApi.php", "line": 103, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "LaravelJsonApi\Laravel\Http\Middleware\BootJsonApi", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php", "line": 50, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Routing\Middleware\SubstituteBindings", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php", "line": 44, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Auth\Middleware\Authenticate", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php", "line": 78, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Foundation\Http\Middleware\VerifyCsrfToken", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php", "line": 49, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\View\Middleware\ShareErrorsFromSession", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php", "line": 121, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php", "line": 64, "function": "handleStatefulRequest", "class": "Illuminate\Session\Middleware\StartSession", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Session\Middleware\StartSession", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php", "line": 37, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php", "line": 67, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Cookie\Middleware\EncryptCookies", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 103, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", "line": 697, "function": "then", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", "line": 672, "function": "runRouteWithinStack", "class": "Illuminate\Routing\Router", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", "line": 636, "function": "runRoute", "class": "Illuminate\Routing\Router", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", "line": 625, "function": "dispatchToRoute", "class": "Illuminate\Routing\Router", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php", "line": 166, "function": "dispatch", "class": "Illuminate\Routing\Router", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 128, "function": "Illuminate\Foundation\Http\{closure}", "class": "Illuminate\Foundation\Http\Kernel", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php", "line": 21, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php", "line": 31, "function": "handle", "class": "Illuminate\Foundation\Http\Middleware\TransformsRequest", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php", "line": 21, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php", "line": 40, "function": "handle", "class": "Illuminate\Foundation\Http\Middleware\TransformsRequest", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Foundation\Http\Middleware\TrimStrings", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php", "line": 27, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Foundation\Http\Middleware\ValidatePostSize", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php", "line": 86, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance", "type": "->" }, { "file": "/var/www/html/vendor/fruitcake/laravel-cors/src/HandleCors.php", "line": 52, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Fruitcake\Cors\HandleCors", "type": "->" }, { "file": "/var/www/html/vendor/fideloper/proxy/src/TrustProxies.php", "line": 57, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 167, "function": "handle", "class": "Fideloper\Proxy\TrustProxies", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", "line": 103, "function": "Illuminate\Pipeline\{closure}", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php", "line": 141, "function": "then", "class": "Illuminate\Pipeline\Pipeline", "type": "->" }, { "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php", "line": 110, "function": "sendRequestThroughRouter", "class": "Illuminate\Foundation\Http\Kernel", "type": "->" }, { "file": "/var/www/html/public/index.php", "line": 52, "function": "handle", "class": "Illuminate\Foundation\Http\Kernel", "type": "->" }, { "file": "/var/www/html/server.php", "line": 21, "function": "require_once" } ] }, "status": "500", "title": "Internal Server Error" } ] }


### Other details

I can repro both in PHPUnit and manually, using either a Web (Laravel Sanctum) or API (Laravel Passport) guard with the folllowing in composer.json:

- "laravel-json-api/laravel": "^1.0"
- "laravel-json-api/non-eloquent": "^1.0"
- "laravel/framework": "^8.40"
- "laravel/passport": "^10.1"
- "laravel/sanctum": "^2.11"

php -v:

PHP 8.0.11 (cli) (built: Sep 23 2021 21:26:42) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.11, Copyright (c) Zend Technologies with Zend OPcache v8.0.11, Copyright (c), by Zend Technologies with Xdebug v3.0.4, Copyright (c) 2002-2021, by Derick Rethans

lindyhopchris commented 3 years ago

Thanks for reporting.

ouestdarq commented 3 years ago

@helmroos any solution?

lindyhopchris commented 3 years ago

There's probably no work around for this - it needs me to have time to implement a fix, or for someone else to submit a PR fixing it.

ouestdarq commented 3 years ago

@lindyhopchris so I noticed that within the relationship method in theJsonApiResource Class, conditional relationships are given as a ConditionalField object and not as Relation Object... Barely fiddling with the code because I don't understand sh*t of what is going on (pardon my french) I managed to pass all the test (relationship endpoints) by re-writing the relationship method to...

/**
* Get a resource relation by name.
*
* @param string $name
* @return JsonApiRelation
*/
public function relationship(string $name): JsonApiRelation
{
   /** @var JsonApiRelation $relation */
   foreach ($this->relationships(null) as $relation) {
      $relation instanceof JsonApiRelation ?: $relation = ($relation)(); // Invoke (I think) ConditionalField class to return value
      if ($relation->fieldName() === $name) {
           return $relation;
      }
   }

    throw new LogicException(sprintf(
        'Unexpected relationship %s on resource %s.',
        $name,
        $this->type()
   ));
}

This works but I do not understand neither why, nor how... I would've thought that instead of calling ($relation)() I could've just called $relation->get() but this throws a serialization error... does this work around seem logical?

lindyhopchris commented 3 years ago

I think it should actually be checking whether $relation is conditional, and if its - resolve it. I think this is probably one I'm going to have to look at.

ouestdarq commented 3 years ago

how would one "resolve it"?

ouestdarq commented 3 years ago

leaving a note that my solution of

$relation instanceof JsonApiRelation ?: $relation = ($relation)();

only works with when and not mergeWhen, for ConditionalFields is not callable, as is ConditionalField...

lindyhopchris commented 2 years ago

Will be in the 1.1 release.