Zend_Form and RESTful HTTP request - php

I have implemented a search form in Zend ( SOLR in the backend ).
To offer the user some more control I have added a multicheckbox for applying certain content filters.
The thing is in the following steps ( bear with me here ):
The request is made, something similar to /search/?q=bla&filter=1
The request is rewritten in the controller to be restful to: /search/query/bla/filter/1
If the user removes filter 1, adds filter 2 and submits the request becomes: /search/query/bla/filter/1?q=bla&filter=2
How would I properly create a restful request using that. The problem being here that using the getRequest() functionality of the Controller I will also get a value for the first filter, meaning I have no way of knowing which one I can discard.
So, to summarize:
How do I properly use a Zend_Form to create RESTful HTTP requests

IMO, you're trying to solve an inexistent problem. You're working on aesthetics not RESTful compliance.
REST tells that you need to identify resources, not that you're resource links should look nice (well in a way). But since your search is a kind of a filter, it is totally acceptable to use a QueryParam.
I think, your use of the term "search" within REST is wrong. Search is not a resource (at least in your case).
You should either hide the search implementation by doing something like:
GET /articles?q=foo&filter=1
The way you construct your filters criteria should not matter.
Or you may want to define a "search" as a resource (SO actually does that IIRC).
POST /articles/search/
"{
"query" : "foo",
"filter" : "bar"
}"
Would result in something like:
Location: /articles/search/a125f41fbc135d
Where a125f41fbc135d is the identifier of the search which would be used to identify the search resource.

Related

Defining Laravel routes when certain query strings are present

Say I want to be able to submit a search form on any page that will append a ?s= to the current url but return a SERP: https://example.com/my-page?s=foobar. (I've seen a few sites do this instead of pointing to /search?s=.* - not the way I'd do it, but it illustrates my question.)
In my Laravel web.php routes, is there currently a way to register this other than maybe using a wonky regex?
<?php
Route::get('.+?\?.+?\bs={search}', 'SearchController#search');
// This regex is probably wrong, but you get what I was going for,
// and that kinda highlights why this is not an ideal way to do it
?>
This gets uglier when, say, you want to capture multiple $_GET params:
https://example.com/my-page?s=foobar&dept=clothing
I haven't found anything in Laravel docs that let you define query string options on the Route $uri parameter. The recommended option is to just use pretty URLs (https://example.com/search/foobar), but there are definitely valid use cases for keeping query strings.
1: Create a middleware (https://laravel.com/docs/5.7/middleware)
2: Validate incoming request using $request->query('s')
3: If validation successfull return to next else redirect to wherever or display an error response
That is very simple that depends on the parts of a url. The Route class uses the "path string" of the url and you try to use the "parameters" of the url.
https://doepud.co.uk/blog/anatomy-of-a-url
In modern websites you should work with that structure because you get a better URL structure and it's much better for SEO and search engines.
You should use the parameters only in the function you call for small things which you can call over the $request->get('s'); method but then you have to redirect or you have to work in that function.
So don't fight the framework and work in that structure what is defined from the framework that all people who know the framework know how to work with it.

Passing an array of values into Rest API Route

I am using Slim framework to create an REST API for my project. The WebApp itself is developed using ReactJS.
I have a doubt regarding the same. I have a set of values stored in an array in my ReactJS App. These values are filters which is used ti filter data from my table.
My table contains a field called location. In my WebApp I have search filter were I can add multiple locations based on which the results have to be displayed. I store these filters in an array.
I want to know how can I pass this array to Rest API Route so that I can get this array in my REST API Framework.
I want to achieve something like
/routes/location/[arrayOfValues]
There are only two ways of passing data to the server - either as URL params (for POST, GET, or anything else) or in the request body (for PUT or POST). Are you also writing the code to handle the API request? From your description of the use case, it sounds like GET would be the most semantically correct verb, so you you should use URL params as #BrianPutt suggested. Using square brackets is the standard way to encode an array value. How are the locations defined? Longitude/latitude? If so, you could also just build a comma-separated string, e.g.
/routes/location?q=12.3409,-40.0004,2.34004,120.0294
But odds are your back end framework has built-in support for parsing those URL params, so you should just use that.
/routes/location?q[]=12.3409,-40.0004&q[]=2.34004,120.0294
The only reason not to do this is if you have a huge number of locations, in which case you might want to use a POST request and build some kind of JSON object to put in the body.
Also: be consistent! If the rest of your API uses JSON, you should probably use it here too.

PHP MVC - URL without action

I'm currently creating my own custom MVC framework in PHP that uses the MVC URL standard:
example.com/{controller}/{action}/{id}
This works fine, however, one of my controllers called "books" does not need the action in the URL:
example.com/{controller}/{id}
The index method of the books controller displays a list of books:
example.com/books
I want the controller to display a specific book if an ID follows:
example.com/books/47
At the moment, I have to use this URL to view a specific book which isn't as nice:
example.com/books/view/47
What would be the best way to go about doing this?
If you want to provide the ability to create custom URLs, then you will have to look into creating a routing mechanism. Usually in PHP it is done by employing simplified URL patterns, that are transformed into regular expression.
Then, when user's request gets handled at bootstrap stage, the routing mechanism applies all of the regular expressions on by one. When the match is found, the appropriate route is selected.
The the resulting state of request instance is combination of the data that was extracted with regular expressions, supplemented by default values that are associated with each of those patterns.

why we need put and delete in REST(full) web service?

can i call a web service like this
and not use put and delete method?
is this a REST web service really?
....
$url = 'webservice.php';
$data = array(
'username' => 'a',
'password' => 'a',
'param1'=> 'param1',
'operation'=> 'delete',
'output'=>'xml'
);
$client = curl_init($url);
curl_setopt($client, CURLOPT_POST,1);
....
...................
//webservice.php
$operation=$_POST['operation'];
$param1=$_POST['param1'];
if ($operation=='delete')
{
$r=mysql("delete from list where id='$param1'");
}
if ($operation=='insert')
{
$r=mysql("insert into list values ('$param1')");
}
.....
One of the major ideas behind REST is to not give operational methods as part of the argument (in this case the 'operation' parameter).
Instead, each resource has its unique URL and the HTTP verbs (GET, POST, PUT or DELETE) are used on those resources.
Your approach is not RESTful.
Example:
Deleting a comment using the flickr API:
GET /services/rest/?method=flickr.photos.comments.deleteComment&comment_id=28
Note how they use a 'method' parameter to determine what operation to perform (like in your example).
The RESTful implementation would accept something like:
DELETE /comment/28
Best practise in this case would be to use POST for creating new resources, DELETE for removing them, GET for retrieving existing and PUT to update existing.
This kind of technique is sometimes called "tunneling" because it buries the true operation in the body of a generic POST operation. In my opinion it's kind of a hack and defeats the purpose of REST but sometimes it's necessary if your web host doesnt allow the required HTTP verbs.
Using standard verbs and understanding the implications they make about your service is an important aspect of REST that should not be overlooked. For example, you should be able to issue a DELETE operation repeatedly on the same resource and that should result in only the first DELETE having any effect (idempotent). With GET it should be assumed that no changes are being made on the server (safe). But hiding the operation inside of a POST obscures that.
This isn't really a RESTful service. You don't need to implement all HTTP verbs to be RESTful, but you shouldn't use POST to DELETE data.
Personally I'd implement DELETE for removing items and only use POST for inserting data.
I'm going to go against the tide here and say it is perfectly fine to create RESTful services without PUT and DELETE. The only key thing that you need to be aware of is what you are giving up in doing so.
1) Intermediary components(e.g. proxies, caches, load balancers) will not know whether you are creating/updating or deleting resources, they will only know if the operation is safe (GET) or unsafe (POST). My question is, do you know of any intermediary components that take advantage of this knowledge?
2) The programmer who is going to be accessing your service will not be able to guess how to DELETE a resource, you are going to have to include a link with a link relation that has some documentation that explains to the programmer that they will need to POST to the link's URI to do a delete. It's a bit more work for the client developer but at least you are being explicit about how to do it.
And before I get downvoted into oblivion, here is a quote from Roy Fielding who says it is ok too!
In any case, there are plenty of
RESTful services that do nothing but
GET and POST. The key is how those
methods are used, not what methods are
used. To give a specific example, what
makes a wiki more or less RESTful is
almost always determined by how it
(ab)uses GET and sessions -- whether
it uses PUT or POST for editing pages
is sugar topping in comparison.
http://code.google.com/p/implementing-rest/wiki/FAQ
Having said all of this, creating a single resource called webservice.php and passing a "operation" parameter is a nasty design smell from the perspective of REST.

