CakePHP restful API routing to a set of controllers - php

I'm wondering if it's possible to set a route in Cakephp that will allow me to route to a set of controllers where a prefix is set. What I'm looking to do is duplicate most of my controllers but for a REST api.
I'd like to still have all the default controllers for the site itself but have a product controller for instance that only returns JSON. For this I would like to move all api controllers into a subfolder and route to them by detecting /api/controllername.
Is this possible or even the correct way to accomplish this?

What I'm looking to do is duplicate most of my controllers but for a
REST api.
Bad idea. IMHO. You're going to duplicate code very likely and scatter code everywhere. Keep it in one place. This sentence is an indicator that makes me think you have to much logic in your controllers. Move it to models, fat models.
There are several better ways to do this.
Use a prefix for routing to API methods inside your related controllers (api/v1/foo/bar -> ControllerName::api_actionName())
Implement a single API controller that dispatches model methods (api/v1/foo/bar -> FooModel::barMethod($queryParam1, $queryparam2,...)
Implement a service layer that sits between the model and the controllers and implement a dispatcher filter or the API controller from the 2nd suggestion to dispatch the service methods. You'll use services instead of models then. Controller <-> Service <-> Model. To implement this well some experience with the framework and design patterns is required. If its not well done it will probably cause more problems than benefit - IMHO.
If it's a more or less simple API and the API logic is similar to your actions you can simple re-use the same controller actions you already have and just usethe built in REST and JSON/XML view serialization and could still use routing to create a fancy route (api/v1/...) for them. You can then do conditional checks as well if the controller is called as API.
It's up to you which one you pick, I've seen and used them all in action, they all work the difference is mostly the implementation and level of abstraction you need. However, the key point is to write clean and DRY code and care about SoC.

Related

What is the best practice for using services in Symfony instead of Controllers and not only there?

Well i'm learning Symfony (3.3) and i'm little confused about Service Container. In first tutorial the lector show register, login, add post, edit, delete methods in User, Article Controllers. Then in other tutorial, they show same methods but use Service Container (User and Article services) with User and Article interfaces. So .. what is the best practice for implementation in Services instead of Controllers.
I would like to add to Alexandre's answer that it is considered best practice to keep your controller 'thin'. In other words, only put code in your controller that really has to be there (or if it only makes sense to put it in your controller).
Services are like tools you can use in your application. A service in an object that helps you do something. In one service, you can have many functions. I think the best way to understand the difference is that a controller is for one specific action, a service can be used in many actions. So if you have parts of code that you want to use in more than one controller, create a service for it. And for the sake of re-usability, create functions in your service that do only one thing. This makes it easier along the way to use these functions.
the "best practise" depends on what you want to do with the Service. If you build an REST-Api you might want to do Database-Operations in Controller. Why? When you rely on the SOLID-Pattern you want to reduce or eliminate redundant code. If you code a real REST Api you don't have redundant code because each REST-Verb will do a different query/thing.
So in a non-REST-Api-application you will have a lot of redundant code. You do the same things/services on different pages/controller-actions. So the best thing is to implement all the business-logic in services to have it only one time in one place. If you have a lot of individual queries place them into repositories. If you have business-logic that fit's into an entity-class place them there. So in my opinion you can choose a thick controller/no service design in API's and a thin controller/thick service design in classic symfony front-/backend applications.
But one more thing: there is no totally wrong way to design an application. But if you work with other people or want to run the application longer than a month (without having trouble to maintain it) you should pick a common design-pattern.
Controller must implement the application logic like check if it's a post request or if a form is submit etc...
Never use DQL or any SQL Request directly inside a controller !
EDIT In the example i use a find method inside the controller because it's a Repository method but i parse the result inside slugify (my service method)
Services contains business logic like formatting phone numbers, parse some data etc...
Of course you can inject a repository inside a service and call your methods inside it.
An example:
//This is a fictive example
public function indexAction(Request $request) {
//Application logic
if(!$request->get('id')) {
//redirect somewhere by example
}
$article = $this->getDoctrine()
->getRepository(Article::class)
->find($request->get('id'));
//Business Logic
$slug = $this->get('my.acme.service')->slugify($article->getTitle());
}
Hope this helps

Laravel controllers for complex pages

I have started a new laravel website project and I have hit a road block in my understanding of MVC. I need to refactor to continue but I don't know the best way.
Currently I have web pages that display the results of a single bit of logic. I.e. A page listing all users, a page listing the details of just one user etc etc - all handled by a userController. This applies to other pages being handled by other controllers.
I have created models directly relating to the tables in my database, and controllers in relation on the models. I moved the business logic from the controllers to services. The controllers use the services to perform the business logic and with the data returned, pass that data to the views.
This nicely groups similar functionality together and works fine.
userTable -> userModel -> userController -> userService
clientTable -> clientModel -> clientController -> clientService
...
In my routes, I have pages which do related functionality use the same respective controller, but individual methods depending on what the page does
/listallusers -> userController#list -> userList.blade.php
/listallclients -> clientContoller#list -> clientList.blade.php
/listdetailofoneclient -> clientContoller#details -> clientDetails.blade.php
This is ok when dealing with pages that do that functionality and (apart from using services) seems to be what is hinted at in the laravel docs.
However, I'm starting to get confused about controllers when dealing with pages that either don't really use functionality from any of the services or pages that heavily require functionality from multiple services (and the data needs complex manipulation like formatting or such).
A basic index page.
What controller would handle this? The index might link to routes that are handled by existing controllers but it probably won't need to display much functionality apart from that. That means the controller won't need to pass much complex -if any- data to the view. You could stick the logic to return the view in the route file but that is pretty tightly coupled.
A page that shows complex client and user data
You need to pass client data and user data to the view from the controller. But from what controller? This is the part that is really holding me back.
Because I have a limited number of pages but lots of logic displaying on each page, I was thinking of making a page controller (or something) which would handle the routing. Although I have looked, I have not seen any real mention of this idea anywhere which makes me think I am either reinventing the wheel or have failed to grasp some basic concept in laravel / MVC.
Would the page controller in this case handle all the routing? Would it handle only the pages with 'overlapping' existing controller functionality and the pages that don't fall into the existing controllers? Is a page controller even a good idea?
Some more points that have made me question MVC from this issue
Do controllers need an equivalent model?
Can controllers 'control' other controllers in order to separate logic?
I'll take a shot at a couple of these questions.
Having a PageController or HomeController is very acceptable. Controllers don't have to be linked to a specific model, for instance an AuthController would handle logic for logging in and out but isn't tied to a model, or PasswordController which handles setting/resetting passwords, or a PaymentController that handles billing routes. A controller is just a way to organize logic for related routes in one file. Static basic pages are related routes so a PageController makes sense to me.
Are users tied to a specific client? If so you can arrange your controllers in a nested way so you have a ClientController and a UserController and your routes look something like this:
/clients/{client}/users //list all users for this client
For heavy data formatting it's probably best to use a service provider and use dependency injection to inject it into controllers where you need to use it. This allows you to detach your data manipulation from your controller so you could change it out if needed. Say you are using a software to make charts, and you want to change it out later - you want that formatting logic to be removed from your controller.
I hope I helped in some way... sort of a train of thought here!

Should interactions to an external api be a model or a controller action?

Currently building an API that pulls data from another API.
I'm just a little unsure about how I should represent some data considering the whole skinny/fat model/controller argument and I haven't been able to find a clear answer so I was hoping for a discussion on this here.
As Models represent interactions with data it feels like my calls be mapped into a model using something like Fractal or Jenssengers "Laravel Model".
As currently I have actions in my controller that send send requests, but it feels like this is a bit too much responsibility for a controller.
So I just wanted some opinions on where I should place this logic in regards to a Laravel project!
Thanks
EDIT:
From further research it looks like the repository design pattern may be a possible solution!
Repositories Simplified
Using Repository Pattern In Laravel 5
Neither method is particularly a great solution. Really, a Controller is responsible for handling the HTTP requests and your models are representations of your business domain. So where does third-party data fit into this?
Well, the data itself should probably be represented by a model. However, the method of getting the data from the third party provider should really be delegated to a service provider that you can then easily switch out to work with different apis and thus decoupling yourself from a single provider (easiest example would be payment gateways, having all of your logic hard coded in your Controller for a Paypal integration would make it extremely difficult to then later add a second payment option).
Take the following example; let's say you have an application that provides a user with the latest results for their favourite football teams.
Your application could have the following endpoints:
/team/{team}/players
/team/{team}/fixtures
/team/{team}/results
These could map to the following controller methods:
PlayerController#getPlayersInTeam($team);
FixturesController#getFixturesForTeam($team);
ResultsController#getLatestResultsForTeam($team);
Notice there are three different controllers, rather than one single controller. This way you can assign a controller to the type of model you're expecting to return to the user.
Now obviously, you shouldn't do your API calls within each controller. But, why would you then do it within your model? The term 'Skinny controllers, fat models' is such an anti-pattern that it really does a lot more harm than good.
Why not use a service that is solely responsible for getting data from the API for your models?
interface FootballTeamData
{
public function getPlayersInTeam(Team $team);
public function getTeamFixtures(Team $team);
public function getTeamResults(Team $team);
}
Now, you can implement this contract and easily switch the way that you get your data from third parties without having to touch your models - which is your business domain, and therefore shouldn't be so highly coupled with the third party API.
You're also now benefiting from skinny controllers, and skinny models. There's no reason why a class can't exist that has just a few lines of code, neither should be fat.
Good luck!

CakePHP: Where to put 'Services' logic

I come from a Java/Grails background and cannot seem to find a definite answer online as to where the service logic for a CakePHP application should be stored. By "Services", I am talking about classes that are usually instantiated through dependency injection to conduct business logic on domain objects. They should be able to query any domain object and make changes in response to a controller action.
Currently, CakePHP's "Component" class seems to be the closest match to this behavior. I can load a component into any controller and execute its methods as needed. However, I have read in several places that components should never access the database and that doing so will result in some steep performance hits.
I have also looked into CakePHP's "Behavior" class and it doesn't seem to fit the ticket at all. It seems well-equipped to organize domain objects into a data structure setting, but that's not the kind of logic that a service would execute. Also, to import any model definition into a Behavior, I would have to edit the model definition itself to allow access, which is very awkward.
So I ask this question: Where should service logic be stored? Certainly not the controller, as it should only contain the minimal logic to process a request and send a response.
Components are the service layer in CakePHP. They are constructed by a dependency injection container (Components Collection) and get passed the controller, request and response that is to be handled.
There are no restrictions in what Components can do other than maintaining separation between layers. It is fine to use database connections, or use models, directly from a component and modify the request.
Components are actually very light-weighted if you only make them act for specific cases. Inspecting the action name, is a common way of limiting the reach of a component. You can also inject setting so it can know when is OK to execute custom service logic.
So I ask this question: Where should service logic be stored?
Certainly not the controller, as it should only contain the minimal
logic to process a request and send a response.
Sounds like the ideal use case for a Dispatcher Filter. It gets called even before a controller is instantiated. If you need to query the database simply load a model via ClassRegistry::init('YourModelName') and pass the request params to the model method and return whatever you need in your request. No controller needed at all. We've implemented oauth + xhttp using Dispatcher Filters without calling ever a controller.
How using a model inside a component should effect the performance... I don't know who got that strange idea, sounds like not the best article you found. It is true that you should not put model layer related logic in them but you can call a model for example through the controller instance and the controllers models.

Hot to share common controllers action across other controllers in ZF?

Let us say I have a controller that takes care of login/registration/password recovery and such in my app. I want to share this across different modules and controllers. What's the best way?
Should I make an action helper, Or use inheritance? Of course I don't mean logic of those action, those are implemented by models (different for every module), I just want to share common parameters, interpretation and passing results to views.
I'm targeting to do some kind of a generic library for those things in my project. So I would have some abstract user model from which all other models that want to use login/registration function will inherit, but I'm wondering what about the controller stuff.
Any idea?
Basically I think what you are trying to create are widgets . Here is an great article how to create them using action helper by ZF team lead http://weierophinney.net/matthew/archives/246-Using-Action-Helpers-To-Implement-Re-Usable-Widgets.html .
Creating a re-usable authentication service is what you want to do. Creating it as a service allows you to test it in isolation. Inject the service into a front-controller plug-in so it is run during each request. The actual checking can be encapsulated into a custom validator so you can simply call ->isValid(). If not valid, re-route to the login page.

Categories