Not sure this is specific to Laravel but what is the proper RESTFUL way to handle creating a child of a parent with Laravel. For example I have a Car that can have many Drivers (hasMany) and Drivers belong to one Car (belongsTo). If I want to create a Driver whose parent is Car #1 does the CarController.php have the responsibility to create the driver: /car/1/driver/create or do I use /driver/create/car/1 and keep the responsibility within DriverController.php?
Right now I'm doing /driver/create/1 (where #1 represents the Car) which feels wrong but I'm not clear about what the RESTFUL way should be. TIA.
There really isn't a proper way of implementing nested resources in REST as it doesn't really care. There are arguments for and against nested resources, however, there are some generally accepted implementations and the agreement that whatever you decide on, be consistent.
I utilise nested resources, but only a single level of nesting and no more. So for example:
GET /cars/{carId}/drivers/{driverId}
However, I would avoid the following:
GET /cars/{carId}/drivers/{driverId}/incidents
If you have multiple nested resources, consider obtaining the nested resource through the parent resource:
GET /cars/{carId}/drivers/ // Get all drivers for the car
GET /drivers/{driverId}/incidents // Get all incidents for the driver
Arguably nested resource URLs can convey more meaning than a single resource URL at a glance. e.g.
GET /cars/{carId}/drivers/{driverId} // more meaningful
GET /drivers/{driverId} // less meaningful
With the second URL above, I do not know which car the requested driver is associated with until the resource is returned. That being said /drivers/{driverId} can still be applicable and useful to have depending on your use case.
A use case for a /drivers endpoint would be if you can create new drivers that are not yet associated with a car.
In response to your question of how to create a driver, I would consider the following use cases;
Create a driver without an association to a car
POST /drivers
Create a driver with an association to a car
POST /cars/{carId}/drivers
POST /drivers
For the POST /drivers endpoint you would use a DriverController and pass your Driver information to the store method. The validation rules in the store method would allow for an optional car_id parameter as part of the request. This would allow you to either associate a driver with a car at creation, or not.
For the POST /cars/{carId}/drivers endpoint, you would use a CarDriverController (or a DriverController in a Cars subfolder if often seen) and pass your Driver information to the store method. A car_id paramter would not be required in the request as the associated car would be obtained from the {carId} passed in the URL.
For updating your driver resources, you can follow the same principle just amending your HTTP verbs and creating the appropriate routes.
PUT /drivers/{driverId}
DriverController#update
PUT /cars/{carId}/drivers/{driverId}
CarDriverController#update
If you decided to implement both methods for creating drivers and you find duplicate code, consider refactoring it to a service.
Update 1
For #2 POST /cars/{carId}/drivers is the store endpoint does that make GET /cars/{carId}/drivers/create the create endpoint? And similarly for POST /drivers creation endpoint GET /drivers/cars/{carId}?
If you're working with blade views and following the Laravel conventions then your form to create a new driver for a given car would be found at GET /cars/{carId}/drivers/create or GET /drivers/create.
And it sounds like relationships should always get a separate controller.
Ideally yes as most applications are nothing more than CRUD and so everything can be mapped to one of the 7 controller actions. This keeps things clean and simple and responsibilities separate.
Take a look at this video by Adam Wathan which explains how to map what you think are custom actions to one of the 7 basic Laravel actions. Bit lengthy at 40 minutes but well worth a watch.
POST /cars/1/driver.
no interest in specifying the action (create). the method (post) already does it.
Related
Suppose we have a M:M relationship between a User model and a Project model in a project management SaaS. Naturally we have a pivot table mapping users to projects. An entry is deleted either if the user leaves or if the project manager removes that user from the project.
Even though the final result is essentially the same (i.e., the entry is deleted), I imagine it would be better to distinguish between these two actions by defining two separate API endpoints as follows:
user leaves project
route DELETE /users/{id}/projects/{id}
action UserProjectController#destroy($id) where $id refers to the project
project manager removes user
route DELETE /projects/{id}/participants/{id}
action ProjectParticipantController#destroy($id) where $id refers to the user
Should I ignore Cruddy by Design and RESTful design principles and simply define leave() join() remove() actions instead and use verbs in the URIs? like so:
POST /projects/{id}/join
POST /projects/{id}/leave
POST /projects/{id}/participants/{id}/remove
join,leave,remove are arguably RPC rather than REST. Pivot tables etc are how the domain is implemented and are irrelevant to the caller of the API, which works at the domain level. How do the URLs map to your domain model?
If Project has one or more User why not just use
/projects/{id}/
to manage everything about Project and Participant instances?
User is in a Project but only if
/projects/{id}/participants/{id}
has been called.
FWIW,
DELETE /users/{id}/projects/{id}
looks like it's deleting the Project instance owned by a User as the Project object has participants but the User doesn't use that terminology. Perhaps it would be:
DELETE /users/{id}/projects/{id}/participants
for consistency with the domain model.
However it seems much easier to just use Project to manage Project instances. Removing a User from a Project using the User API seems a convenience that complicates the backend and doesn't really match the Project terminology. That would mean only having UserController and ProjectController classes.
You would have to consider whether a Participant id is the same as a User id and whether the pivot table handles that but that won't affect the API. The API should be an intuitive representation of your domain model.
Something to consider: how would you do it on the web?
Even though the final result is essentially the same (i.e., the entry is deleted), I imagine it would be better to distinguish between these two actions by defining two separate API endpoints
So on the web, you might well have two different forms that are used to "achieve the same result", but that doesn't necessarily mean that the forms should target different resources.
POST /foo
Content-Type: application/x-www-form-urlencoded
action=UnsubscribeUser&otherArguments=....
POST /foo
Content-Type: application/x-www-form-urlencoded
action=CancelProject&otherArguments=....
"One resource or two resources" isn't a question of right or wrong, but rather a question of trade-offs.
POST /projects/{id}/join
POST /projects/{id}/leave
POST /projects/{id}/participants/{id}/remove
That's also "fine"; again, it's a question of trade offs. The machines don't care that your identifiers have a verb in the URI.
They do, somewhat, care whether or not the identifier for reading is the same as the identifier for writing. See RFC 7234.
But it's perfectly reasonable to say that having semantically significant URI spellings in the access log or browser history are more important to our long term success than cache-invalidation.
Keep firmly in mind that DELETE - in the context of HTTP - does not mean the same thing as DELETE in the context of SQL; we're talking about two different name spaces with their own semantics.
HTTP DELETE is of the transfer of documents over a network domain. The fact that the implementation of your handler includes a SQL DELETE is completely irrelevant.
Relatively few resources allow the DELETE method -- its primary use is for remote authoring environments, where the user has some direction regarding its effect.
It is OK to use POST.
I'm working on a REST api for a model having the following entities:
A Team cannot exists if it has no relationships with a Course and a Student. At the beginning, I created an endpoint for the teams (API/teams) for the CRUD operations. Now I ended up moving all the CRUD operations for the teams under the following URLs:
/API/courses/{courseId}/teams
The same has been done for Machine that cannot exists without any relationships with a Team and Student, so any CRUD operation should be done to the following:
/API/courses/{courseId}/teams/{teamId}/virtual-machines
This makes sense to me, since every time I need to perform an operation on a Machine I have to verify the constraint for which the Machine is owned by a Team related to a Course. For this reason, If I continued to perform any operation on URLs like /API/teams I should have requested the course and team ids to verify those contraints in the request body.
Having said this, my CourseController invokes a VirtualMachineService for all the operations on the Machine entity. What it seems odd to me is that each signature of every method in the VirtualMachineService need to have the course and the team id to verify the above constraints. This caused to have lots of duplicated code in every method.
Are my design choices correct?
The CourseController only have to invoke the methods of VirtualMachineService and to validate the parameters coming from the requests body.
Should those constraints validation be done inside the controller or inside the service?
Neither Configuration nor Model are entities. Entities are classes from the domain (real world representations related to project, if you will), not every class you use.
REST doesn't directly care about your entity model (meaning graph) but you should follow the guidelines for specifying REST endpoints which is
different endpoint for
/courses/... and /teams/... - don't mix these. Any constraints you would like to apply are applied at the backend and have nothing to do with endpoint definitions.
Validation guide https://www.baeldung.com/spring-mvc-custom-validator
Dumb question but I have some lingering confusion of what, exactly, a "resource" is in Rails. The term is used everywhere but I get a funny feeling it might be being used rather loosely. It's referenced in the model, the controller and, quite literally, in routes.rb.
Is it the specific route? For example, map.resources maps the 7 RESTful "resources". So an example of one resource would be the call to, say, the index action of a particular class's controller?!?
Is it a reference to the whole page/object being retrieved? or perhaps, more narrowly, a database table? or the row being retreived?
Is it something else?
Anyway, hopefully someone can set me straight...
Any object that you want users to be able to access via URI and perform CRUD (or some subset thereof) operations on can be thought of as a resource. In the Rails sense, it is generally a database table which is represented by a model, and acted on through a controller.
For example, you might have a User resource (with a users table in your DB). This is represented by a User model, is mapped to users_controller with map.resources :users (which then generates routes like /users (a collection of User resources) and /users/1 (a specific User resource).
You act upon those resources by using the appropriate HTTP method when making calls to those resources. POST to the resource collection (/users) creates a new record; GET retrieves a list of resources (/users) or a specific user (/users/1). PUT updates a specific user (/users/1/), and DELETE destroys that user. The URLs are the same, but the result (and controller action) may be different based on the HTTP verb. The idea, though is that /users/1 always means "I'm interacting with the User that has ID #1", regardless of the action.
Here's a good article discussing how most developers think that "Resource" is synonomous with the database table, the argument, I guess, being that mapping to the resource is mapping the controller to that database table (or, with ActiveResource, to another REST url).
Basically, I think a "resource" is "persisted data." map.resources maps the 7 RESTful actions to a particular suite of persisted data.
But I haven't thought about it too much in depth. Good question!
I think they probably mean it in the general web sense, i.e., Resource (Web):
the referent of any Uniform Resource Identifier
I don't think it has anything to do with database tables.
open your model folder, that is a hint of what resources you have!
example: users, pictures, comments...
A lot of people here say that resources refer to the database tables you have. It might be true sometimes but not necessarily true always. I could give you a lot of examples where you don't have a corresponding table in your database for a particular resource. Hence asssociating it with tables is rather wrong.
I would define a resource as a route which maps to related requests. So instead of declaring separate routes for the actions you want to do you can simply declare them using a resourceful route.In Rails, a resourceful route provides a mapping between HTTP requests and URLs to controller actions.
So say you define resources :users in config/routes.rb. You can now use a number of helpers to the controllers in your application like edit_user_path which returns users/edit .
Here's a good link: https://api.rubyonrails.org/v5.2.1/classes/ActionDispatch/Routing/Mapper/Resources.html
Which basically says: Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index, show, new, edit, create, update and destroy actions, a resourceful route declares them in a single line of code:
resources :photos
Lets say we have a class "Car" than has different pieces of data ( maker, model, color, fabrication date, registration date, etc). The class has no method to get data, but it knows to as for it from another object (sent via constructor, let's cal it for short DS).- and the same for when needing to update changes.
A method getColor() would be implemented like this
if(! this->loaded('color')){
this->askDS('color') // this will do the necesarry work to generate a request to DS
}
return this->information('color');
Nothing too fancy so far. No comes the part i want to find out if it has a name, or if there are libraries / frameworks that do this already.
DS has a list of methods registered dinamically based on the class that needs data. For car we have:
input: car serial number, output: method to use to read the numbers to extract raw values
input: car raw color value, output: color code
input: car color code, manufacturer, year, mode, output:human-readable color (for example navy blue)
Now, DS or any method does not have an ordered list of using command to start from serial number and return the color blue, but if can construct a chain of methods that from one set of data, it can run them in order and get the desired data.
For our example above, DS runs 1,2,3 in that order and injects the data resulted from all methods into the class object that needed it.
Now if the car needs registration info, we have method (4) that gets that from the police database with an api request.
So, given:
- a type of model (class/object)
- a list of methods that take a fixed list of input(object properties) and give out a fixed list of output (object properties)
- a class DS that can glue the methods and run the needed ones for a model to get from property A (serial) to properby B (human readable colour) without the model or DS having a preconfigured way to get this data but finding it as needed.
does this have a name or is it already implemented somewhere ?
I've implemented a very basic prototype and it works very nice and i think this implementation method has useful features:
if you have a set of methods that do sql queries and then your app switches to using an api, you only need to change the methods and don't have to touch any other part of the application
when looking for a chain of methods that resolve the 'need' the object has, you can find a method chain, run it, if it fails keep looking for another list of methods based on the currently available data - so if you have multiple sources for a piece of data, it can try multiple versions
starting from the above paragraph i could start with an app that only has sql queries for data retrieval - when i find out a part of the app overloads the sql server i could add a method to retrieve data from cache with a lower cost than the one from database (or multiple layered caches, each with different costs)
i could probably add business logi in the mix the same ways as cache, and based on the user location / options present different data
this requires less coding overall, and decouples the data source from the object, making each piece easier to mock/test
what is needed to make this fast is a caching solution for the discovered method chains, since matching hundreds of thousands of methods per model type would be time-consuming but I don't think this is very hard to do - just store all found chains in memory as you find them and some metadata to be able to resume a search from any point in time - when you update the methods, just clear the cache, take a performance hit for the first requests
Thank you for your time
What you describe sounds like a somewhat roundabout way of doing Dependency Injection. Quote:
"Passing the service to the client, rather than allowing a client to
build or find the service, is the fundamental requirement of the
pattern."
Depending on what language you're using, there should be several Dependency Injection frameworks/libraries available.
I have this idea of generating an array of user-links that will depend on user-roles.
The user can be a student or an admin.
What I have in mind is use a foreach loop to generate a list of links that is only available for certain users.
My problem is, I created a helper class called Navigation, but I am so certain that I MUST NOT hard-code the links in there, instead I want that helper class to just read an object sent from somewhere, and then will return the desired navigation array to a page.
Follow up questions, where do you think should i keep the links that will only be available for students, for admins. Should i just keep them in a text-file?
or if it is possible to create a controller that passes an array of links, for example
a method in nav_controller class -> studentLinks(){} that will send an array of links to the helper class, the the helper class will then send it to the view..
Sorry if I'm quite crazy at explaining. Do you have any related resources?
From your description it seems that you are building some education-related system. It would make sense to create implementation in such way, that you can later expand the project. Seems reasonable to expect addition of "lectors" as a role later.
Then again .. I am not sure how extensive your knowledge about MVC design pattern is.
That said, in this situation I would consider two ways to solve this:
View requests current user's status from model layer and, based on the response, requests additional data. Then view uses either admin or user templates and creates the response.
You can either hardcode the specific navigation items in the templates, from which you build the response, or the lit of available navigation items can be a part of the additional information that you requested from model layer.
The downside for this method is, that every time you need, when you need to add another group, you will have to rewrite some (if not all) view classes.
Wrap the structures from model layer in a containment object (the basis of implementation available in this post), which would let you restrict, what data is returned.
When using this approach, the views aways request all the available information from model layer, but some of it will return null, in which case the template would not be applied. To implement this, the list of available navigation items would have to be provided by model layer.
P.S. As you might have noticed from this description, view is not a template and model is not a class.
It really depends on what you're already using and the scale of your project. If you're using a db - stick it there. If you're using xml/json/yaml/whatever - store it in a file with corresponding format. If you have neither - hardcode it. What I mean - avoid using multiple technologies to store data. Also, if the links won't be updated frequently and the users won't be able to customize them I'd hardcode them. There's no point in creating something very complex for the sake of dynamics if the app will be mostly static.
Note that this question doesn't quite fit in stackoverflow. programmers.stackexchange.com would probably be a better fit