Yii2 Url Rewrite with Array parameter - php

I am trying to rewrite the following url,
http://mywebsite.com/web/myContlr?myContlrSearch[id]=900
Using Yii2 Url manager i am trying to change the url to be as below,
http://mywebsite.com/web/myContlr/900
How can this above format possible using urlmanger rules in Yii2. And also I am having multiple parameters like myContlrSearch[name], myContlrSearch[location],.. etc
Please guide me to build the URL restful.

If You want to make your API RESTful then You should start from resource naming. Resources should be a nouns in plural form.
For example if you have some class like a "car" then corresponding resource url should looks like <your-domain>/cars. In this case GET /cars will be a method to get a collection of cars, and GET /cars/900 -- a method to get specific car with ID=900.
Next, if your parameters are needed for filtering resource collection then you should add them as query parameters to collection resource url, like this: /cars?vendor=ferrari&count=10. If your parameters are needed to specify instance properties (when you create or update some object), then you should include them into a request body.
For instance creation you should use url of resource collection: POST /cars. And for updating an instance -- PUT /cars/<id>.
Lets look on your particular case. You have some resource named myContlr (i hope this is just example name), so myContlr should be an noun which express a object name. Your myContlrSearch in query parameters looks like some search criteria object, so it can be passed as array or as json in query parameters (it's better do not use request body for GET requests). Using array/json/any-other-structure here will not affect your routing -- this should be within the scope of responsibility of the controller.
But if you want to create new object or update existing one, then you should use POST /myContrlr or PUT /myContrlr/900 and then pass your object in request body (of type application/json or application/xml).
Then your routing config can looks as follows:
$config['components']['urlManager'] = [
...
'rules' => [
'GET myContlr/<id:\d+>' => 'myContlr/view',
'PUT myContlr/<id:\d+>' => 'myContlr/update',
'DELETE myContlr/<id:\d+>' => 'myContlr/delete',
'GET myContlr' => 'myContlr/index',
To learn more about building RESTful API in Yii2: http://www.yiiframework.com/doc-2.0/guide-rest-quick-start.html
For further reading: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

Related

What is the best way for various meaning slug in Laravel Routing?

for perfect SEO, I need the following url structure.
http://127.0.0.1:8000/california-side-hustles
http://127.0.0.1:8000/california-san-francisco-side-hustles
http://127.0.0.1:8000/california-san-francisco-94804-side-hustles
http://127.0.0.1:8000/vacation-home-rentals-side-hustles
for above urls, I can make the Laravel Route like this.
Route::get('{id}side-hustles', function ($id) {
});
but I have a problem on this. I am in finding the best way for working, because the above 4 urls have to get the each other results.
http://127.0.0.1:8000/california-side-hustles
california => state param
by using this param, I need to retrieve the results from the database.
http://127.0.0.1:8000/california-san-francisco-side-hustles
california => state param
san-francisco => city param
by using these 2 params, I need to retrieve the results from the database.
http://127.0.0.1:8000/california-san-francisco-94804-side-hustles
california => state param
san-francisco => city param
94804 => zip code param
by using these 3 params, I need to retrieve the results from the database.
http://127.0.0.1:8000/vacation-home-rentals-side-hustles
vacation-home-rentals => object param title
by using this param, I need to retrieve the object from the database
totally, above 4 url rules will have the same format like this {slug}-side-hustles. their process will not be same.
for this, what is the best way on laravel routing?
I would suggest you to simplify.
Using your URLs as example:
http://127.0.0.1:8000/california-side-hustles
http://127.0.0.1:8000/california-san-francisco-side-hustles
http://127.0.0.1:8000/california-san-francisco-94804-side-hustles
You could use the following
http://127.0.0.1:8000/{state}/{article}
http://127.0.0.1:8000/{state}/{city}/{article}
http://127.0.0.1:8000/{state}/{city}/{zipcode}/{article}
And in the controller(s), you can create dedicated methods for each route.

Filter form for URI string parameters

For a filtered list web page, I want pass filters in the URI string. I.e.:
index.php/user/search/name/joe/location/UK/gender/male
According to CodeIgniter documentation it will be easy to retrieve the information using the URI Class. http://www.codeigniter.com/user_guide/libraries/uri.html?highlight=uri%20class
My doubt:
In the view, How should I set up the filter form so that it calls a uri string based url (index.php/user/search/name/joe/location/UK/gender/male) instead of a regular POST (or GET) request?
Instead of doing it like that you can structure your query like this,
index.php/user/search?name=joe&location=UK&gender=male
This way you can access the url parameters using $data = $this->input->get() and then access individual items like $data['name'], $data['location'] and $data['gender'].
And it would be also easier to set up the form with get method.

ZF2 - Get current URL in Controller

This seems like it should be a simple task. I need the current URL from a function within the Controller. This function can be called from multiple actions, and the end goal is to set a form's action attribute. (Side note: It appears IE does not send an ajax request if the URL starts with '#').
I feel like my google-fu is off today because I could not find a good way to do this Zend Framework 2. I have this line currently, but it feels very bulky:
$this->url()->fromRoute(
$this->getServiceLocator()
->get('Application')
->getMvcEvent()
->getRouteMatch()
->getMatchedRouteName()
);
Couldn't you just get the URI from the request object:
$this->getRequest()->getUriString()
Provided your controller extends Zend\Mvc\Controller\AbstractActionController.
Note: This would output the entire URL, like so:
http://example.com/en/path/subpath/finalpath?test=example
If your request route is like this:
http://example.com/en/path/subpath/finalpath?test=example
And You want only this:
/en/path/subpath/finalpath?test=example
You can simply do : $this->getRequest()->getRequestUri()
To specify my Request object is an instance of
\ZF\ContentNegotiation\Request

Which pattern and how to structure this [Different serviceHandlers, structure and validation]?

Alright so I'm trying to make some sense of all these patterns.
Alright, so I'm coding an applicantion in CodeIgniter which needs to be able to send data about a car and a customer to different types of companies using SOAP, maybe XML, comma-separated and so on.
But they all need the same thing.
I wanna make it as dynamic as possible and make sure it's easy to write tests.
So the service should take a couple of things:
a handler
applicants [1-2]
params
object
I started up creating different classes
Gr8Exp
NordCar
SwePerf
each implementing the interface iServiceRequest
interface iServiceRequest{
/**
* Send the request to the company server.
*/
function sendRequest();
/**
* Saves the response into the database.
*/
function saveResponse();
/**
* Prepares the request to the company, setting info from form and shit.
*/
function prepareRequest();
/**
* Soap, XML, CSV, JSON
* #param type $method
*/
function setRequestHandler(iServiceRequestHandler $handler);
}
Then they need to structure up the Soap, XML, CSV, JSON request depending on what handler i put in.
After those who needed to be validated (not all did) I used:
interface iAdaptServiceRequest{
/**
* Structure the array information and put it into an object structure in the right place.
*/
function structure(array $info);
/**
* Make all the checks for the function
*/
function validateInfo();
}
But I'm stuck, It worked really good when I just used SOAP request; but now. Since I need to format them differently, use a different handler for each type of request or company I don't know what to do.
I could put them i different folders and recreate the class in the different folders. But that's not a good practice since I'm duplicating code all over.
In the end I want to run some chaining like this:
$result = $m->prepareRequest()->sendRequest()->saveResponse();
Any suggestions??
IMHO:
-- create/use a front controller.
-- The front controller determines which request handler to use (JSON, SOAP, XML, etc).
-- The request handler generates a common "Request" object that behaves the same across all interfaces, basically putting variables into a common named format inside a "Request object"
-- It determines which service to send the request to and sends the request object there
-- The service processes the request object and generates a response object
-- The controller creates an appropriate (JSON/SOAP/XML) View object to process the response object into the correct view type and the View outputs your response as that type.
I would use something like yours: $result = $m->prepareRequest('JSON')->sendRequest()->saveResponse();, but specifing what format of data I'm sending.
The method prepareRequest(string $type) would check the format and call another method to convert your data to the respective format.
Something like this:
function prepareRequest(string $type){
if ($type == 'json'){
$this->convert2json();
}
if ($type == 'xml'){
$this->convert2xml();
}
// And so on
}
There is often confusion about the MVC or Observer pattern. This is not a situation in which this pattern is applicable. In the MVC pattern are the View and Model related to one another. The View must update itself based on information of the subject. A view and the underlying tables in a database are a good example. That is not what you want here.
The design pattern which suits this problem is the Builder pattern. The Builder pattern consists of four cooperating classtypes:
1. a Builder,
2. a ReaderManager,
3. a ConverterManager, and
4. a DataObject.
The ReaderManager is using the Interpreter pattern. Conversion can be done using the State pattern. What is the output of the ReaderManager (some DataObject) is the input for the ConversionManager. That can be done using an abstract class instead of an interface (my preference for data focused classes). The Builder connects the ReaderManager with the ConverterManager and takes care of the transport of data.
Some years ago I wrote about design patterns. The builder pattern was one of the patterns I described and this is the link to that page:
http://www.loekbergman.nl/InsideArchitecture/TheProcess/DesignPatterns/Builder
It shows a UML diagram of the pattern.
In the next link you can download a jar with some examples of design patterns. One of them the builder pattern:
http://www.loekbergman.nl/InsideArchitecture/DownloadsAndLicense
I have written this code several years ago, therefor do I give you this code without warranty. (Is that the correct term in this context?)
In the code you can see a folder with the name specifications. That is another example of the Interpreter pattern. (In the Builder pattern there is of course also an example of this pattern).
To be complete is here the link to the MVC - pattern:
http://www.loekbergman.nl/InsideArchitecture/TheProcess/DesignPatterns/Observer
and the Interpreter pattern:
http://www.loekbergman.nl/InsideArchitecture/TheProcess/DesignPatterns/Interpreter

get object data in mvc structure

I'm working with a PHP MVC Framework. Works really well. I like the separation of the business layer (model) with the business logic (controller). But i just stumbled upon a problem. Here's the thing:
Suppose i navigate to the following url:
http://localhost/user/showall/
In this case the userController.php is called and within that file there is a method showallAction() which gets executed.
In the showallAction() method i simply do a request to a model which gets all the users for me. Something like this:
public function showallAction()
{
// create userModel object
$users = new userModel();
// get all users and assign the data to a variable which can be accessed in the view
$this->view->users = $users->getAllUsers();
// render views
$this->view->render();
}
So this method gets all the users, assigns the data returned from the userModel to a variable and i can easily work with the returned data in my view. Just a typical MVC thing.
Now here comes the problem.
I also need to create a native iphone variant. Ofcourse the looks will be totally different. So all i actually want to do is to request this url:
http://localhost/user/showall/
And that it just gives me the array (in json format) back. So i can use that for the mobile development.
But this obviously can't be done right now because the showallAction() method assumes that it is for web browser display. It doesn't echo JSON formatted, instead it simply assings the array of users to a variable.
So that means i have to create another method "showallMobileAction()" in order to get the data, but specifically for the mobile device. But this is not an elegant solution. I'm sure that are better ways...
Anyone any idea how can i solve this problem??
In your situation i would modify the routing mechanism.
It would be useful, if you could add extension at the end of URL, which represents the format you expect, like :
http://foo.bar/news/latest >> HTML document
http://foo.bar/news/latest.html >> HTML document
http://foo.bar/news/latest.rss >> you RSS feed
http://foo.bar/news/latest.json >> data in JSON format
It's a simple pattern to recognize. And you can later expand this to add .. dunno .. pdf output, or Atom feeds.
Additionally , two comments :
Model is not a type of objects. Instead it is a layer, containing objects responsible for business logic, and objects responsible for data storage/retrieval.
View should be a full blown object, to which you bind the domain objects (objects responsible for business logic).
You could pass parameters to your url:
/user/showall/json
and get the third URL segment with a custom function or a built-in one. For instance, with CodeIgniter: $this->uri->segment(3).
Some frameworks will pass the additional parameters to your method. Just try this with the URL I wrote above:
public function showallAction()
{
print_r(func_get_args());
}
I'm not familiar with PHP MVC but in general terms I'd use the "accepts" HTML header field to request the response in either "text/html" or "text/json", the controller would check for the accepts type and return the response accordingly.

Categories