Does php mvc framework agavi use CRUD compliant to REST?

The agavi framework uses the PUT request for create and POST for updating information. Usually in REST this is used the other way around (often referring to POST adding information while PUT replacing the whole data record).
If I understand it correctly, the important issue is that PUT must be idempotent, while POST does not have this requirement. Therefore, I wounder how creating a new record can be idempotent (i.e. multiple request do not lead to multiple creations of a record) in particular when usually the ORM uses an id as a primary key and the id of a new record would not be known to the client (since it is autocreated in the database), hence cannot be part of the request. How does agavi maintain the requirement of idempotence in light of this for the PUT request.
Thanks.
PUT can be used both for creation and for updating complete records. POST is usually used for partial updates and related operations as well as for creating a new type of record on the server without specifying a URL for the resource (e.g. POST to /articles/23/comments returns a 201 status and a Location: /articles/23/comments/283136 header). So in your case (with a sequence/autoincrement ID), you would use that approach.
However, HTML (and thus web forms) is different. It only knows GET and POST, not DELETE and PUT. For deletion and updating operations, it overloads the POST method.
That's why Agavi, by default, maps POST to "write" and GET to "read" - it's the most common use case, and "read" and "write" were chosen because they are relatively neutral and also in a way represent the safety aspects of GET vs POST (safety as in "GET can be called without side effects" and blah).
You can change the mapping of verbs for the AgaviWebRequest implementation in factories.xml; refer to the Agavi users mailing list or the IRC channel if you need help with that (or ask away here). A lot of people on the IRC channel are also quite experienced with URL scheme design in case you need more help with making your API pretty.
Instead of thinking of PUT as creating, think of it as "putting". You put a resource at a URI (ie send an entire resource to a URI).
PUT http://example.com/articles/1
If you repeat this (send the same entire resource to the same URI) you get the same result and you haven't changed the resource at that URI, that's what makes it idempotent.
If agavi's implementation of PUT is idempotent then it is implementing PUT correctly. Otherwise it's not.
PUT can be used to create a resource, except that if the resource already exists (or has already been created by a previous PUT) it will just update it. POST should not update resources, however, if this is simple CRUD. Note that the HTTP verbs do not have a defined mapping to certain actions necessarily, since they're useful for a lot more than just CRUD.
Also note that this question has nothing to do with REST - just proper HTTP usage. So please remove the REST tag.
I've had this problem before. This can be solved by changing the factories.xml

Categories