Defining Laravel routes when certain query strings are present - php

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.

Related

Laravel/Vue - Pass URL to Component

I'd like to pass a route('name', $id) to a vue component. In this case, this would be quite easy, since its only one URL with the parameter.
But what do I have to do if I'd like to pass in an array of URLs? How to tell PHP/Laravel to make an array, where the URL is present without the $id part.
For example:
<custom-name
data="{!! $urlData!!}"
id="{!! $id !!}">
</custom-name>
And $urlData consists of ['url1'=> 'test/{id}/abc', 'url2'=> 'test/{id}/xyz'].
The Plan is that I can build a vue component where I loop through the URLs and build a table with links to those URLs in it. I need the possibility to mutate these URLs before they are put into the table. But I need it to be done in the component.
So the question is: if it is possible in laravel to get the (i would call it) raw URL data like it is present in Route::getRoutes() but only for routes, I need no all. To be more precise, the problem is that the route() function need the corresponding $id Value in order to return an URL. But i need the URI like test/{id}/xyz. So i can generate the URLs in the component. I try to do it the Laravel-Way-Of-Life and I really like not to hard code it.
Hopefully, someone could lend me some help. :)
As far as i understand you, you have a bunch of routes and you need their URLs, right? If that is the case you can access it with some helpers methods built in laravel, and i can see that you want it with query strings etc.
You can use access them via the request with the fullUrl() helper, or just the path() helper if you dont need the query string.
Further reading on this is here:
https://laravel.com/docs/5.6/requests

Creating the Post-Redirect-Get pattern with Laravel

I have been used laravel, and I find it's by far the best PHP Framework there is. But even so, I still think that to be able to understand it and PHP MVC's in general, I need to make my own first.
So, as of now, I'm in the process of making my own MVC, I got most things covered. But I wanted to add a feature that is identical to Laravel, which is the Post-Redirect-Get feature, (or so I think).
What I mean is, for those unaware, that if a person visits a link, say localhost/project/laravel/public/profile using the Route::get('localhost/project/laravel/public/profile', 'SomeController#action) He will only be able to view the profile page, from the action() function in SomeController. But when he uses the Route::post('localhost/project/laravel/public/profile', 'SomeController#action2), only when does is the POST request sent from the localhost/project/laravel/public/profile URL, will the action2() function activate.
So, My question is,
How can I make my own Route::get() and Route::post() to work like in laravel
If you want have get and post in the same route you should try this methods
POST and GET in the same pattern

Handling sharp in the url

I am trying to pass a name variable via this routing pattern.
<controller:product>/<name:[^\/]+> => 'product/view'
My aim is to get the $name in my actionView of the product controller, it works most of the times, but what I've discovered is it fails to pass the name if it contains a sharp (#) , for example sending a request
/product/test%20#something
Will fail, as far as I understood it is trying to find actionTest instead.
It might be a solution to set the default action of the controller to go to the view, but I want a better solution for this. I am sure there is a yii way to solve this.
Also another solution is to urlencode($productName), but it makes the URL look more ugly.

Use cases for generated URLs in Symfony2?

Coming from a straight PHP and Drupal background, I am recently learning the Symfony2 framework. Currently I am in the routing chapter of the book. This is probably a simple question.
What are some real world use cases for why one would want to generate URLs in a Symfony app? I understand the code but I'm having a bit of trouble determining its practical applications.
I'm referring to this section should you need a refresher.
As always, thank you!
P.S. Symfony is amazing. :)
Basically, you need to generate a URL whenever you need to link to anywhere in your application.
Let's say that you have an application that needs to manage some users. This means that you will probably have URLs like /user/create, /user/edit/(user id) and /user/remove/(user id).
Whenever you display a link to edit a user you need to know on what URL you can find the page that allows you to edit a user. So you need to link to /user/edit/(user id). One solution would be to have this as a fixed link so that in your code you could just write
edit this user
But what if you want to change this URL scheme? Let's say someone is unhappy with the term "user", after all the humans managed by this system are not only users, they are actually "person"s! So now you need to change all the URLs containing "user". Probably there are quite a few places in your app where you have had to hardcode these URLs and now you will need to find and change all of them. Eugh.
But fear not, for Symfony routing comes to the rescue!
Instead of hardcoding these URLs, we can simply let the Symfony router generate them for us. This means that we first need to tell Symfony which routes we have, e.g. by adding the following YAML code to our routes config file:
user_edit:
path: /user/edit/{userId}
defaults: { _controller: AppBundle:User:edit }
requirements:
userId: \d+
This tells our application "Okay, whenever somebody requests a page that looks like /user/edit/{userId}, then you need to call the editAction method in our UserController class in the AppBundle namespace and you need to pass the userId as a parameter. Oh, and also you should only call the controller if userId is a valid integer with at least one number."
So this is how Symfony knows how to map URLs to controllers. But the goodness that comes along with it is that we can use this information for the reverse way as well.
Usually, in our application we do not really care about what the URL looks like for a certain action we want to perform. All we know is that when clicking a certain link, then the browser should jump to a page that allows me to edit a user. And since we just defined a route that takes us right there, we can have Symfony generate the correct URL to achieve just that.
So in your view you can now discard the hardcoded URL from earlier and instead replace it with a route generated by the Symfony router:
edit this user
Now whenever you need to change what the URL actually looks like all you need to do is edit your routing config and not a lot of separate views.
Because, imagine you want to change a given page URL and you've hardcoded it in 10 Twig templates. You will have to modify all these files. On the opposite, when using the routing component:
You would only have to change the URL where the route is defined.
The routing component "takes" care of the current environment you are using (dev, prod...)
Also note that is a bad practice to "switch environment", a typical issue is to hardcode an URL in a Javascript. In this case you can expose your Symfony2 routes in the Javascript by using a bundle like FOSJsRoutingBundle.
I almost immediately realized their use and now I feel silly. :) For those who stop by this question in the future:
Notes about Generating URLs:
Similar to the Drupal l() function, sometimes you need to generate links inside your application based on a variety of parameters.
You don't always want to hardcode your links in case you decide to change paths sometime down the line.
In summary: Think of this as an alternative to using straight anchor tags with href elements all over the app and, instead, keeping things dynamic.
Use case
In the project I'm working I use generateUrl to redirect the user
after creating, editing an entity.
For example after creating a Service entity, I redirect the user to the view
of the just created Service.
Controller
return $this->redirect($this->generateUrl('myentity_view', array('id'=> $id)));
Additional note
In twig files, you can use the path function which call the routing component and generate url with given route name and parameters.

