laravel 4 pattern filter using a wildcard - api

I started using Laravel 3 last week, and then found the new 4 release and I'm trying to convert now.
I have a dozen+ routes that I want to deliver to a specific controller method. i.e., "/api/v1/owners/3/dogs/1 or /api/v1/owners/3" to run "myresourcecontroller#processRequest"
In Laravel 3 I was able to use this: (note * wildcard)
Route::any('api/v1/owners*', 'owners#processRequest'); // Process tags resource endpoints
I found this example from the documentation but it gives me an error. I get a NotFoundHttpException.
//[Pattern Based Filters](http://laravel.com/docs/routing#route-filters)
Route::filter('admin', function()
{
//
});
Route::when('admin/*', 'admin');
Not sure what I'm doing wrong? Is there another way to do this?
I don't want to use the Laravel 4 restful controllers, cause they don't seem to conform to complete restful design. i.e., no verbs in the url.
I have all of my processing written, I just need to be able to route to it.
I need to be able to create new records by POST /api/v1/owners or /api/v1/owners/3/dogs
I cannot use /api/v1/owners/create.
I'm trying to avoid having to write a route for every endpoint, i.e.,
Route::any('api/v1/owners/{owner_id}', 'owners#processRequest');
Route::any('api/v1/owners/{owner_id}/dogs/{dog_id}', 'owners#processRequest');
Thank you for any help

You should make use of resourceful controllers as they're a great asset when building an API. The endpoints you described can be achieved using resource controllers and nested resource controllers.
Route::resource('owners', 'OwnersController');
Route::resource('owners.dogs', 'OwnersDogsController');
Would allow you to create an owner with POST localhost/owners and create a dog on an owner with POST localhost/owners/3/dogs.
You can then wrap these routes in a route group to get the api/v1 prefix.
Route::group(['prefix' => 'api/v1'], function()
{
Route::resource('owners', 'OwnersController');
Route::resource('owners.dogs', 'OwnersDogsController');
});

