Dynamic url issue in Laravel - php

Hi I have project structured in 2 parts: frontend urls and backend urls. The backend urls are like base-url/admin/pagename the frontend urls are like base-url/pagename.
I want to create some dynamic pages. The url name are came from the database.
this is my route from the web.php file:
Route::any('{slug}', 'PageController#show');
This is my controller
public function show($slug = null)
{
if('admin' != $slug){
$page = Pages::where('route', $slug)->where('active', 1);
$page = $page->firstOrFail();
return view($page->template)->with('page', $page);
}
}
Somehow I want to avoid to take into consideration every url starting with baseurl/admin/. I am wondering if I can do it from the web.php. If yes , how ?

Define all your static routes first for precedence issues. Then define your any route at the end, with some regular expressions
Route::any('{slug}', 'PageController#show')->where('slug', '^[a-zA-Z0-9-]*$');
This is telling the url to only allow alphanumeric and dashes -. So any url with a forward slash wont work.
/my-first-page-1 --> should work
/my/first/page/2 --> shouldn't work
this way you know baseurl/admin/ will never work. You can search online for more regular expressions.

try this:
Route::any('/base-url/admin/{slug}', 'SomeController#someMethod');
Route::any('{slug}', 'PageController#show');
laravel routes are matched from top to bottom and it will stop when it finds the first match, so routes defined first take precedence over those defined later, in this case, the first route will match any request for url starting with /base-url/admin/ and the second route will match everything else.
you just need to replace 'SomeController#someMethod' with the controller in charge of that functionality

Related

Is there a way to partially match a route in laravel?

I want to match every route ending with -xyz suffix to the same router.
is there a way I can achieve it in laravel?
example:
abc.com/abc-xyz
abc.com/pqr-xyz
Both routes should lead to the same controller function. The urls will be dynamically generated in the blade file, so anything with -xyz need to be redirected to the same controller.
You can use the where method to define regex to match the routes.
Route::get('{page}', function ($page) {
dd($page);
})->where('page', '[A-Z-0-9_a-z]+\-xyz');
Tested for the below samples:
asdasd-xyz
2523_ewrew65s-ad5sd4ad-xyz
123-xyz

switch route in web.php laravel

