Closed luceos closed 5 years ago
Thanks!
configured it inside the json-api-v1.php.
Can you provide your configuration?
<?php
return [
/*
|--------------------------------------------------------------------------
| Resolver
|--------------------------------------------------------------------------
|
| The API's resolver is the class that works out the fully qualified
| class name of adapters, schemas, authorizers and validators for your
| resource types. We recommend using our default implementation but you
| can override it here if desired.
*/
'resolver' => \App\JsonApi\Resolver::class,
/*
|--------------------------------------------------------------------------
| Root Namespace
|--------------------------------------------------------------------------
|
| The root namespace for JSON API classes for this API. If `null`, the
| namespace will default to `JsonApi` within your application's root
| namespace (obtained via Laravel's `Application::getNamespace()`
| method).
|
| The `by-resource` setting determines how your units are organised within
| your root namespace.
|
| - true:
| - e.g. App\JsonApi\Posts\{Adapter, Schema, Validators}
| - e.g. App\JsonApi\Comments\{Adapter, Schema, Validators}
| - false:
| - e.g. App\JsonApi\Adapters\PostAdapter, CommentAdapter}
| - e.g. App\JsonApi\Schemas\{PostSchema, CommentSchema}
| - e.g. App\JsonApi\Validators\{PostValidator, CommentValidator}
|
*/
'namespace' => '',
'by-resource' => false,
/*
|--------------------------------------------------------------------------
| Resources
|--------------------------------------------------------------------------
|
| Here you map the list of JSON API resources in your API to the actual
| record (model/entity) classes they relate to.
|
| For example, if you had a `posts` JSON API resource, that related to
| an Eloquent model `App\Post`, your mapping would be:
|
| `'posts' => App\Post::class`
*/
'resources' => [
],
/*
|--------------------------------------------------------------------------
| Eloquent
|--------------------------------------------------------------------------
|
| Whether your JSON API resources predominantly relate to Eloquent models.
| This is used by the package's generators.
|
| You can override the setting here when running a generator. If the
| setting here is `true` running a generator with `--no-eloquent` will
| override it; if the setting is `false`, then `--eloquent` is the override.
|
*/
'use-eloquent' => true,
/*
|--------------------------------------------------------------------------
| URL
|--------------------------------------------------------------------------
|
| The API's url, made up of a host, URL namespace and route name prefix.
|
| If a JSON API is handling an inbound request, the host will always be
| detected from the inbound HTTP request. In other circumstances
| (e.g. broadcasting), the host will be taken from the setting here.
| If it is `null`, the `app.url` config setting is used as the default.
| If you set `host` to `false`, the host will never be appended to URLs
| for inbound requests.
|
| The name setting is the prefix for route names within this API.
|
*/
'url' => [
'host' => null,
'namespace' => '/api/v1',
'name' => 'api:v1:',
],
/*
|--------------------------------------------------------------------------
| Controllers
|--------------------------------------------------------------------------
|
| The default JSON API controller wraps write operations in transactions.
| You can customise the connection for the transaction here. Or if you
| want to turn transactions off, set `transactions` to `false`.
|
*/
'controllers' => [
'transactions' => true,
'connection' => null,
],
/*
|--------------------------------------------------------------------------
| Jobs
|--------------------------------------------------------------------------
|
| Defines settings for the asynchronous processing feature. We recommend
| referring to the documentation on asynchronous processing if you are
| using this feature.
|
| Note that if you use a different model class, it must implement the
| asynchronous process interface.
|
*/
'jobs' => [
'resource' => 'queue-jobs',
'model' => \CloudCreativity\LaravelJsonApi\Queue\ClientJob::class,
],
/*
|--------------------------------------------------------------------------
| Supported JSON API Extensions
|--------------------------------------------------------------------------
|
| Refer to the JSON API spec for information on supported extensions.
|
*/
'supported-ext' => null,
/*
|--------------------------------------------------------------------------
| Encoding Media Types
|--------------------------------------------------------------------------
|
| This defines the JSON API encoding used for particular media
| types supported by your API. This array can contain either
| media types as values, or can be keyed by a media type with the value
| being the options that are passed to the `json_encode` method.
|
| These values are also used for Content Negotiation. If a client requests
| via the HTTP Accept header a media type that is not listed here,
| a 406 Not Acceptable response will be sent.
|
| If you want to support media types that do not return responses with JSON
| API encoded data, you can do this at runtime. Refer to the
| Content Negotiation chapter in the docs for details.
|
*/
'encoding' => [
'application/vnd.api+json',
],
/*
|--------------------------------------------------------------------------
| Decoding Media Types
|--------------------------------------------------------------------------
|
| This defines the media types that your API can receive from clients.
| This array is keyed by expected media types, with the value being the
| service binding that decodes the media type.
|
| These values are also used for Content Negotiation. If a client sends
| a content type not listed here, it will receive a
| 415 Unsupported Media Type response.
|
| Decoders can also be calculated at runtime, and/or you can add support
| for media types for specific resources or requests. Refer to the
| Content Negotiation chapter in the docs for details.
|
*/
'decoding' => [
'application/vnd.api+json',
],
/*
|--------------------------------------------------------------------------
| Providers
|--------------------------------------------------------------------------
|
| Providers allow vendor packages to include resources in your API. E.g.
| a Shopping Cart vendor package might define the `orders` and `payments`
| JSON API resources.
|
| A package author will define a provider class in their package that you
| can add here. E.g. for our shopping cart example, the provider could be
| `Vendor\ShoppingCart\JsonApi\ResourceProvider`.
|
*/
'providers' => [
Component\Extension\Api\ResourceProvider::class,
Component\User\Api\ResourceProvider::class,
],
];
The resource providers have a getResolver()
method on them - you might need to overload that and return your own instance.
The resolver that's used from the resolver
key of your config is the resolver for the things in your config... so won't have any affect on the resource providers. The resource providers basically do their own thing - so that they are operationally independent (they're like packages).
So I think if you overload the getResolver()
method on your providers to use your custom resolver you should be ok, but let me know?
https://github.com/cloudcreativity/laravel-json-api/blob/develop/src/Api/AbstractProvider.php#L62-L68
So.. that was a great pointer, but did not completely fix it. In addition to that I also had to ensure that the Resolver::isResourceType would return true for the supported resources (in my case all of them).
Thanks for your help!
One more question, if you allow me.
The resolving now works, but when it tries to instantiate an adapter it will use the construct argument from the AbstractAdapter, which is an Eloquent Model and cannot be instantiated:
[2019-10-23 12:41:49] local.ERROR: Target [Illuminate\Database\Eloquent\Model] is not instantiable while building [Component\Extension\Api\Adapters\ExtensionAdapter]. {"exception":"[object] (Illuminate\\Contracts\\Container\\BindingResolutionException(code: 0): Target [Illuminate\\Database\\Eloquent\\Model] is not instantiable while building [Component\\Extension\\Api\\Adapters\\ExtensionAdapter]. at vendor/laravel/framework/src/Illuminate/Container/Container.php:979)
[stacktrace]
#0 vendor/laravel/framework/src/Illuminate/Container/Container.php(813): Illuminate\\Container\\Container->notInstantiable('Illuminate\\\\Data...')
I was considering doing a conditional ioc binding ($this->app->when(ExtensionAdapter)->needs()->give()
), but shouldn't there be a better way?
Edit: I've actually overridden the construct and set the correct model as argument, is that the recommended way?
The recommended way is to type-hint the actual model the adapter relates to in the constructor, then pass that into the parent constructor, eg in the generated Eloquent adapter: https://github.com/cloudcreativity/laravel-json-api/blob/develop/stubs/eloquent/adapter.stub#L32-L35
If your child adapter doesn't relate to an Eloquent model, then you shouldn't be extending the Eloquent adapter.
Hope that helps!
Okay thanks you, I am now generating an index with valid json api spec. Thanks a bunch!
First off, 🙇 what a great package ❤️ !
A lot of hard work has gone into this, exceptionally well done!
I am refactoring a pretty large app by using Domains (DDD), so my Laravel app has a component directory containing some items like
User
andExtension
. To structure the API related code inside of that I gave each of them aApi
subdirectory with aResourceProvider
registered inside thejson-api-v1.php
configuration. In order to support this structure I created aApp\JsonApi\Resolver
class, implemented theresolve
method and configured it inside the json-api-v1.php.Now when trying to hit the resource route for
extensions
I receive an exception:Thrown by
vendor/cloudcreativity/laravel-json-api/src/Store/Store.php:341
.I was assuming that my Resolver would be used everywhere, but dd'ing inside of it doesn't make a difference. When I dd inside the
CloudCreativity\LaravelJsonApi\Factories\Factory::createResolver
method I actually see my Resolver is being used, but no resources have been registered.providers
from the configuration used to generate resources?