Laravel Route Params and Form Params

I have a Backend in Laravel, which is basically a REST API, because I'm using AngularJS in the FronEnd and making ajax requests.
Let's say I have to make a simply CRUD for Users
And I don't know if there is any difference between putting some of the parameters in the Route itself or all of them in the Form Input.
For Example:
Route::post('/Users/Update', 'UsersController#update);
And then call the 'id' parameter from:
Input::get('id')
or
Route::post('/Users/Update/:id', 'UsersController#update);
and include it as a parameter of the function update like:
public function update($id) { }
Is there any real difference between this two ways? maybe security issues? coding standards? or is it the same?
Should I just use Laravel's REST controllers?
If you are building a REST API you should have a URL like example.com/posts/42 and not example.com/posts?id=42 because it is cleaner and it is a coding standard.
I would also drop uppercase characters in your URLs and definitely go for your second choice of implementation. By the way, if you need to update a user you should use a PUT request like so: PUT users/:id.
The concise some-what opinionated answer:
You should define your route as:
Route::put('/users/:userId', 'UsersController#putUser');
Your public function putUser($userId) {} should return a 204 No Content on success.
The reasoning:
I've changed the route to be a PUT request to closer follow REST principles. Changing the controller method to putUser from update allows us to better define what the method is intending to do. While it seems trivial, it will help you distinguish between a PUT and PATCH update if you ever decide to implement one in the future. I used PUT as the method here but you can read about PATCH vs PUT and decide how far you want to go into following REST principles.
As for laravels restful controllers I feel they impose restrictions and add no real benefit so for REST api's I don't recommend using them.

Categories