I'm evaluating the use of this library for a rewrite of our API.During my tests I wanted to create a custom controller and used this:
$api->resource('model', ['controller' => true]);
What about detecting controllers automatically based on the by-resource setting?
true âž¡ App\JsonApi\Model\Controllerfalse âž¡ App\JsonApi\Controllers\ModelControllerWhat do you think about this? Is it hard to realize?
I made a quick implementation of it: https://github.com/jannis-a/laravel-json-api/commit/1a6643bdfcb8737449e94405c02140d033ca540d
Hi! Thanks for the suggestion! The main reason I haven't put this in is because the Laravel convention is for controllers to be in the Http namespace, not the JSON API namespace. Personally I prefer to stick to the Laravel convention if at all possible because it is more predictable for people who are used to developing in Laravel.
A secondary reason is that when registering routes, Laravel already knows the namespace that it is expecting the controller to be in (as that's how the route group namespace option works). So there's no reason for this package to attempt to figure it out.
I'm happy to leave this issue open for a while... if there's a number of people who think that they would want their controllers in the JSON API namespace then potentially it could be added in. My only requirement though on adding it in would be that keeping controllers in the Http namespace would have to continue to work as the default implementation to keep in line with the Laravel convention.
That's a valid point I didn't thought of. Personally, I like having everything related to a resource in the same namespace.
Hey @lindyhopchris ,
first of all: WOW, i am very (!) impressed by this awesome library.. That is some solid work you did there :+1:
I have a similar question as described by @jannis-a , however, my application is structured in a "modular" way (as i personally dont like the Laravel-approach "everything is within one folder" :laughing: ). My application structure is as follows (simplified User -> Posts -> Comment example)
app/Modules
/Authentication
/Comments
/Posts
/Users
Each Module, in turn, is structured as follows
app/Modules/User
/Contracts
/Data
/Migrations --> the migration files for this module
/Factories --> the factory classes for this module
/Models --> the user model and other models that may be important for this module
/UI
/Api --> everything related to the api
/Controllers
/Requests
/Routes
/Transformers
/Web
/...
/Tests
/Traits
Basically, i would like to put everything, that is in your App\JsonApi\X namespace into my App\Module\X\UI\Api\ namespace. For example, the App\JsonApi\Users\Adapter, App\JsonApi\Users\Schema and App\JsonApi\Users\Validator may be generated into app/Modules/User/UI/Api/....
Is this possible with this framework? As @jannis-a says, i am currently evaluating this package to be used in our lectures here at university to be used in some projects with my students! Would be awesome to teach them how easily it is to develop standardized APIs with such great packages!
Thanks a lot for your response!
@johannesschobel thanks for the positive feedback, much appreciated!
Yes this would be possible. The namespace resolution all occurs behind this interface:
https://github.com/cloudcreativity/laravel-json-api/blob/develop/src/Contracts/Resolver/ResolverInterface.php
So all you would need to do is write your own resolver that does the logic that you want. An easy way to do this would be just to extend the one that this package has implemented, or look at that to see what we've done:
https://github.com/cloudcreativity/laravel-json-api/blob/develop/src/Resolver/NamespaceResolver.php
The only thing I would need to add is then something in the JSON API config that allows you to set the resolver container binding to use. You can't do that at the moment but it is on the 1.0 milestone:
https://github.com/cloudcreativity/laravel-json-api/issues/123
Think that would meet your requirements - what do you think?
@lindyhopchris A custom namespace resolver sounds great!
I think that would also implement a feature we need. Right now I'm writing base classes which implement common behaviour for our future API. Those are implemented in a namespace like "Common" and I want to use/implement them in a namespace like "ClientProject". In ordner to have the classes in the namespsace "ClientProject" available I do quite a few calls to $this->app->bind() inside the AppServiceProvider.
Am I correct that this could be obsolete with a custom namespace resolver?
@johannesschobel and others... have put support for custom resolvers into the develop branch so it will be in 1.0.0-beta.3 when I release that. All you do is set the following new config option to the container binding name for your implementation:
https://github.com/cloudcreativity/laravel-json-api/blob/develop/stubs/api.php#L26-L34
@jannis-a bit difficult to know without understanding your implementation. Either the resolver will do it, or you might want to use a ResourceProvider. That's not documented yet but there's an example of it in the tests. It's designed so that packages can provide resources into your application's API:
https://github.com/cloudcreativity/laravel-json-api/blob/develop/tests/package/src/ResourceProvider.php
Not totally sure from your description which of those two approaches will do the job!
Hey @lindyhopchris ,
first of all - WOW, what a great support! Really fast, very pleasant to see you maintaining this project that well and actually caring about potential devs! :+1:
May i make a humble request in your latest approach? I think it would be better to directly assign the "default resolver" in the config file, like this:
return [
// lots of config stuff and docs here
'resolver' => CloudCreativity\LaravelJsonApi\Resolver\NamespaceResolver::class,
// again lots of other stuff
]
This would comply with the style you apply, for example, in the config.resources block as well! What do you think?
Which method(s) from the original NamespaceResolver needs to be overwritten in order to provide customized namespaces like i described above (in my folder structure)?
All the best and great work!
Awesome @lindyhopchris! The ResourceProvider looks like what I need.
I totally have to agree to @johannesschobel, keep up the really good work! :smile:
I'm not totally in favour of specifying the NamespaceResolver in the resolver setting, because it isn't actually created via the container.
The other thing I've realised is that the namespace, by-resource and resources options are not actually used if you use a custom resolver.... because they are effectively configuration options for our NamespaceResolver.
Think I need to add some documentation about this.
but you could use these options, if you do something like
class MyCustomNamespaceResolver extends NamespaceResolver
and then just change the respective methods you need to adapt in order to create different namespaces on the Generators..
Let me play around with options on a branch. The main thing to sort out is how to pass your custom resolver the config, because I'd have to construct it via the container as I wouldn't know what your constructor arguments are (you could be doing DI in your custom resolver's constructor for example).
@johannesschobel does this look like it will work:
https://github.com/cloudcreativity/laravel-json-api/blob/feature/resolver/docs/features/resolvers.md
wow, that is quite a beautiful doc - nice feature, i really like it! Glad you'll add it to your project!
The only thing that feels some kind of weird is that you need a Factory to return the Resolver.. But that may be particular because of the application design - don't really know ;)
Yeah it's because creating a resolver needs access to the config, e.g. the list of resources in the config. That factory pattern is used by Laravel for other things though, e.g. log channels:
https://laravel.com/docs/5.7/logging#creating-channels-via-factories
Actually your comment made me think that the resolver setting could be a resolver or a factory. So I've made that change and updated the docs. Will merge this now.
i like the change ;) i think this may be cleaner as in most cases you want to explicitly only change the resolver.. and this does not require to create a factory that creates / returns the resolver..
awesome work!
This is now released as 1.0.0-beta.3 so closing the issue.
Most helpful comment
@johannesschobel thanks for the positive feedback, much appreciated!
Yes this would be possible. The namespace resolution all occurs behind this interface:
https://github.com/cloudcreativity/laravel-json-api/blob/develop/src/Contracts/Resolver/ResolverInterface.php
So all you would need to do is write your own resolver that does the logic that you want. An easy way to do this would be just to extend the one that this package has implemented, or look at that to see what we've done:
https://github.com/cloudcreativity/laravel-json-api/blob/develop/src/Resolver/NamespaceResolver.php
The only thing I would need to add is then something in the JSON API config that allows you to set the resolver container binding to use. You can't do that at the moment but it is on the 1.0 milestone:
https://github.com/cloudcreativity/laravel-json-api/issues/123
Think that would meet your requirements - what do you think?