I've 2 routes in my web.php
1) Route::get('/{url}', 'MenuController#menu');
which provide url :
/menu
2) Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
which provide url :
/menu (different page but same name in route 1)
/food
I want to use 2 route if route = same name I want to use route 1 if route 1 dont have url It will use route 2 . In web.php is their anyway to do something like
if(Route::get('/{url}', 'MenuController#menu')) is null use
`Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');`
now in my web.php I do this
Route::get('/{url}', 'MenuController#menu');
Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
when I go /food It will go page not found.
UPDATE
In my controller I try this
try {
// if find url
}
} catch (\Exception $e) {
//if not find url
return redirect()->route('promotiondetail', $url);
}
and It return Error redirected you too many times
UPDATE 3
$url = food
Your problem is that when you use
Route::get('/{url}', 'MenuController#menu');
Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
you are having the same request because {url} or {name} are optional parameters and what happens is that it will always match the first case. The best solution for you can be using this part of code:
Route::get('/menu', 'MenuController#menu');
Route::get('/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
You should always have the one with only optional parameters last, because otherwise it will always be executed first because it will be matching. And what you should remember is that using /{name} it will match anything, it is like a variable and can contain a number also it can be a string, for instance a url might be domain/{anything}. If you use /name it will match only if you are having domain/name as request.
You might want to read Laravel routing for more information about routing.
The problem you have is that both routes are essentially the same, /{something}.
You have a couple of solutions.
Firstly, sort out your routes, make them slightly different so they don't match each other and correct the order.
For example;
Route::get('/promo/{name}', 'HomeSlideviewController#index')->name('promotiondetail');
Route::get('/{url}', 'MenuController#menu')->name('menu');
Another solution that may work for you is to place the promotiondetail route first, and do a check in that for the same name, if not then redirect to the other controller. So in your index function of HomeSlideviewController, try something like;
public function index($name) {
if ($name !== 'whatever you want it not to be') {
return redirect()->route('menu);
}
// continue
}

Laravel routing: static text in optional url segment

I'm migrating the forum section of my website to Laravel 4. I manage the pagination myself. (Not the Laravel built-in one)
My urls currently use the following format:
example.com/forum
example.com/forum/page-1
I'd like to keep it like that after the migration.
My route looks like that:
Route::get('/forum/page-{page?}',
array('uses' => 'ForumController#showForum', 'as' => 'forum'));
But of course it doesn't work when I request the page without a page number.
I can do it like /forum/{pagetext?}-{page?} but I dont want to have to catch the pagetext parameter in my Controller, and I want to only give the $page parameter when I build urls for the page with URL::route().
I've found many examples on Internet but it was always with multiple parameters, no static optional text.
How can I make this "static" portion optional as well ?
I'm thinking to something like an optional group in a regular expression, like /forum/(page-{page})? but how do I do that in Laravel ?
If you truly need the parameter to be optional, I would make the whole segment of that route a single parameter, and you can use a regular expression to enforce it:
Route::get('/forum/{page?}', function($page = null) {
echo 'On page ' . $page;
})->where('page', 'page-[\d]+');
The drawback here is you'll have to get the numeric page number from within your route.
As #Jarek mentioned in the comments, you can also split this up into two different routes:
Route::get('/forum', function() {
echo 'Forum Index';
});
Route::get('/forum/page-{page}', function($page) {
echo 'On page ' . $page;
})->where('page', '[\d]+');

Routing Issue - Codeigniter

I have pages that are generated from a database, based on the URI. Functons as it should, however I can't set-up my routes to eliminate the controller and function from the URL.
$route['studios/(:any)'] = 'studios/location/$1';
Right now, I have the route to show the controller name and the URI variable (whatever that may be). However, I want to eliminate the controller name as well and just display the URI variable that's called as the URL. Hard to explain - hopefully someone picks up my drift...
Current URL would be: domain.com/studios/studio1
But I want to just display: domain.com/studio1
I tried $route['/(:any)'] = 'studios/location/$1';, but that's messing up my entire site.
Help?
$route['studios(/:any)*'] = 'studios/location';
This route will force everything from studios on to studios/location. You can then access any of the parameters using URI segments:
$id = $this->uri->segment(2);
If your URL was somewhere.com/studios/location/2, $id would resolve to 2
However, since you want it to just be from the root on, you will have to put your override route at the bottom of the routes file so it is assessed last:
// all other routes here. Which must be specifically
// defined if you want a catch all like the one you mentioned
$route['(:any)'] = 'studios/location';
Alternatively, if you want a high maintenance site, you can specify a collection of routes like so:
$route['(studio1|studio2|studio3)'] = 'studios/location/$1';
how is it "messing up your site"?
In any case, you should not have the / before (:any)
Just:
$route['(:any)'] = 'studios/location/$1';
EDIT:
BEFORE the $route['(:any)'], you'll need to specify routes fro all your controllers; this is pretty normal, don't know if I'd call it "high maintenance", but you'll need to decide

Routes in Codeigniter - Automatically

I have a problem with Codeigniter routes. I would like to all registered users on my site gets its own "directory", for example: www.example.com/username1, www.example.com/username2. This "directory" should map to the controller "polica", method "ogled", parameter "username1".
If I do like this, then each controller is mapped to this route: "polica/ogled/parameter". It's not OK:
$route["(:any)"] = "polica/ogled/$1";
This works, but I have always manually entered info in routes.php:
$route["username1"] = "polica/ogled/username1";
How do I do so that this will be automated?
UPDATE:
For example, I have controller with name ads. For example, if you go to www.example.com/ads/
there will be listed ads. If you are go to www.example.com/username1 there are listed ads by user username1. There is also controller user, profile, latest,...
My Current routes.php:
$route['oglasi'] = 'oglasi';
$route['(:any)'] = "polica/ogled/$1"
$route['default_controller'] = 'domov';
$route['404_override'] = '';
I solved problem with this code:
$route['oglasi/(:any)'] = 'oglasi/$1';
$route['(:any)'] = "polica/ogled/$1"
$route['default_controller'] = 'domov';
$route['404_override'] = '';
Regards, Mario
The problem with your route is that by using :any you match, actually...ANY route, so you're pretty much stuck there.
I think you might have two solutions:
1)You can selectively re-route all your sites controller individually, like:
$route['aboutus'] = "aboutus";
$route['where-we-are'] = "whereweare";
//And do this for all your site's controllers
//Finally:
$route['(:any)'] = "polica/ogled/$1";
All these routes must come BEFORE the ANY, since they are read in the order they are presented, and if you place the :any at the beginning it will happily skip all the rest.
EDIT after comment:
What I mean is, if you're going to match against ANY segment, this means that you cannot use any controller at all (which is, by default, the first URI segment), since the router will always re-route you using your defined law.
In order to allow CI to execute other controllers (whatever they are, I just used some common web pages, but can be literally everything), you need to allow them by excluding them from the re-routing. And you can achieve this by placing them before your ANY rule, so that everytime CI passed through your routing rules it parses first the one you "escaped", and ONLY if they don't match anything it found on the URL, it passes on to the :ANY rule.
I know that this is a code verbosity nonetheless, but they'll surely be less than 6K as you said.
Since I don't know the actual structure of your URLs and of your web application, it's the only solution that comes to my mind. If you provide further information, such as how are shaped the regular urls of your app, then I can update my answer
/end edit
This is not much a pratical solution, because it will require a lot of code, but if you want a design like that it's the only way that comes to my mind.
Also, consider you can use regexes as the $route index, but I don't think it can work here, as your usernames are unlikely matchable in this fashion, but I just wanted to point out the possibility.
OR
2) You can change your design pattern slightly, and assign another route to usernames, something along the line of
$route['user/(:any)'] = "polica/ogled/$1";
This will generate quite pretty (and semantic) URLs nonetheless, and will avoid all the hassle of escaping the other routes.
view this:
http://www.web-and-development.com/codeigniter-minimize-url-and-remove-index-php/
which includes remove index.php/remove 1st url segment/remove 2st url sigment/routing automatically.it will very helpful for you.
I was struggling with this same problem very recently. I created something that worked for me this way:
Define a "redirect" controller with a remap method. This will allow you to gather the requests sent to the contoller with any proceeding variable string into one function. So if a request is made to http://yoursite/jeff/ or http://yoursite/jamie it won't hit those methods but instead hit http://yoursite/ remap function. (even if those methods/names don't exist and even if you have an index function, it supersedes it). In the _Remap method you could define a conditional switch which then works with the rest of your code re-directing the user any way you want.
You should then define this re-direct controller as the default one and set up your routes like so:
$route['(.*)'] = "redirect/index/$1";
$route['default_controller'] = "redirect";
This is at first a bit of a problem because this will basically force everything to be re-directed to this controller no matter what and ultimately through this _remap switch.
But what you could do is define the rules/routes that you don't want to abide to this condition above those route statements.
i.e
$route['myroute'] = "myroute";
$route['(.*)'] = "redirect/index/$1";
$route['default_controller'] = "redirect";
I found that this produces a nice system where I can have as many variable users as are defined where I'm able to redirect them easily based on what they stand for through one controller.
Another way would be declaring an array with your intenal controllers and redirect everything else to the user controller like this in your routes.php file from codeigniter:
$controllers=array('admin', 'user', 'blog', 'api');
if(array_search($this->uri->segment(1), $controllers)){
$route['.*'] = "polica/ogled/$1";
}

Categories