Haven't used Laravel myself, but try any('api/v1/owners/*', (note slash before asterisk) as in the example.

Related

How to create an static api route after a dynamic route in Next.js?

I have an api that dynamically pulls a post. localhost/api/post/[postId]
I want to extend functionality to retrieve the comments of the post at the URL localhost/api/post/[postId]/comments
What is the correct way to structure this in Next.js? I am thinking to create a dynamic route and check if the query equals comment? localhost/api/post/[postId]/[comment]
The following file structure should work:
/pages/api/post/[postId]/index.js //Route: /api/post/1
/pages/api/post/[postId]/comments.js //Route: /api/post/1/comments
Besides that, just to follow good practices, I would recommend that you rename "post" to "posts", like that:
/pages/api/posts/[postId]/comments.js

Laravel Route apiResource (difference between apiResource and resource in route)

I'm using apiResource in Route which is using (index, create, show, update, destroy) methods in exampleController. When I would like to use show method the route wont work. what shall I do? I think it is because of {fruits} but I do not how solve it?
Route::apiResource('/fruit/{fruits}/apples', 'exampleController');
My route in browser is:
localhost:8000/api/fruits/testFruitSlug/apples/testAppleSlug
difference between apiResource and resource in route: Route::apiResource() only creates routes for index, store, show, update and destroy while Route::resource() also adds a create and edit route which don't make sense in an API context.
Already peoples added answers, I am just adding the route differences as visually :
Normal Resource controller
Route::resource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
Api Resource controller
Route::apiResource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
POST /users store users.store
GET /users/{user} show users.show
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
To quickly generate an API resource controller that does not include the create or edit methods, use the --api switch when executing the make:controller command:
php artisan make:controller API/PhotoController --api
Try using the command line to generate your controller. It will save you stress. You can then do this in your route
Route::apiResource('photos', 'PhotoController');
I solved my question in below way:
public function show(Fruits $fruits, Apples $apples){
}
I found that I should give all variables in my function however I did not use all of them.

ASP.NET Web API 2 - define controller-to-method mappings?

Microsoft has a good tutorial for getting your first ASP.NET Web API project going:
http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
...but what's unclear to me -- how is the mapping between the API URIs and my C# controller methods defined?
for ex:
/api/products/{id}
resolves to
public IHttpActionResult GetProduct(int id)
{
[...]
}
...but im not sure how. automagic?
I ask because I want to create a new mapping for this URI:
/api/setReportNotificationsAsRead?uid={username}&items={itemIDs}
to this new method in my controller:
public IHttpActionResult SetReportNotificationsAsRead(string username, string itemIDs)
{
[...]
}
...but im not sure how. automagic?
The Automagic lies with HTTP Verbs in Web API. The route /api/products/{id} can map to anything that starts with GET (or just method name Get) if you make a GET request for the WebAPI.
If you make a POST request then it will map to any POST method (or else is you use route prefix).
This link can help you understand the magic. That can also help you understanding how you can configure SetReportNotificationsAsRead function to be called.
You're very close to having a working solution. You have your method parameter names mixed up:
public IHttpActionResult SetReportNotificationsAsRead(string uid, string items)
{
//Do your stuff!
}
The name of the HTTP GET parameter should match the name of the method parameter. This is part of the ASP.NET MVC naming convention.
One final note, if you are actually expecting a group of items (i.e. multiple item ids) you can actually save yourself some work and use a string[] parameter so long as your HTTP parameters are sent correctly. In this case you would want the URI to look like: /api/setReportNotificationsAsRead?items=123&items=456&items=789. Notice how the parameter name is repeated multiple times, but with different values.
For more information about the routing system I would suggest heading over to the ASP.NET MVC routing overview.

How can I access query string parameters for requests I've manually dispatched in Laravel 4?

I'm writing a simple API, and building a simple web application on top of this API.
Because I want to "consume my own API" directly, I first Googled and found this answer on StackOverflow which answers my initial question perfectly: Consuming my own Laravel API
Now, this works great, I'm able to access my API by doing something like:
$request = Request::create('/api/cars/'.$id, 'GET');
$instance = json_decode(Route::dispatch($request)->getContent());
This is great! But, my API also allows you to add an optional fields parameter to the GET query string to specify specific attributes that should be returned, such as this:
http://cars.com/api/cars/1?fields=id,color
Now the way I actually handle this in the API is something along the lines of this:
public function show(Car $car)
{
if(Input::has('fields'))
{
//Here I do some logic and basically return only fields requested
....
...
}
I would assume that I could do something similar as I did with the query string parameter-less approach before, something like this:
$request = Request::create('/api/cars/' . $id . '?fields=id,color', 'GET');
$instance = json_decode(Route::dispatch($request)->getContent());
BUT, it doesn't seem so. Long story short, after stepping through the code it seems that the Request object is correctly created (and it correctly pulls out the fields parameter and assigns id,color to it), and the Route seems to be dispatched OK, but within my API controller itself I do not know how to access the field parameter. Using Input::get('fields') (which is what I use for "normal" requests) returns nothing, and I'm fairly certain that's because the static Input is referencing or scoping to the initial request the came in, NOT the new request I dispatched "manually" from within the app itself.
So, my question is really how should I be doing this? Am I doing something wrong? Ideally I'd like to avoid doing anything ugly or special in my API controller, I'd like to be able to use Input::get for the internally dispatched requests and not have to make a second check , etc.
You are correct in that using Input is actually referencing the current request and not your newly created request. Your input will be available on the request instance itself that you instantiate with Request::create().
If you were using (as you should be) Illuminate\Http\Request to instantiate your request then you can use $request->input('key') or $request->query('key') to get parameters from the query string.
Now, the problem here is that you might not have your Illuminate\Http\Request instance available to you in the route. A solution here (so that you can continue using the Input facade) is to physically replace the input on the current request, then switch it back.
// Store the original input of the request and then replace the input with your request instances input.
$originalInput = Request::input();
Request::replace($request->input());
// Dispatch your request instance with the router.
$response = Route::dispatch($request);
// Replace the input again with the original request input.
Request::replace($originalInput);
This should work (in theory) and you should still be able to use your original request input before and after your internal API request is made.
I was also just facing this issue and thanks to Jason's great answers I was able to make it work.
Just wanted to add that I found out that the Route also needs to be replaced. Otherwise Route::currentRouteName() will return the dispatched route later in the script.
More details to this can be found on my blog post.
I also did some tests for the stacking issue and called internal API methods repeatedly from within each other with this approach. It worked out just fine! All requests and routes have been set correctly.
If you want to invoke an internal API and pass parameters via an array (instead of query string), you can do like this:
$request = Request::create("/api/cars", "GET", array(
"id" => $id,
"fields" => array("id","color")
));
$originalInput = Request::input();//backup original input
Request::replace($request->input());
$car = json_decode(Route::dispatch($request)->getContent());//invoke API
Request::replace($originalInput);//restore orginal input
Ref: Laravel : calling your own API

How to enable dojox.data.JsonRestStore access struts2's action to retrieve data? I mean how to configure 'target' or others

I tend to use dojox.data.JsonRestStore as my grid's store, but I am always failed to access struts2 action, I am unfamiliar in REST, is it only can be used in servlet rather than struts2, etc.
Currently, My project is using struts2 + spring as backend skill and dojo as front-side skill, have you any ways for me to make dojox.data.JsonRestStore access a structs2 action class?
Thanks in advance.
to get the data, all you need is an HTTP GET that returns an array of JSON objects. The return value from the action must be a string with something like:
[
{
"penUser":"Micha Roon",
"submitTime":"12.03 13:20",
"state":"Eingang",
"FormNumber":"001001"
},
{
"penUser":"Micha Roon",
"submitTime":"12.03 13:20",
"state":"Eingang",
"FormNumber":"001001"
}
]
If you want to be able to update objects you have to have a method that reacts to PUT with the same URL as the one you used for GET and if you need to delete, DELETE will be used. The important part is that it must be the same URL.
In order to have JsonRestStore pass the ID in a GET parameter instead of appending it to the URL, you could specify the URL like so:
target:"services/jsonrest/formstore?formId="
When you call yourStore.get("123") the request will try to get http://yourserver:port/AppContext/services/jsonrest/formstore?formId=123
REST is nothing more than a convention.
You can use a RESTFull API like jersey.java.net in order to make your life easier and your URL more RESTFull.