rewriting urls in codeigniter - php

How can I rewrite the following codeigniter url
localhost/test_project/pages/show_page/11
to
localhost/test_project/pages/11
and is it possible to further reduce like:
localhost/test_project/11
Thanks.

You should edit this file: application/config/routes.php.
Let's assume you have a pages controller and a show_page method with receives an id as a parameter (just as you said).
your URL is like localhost/test_project/pages/show_page/11
I assume that the parameter is always a number, so using wildcards as described here you can add the following to your routes.php file:
$route['pages/(:num)'] = "pages/show_page/$1";
So your URLs will be like localhost/test_project/pages/3. This is like saying if anyone tried to visit localhost/test_project/pages/3, he/she actually means localhost/test_project/pages/show_page/3.
For urls like localhost/test_project/3 you can add this:
$route['(:num)'] = "pages/show_page/$1";

You've a few options. These are in descending order of priority.
First there is routes.php, which is the generally preferred way of handling things (information already provided, but here it is again).
You can also add a _resolve method to a controller (which means that CI needs to get to your controller to begin with), and
finally you can override the CI_Router library, the class which actually returns the route to go to.
Seriously, don't override CI_Router unless you know what you're doing.

Related

Conditional Routing in Laravel

Let say I have my user controller and there are action_index(), action_login(), action_logout() action_profile($userid) methods in it. I want to make a routing that
www.mysite.com/user/xxxx
checks the xxxx part of the url and if it is not one of (login,logout,index) it calls action_profile(xxxx) method.
Now I am doing it like this:
my routing routs all www.mysite.com/user/xxxx type of requests to action_index and it checks whether xxxx is a method name or not. If it is not a method name it calls action_profile(xxxx)
However, I think it is possible in a better way. How can I do it better?
Hmm I'm not sure if I understand what you're asking. Routes in laravel are on a first match basis.
So you could just add the following to your routes.php:
Route::get('user/(:num)', 'user#profile');
Route::controller('user');
The first line is for routing user/xxx to action_profile() in user controller where xxx is any numerical value. While the second will maps any other URI (user/***/***) to corresponding user controller's methods. That means it automatically maps user/login to action_login(), user/register to action_register() and so on.
I would recommend you avoid using Route::controller() in this instance. While it can be fine to use in some cases, for what you're after it would be better to map to the routes.
You could do it like so.
Route::get('user', 'user#index');
Route::get('user/(:num)', 'user#profile');
Route::get('user/(:any)', 'user#(:1)');
Or you could be a little stricter with your last route.
Route::get('user/(login|logout)', 'user#(:1)');
My reasoning for recommending you avoid Route::controller() is that it does create duplicates to some content. For example, yoursite.com/user will by duplicated on yoursite.com/user/index. This can be bad for search engine optimization.
Mapping to your actions gives you that extra flexibility and control.

Route random strings to a specific controller in CodeIgniter?

I am trying to create short links to my application in codeigniter but I've met a kind of a problem when designing my route. The problem is that I want a route which will take a string containing a-Z and numbers and redirect that to a controller called image with the string after. Like this: app.com/randomstring -> app.com/image/randomstring. But when I am trying to do this in the routes config file with a regular expression it disables my application and I am unable to enter "normal" urls with controllers that already exist.
How my route looks like right now (I know it's probably very wrongly made):
$route['(^[A-Za-z0-9]+$)'] = "image/$1";
Is there any easy way to redirect with that short url without using another fake controller first like this: app.com/i/randomstring -> app.com/image/randomstring
And could you maybe help me improve and tell me what part of my regexp is failing?
As I mentioned in the comments, without a clearly defined spec on what the image urls will be, there's no comprehensive way to solve this. Even YouTube (related to the library you linked to) uses urls like /watch?v=h8skj3, where "watch" is the trigger.
Using a i/r4nd0m$tring would make this a non-issue, and it's what I suggest, but I had another idea:
$route['(:any)'] = "image/$1";
// Re-Route all valid controllers
foreach (array('users', 'login', 'blog', 'signup') as $controller)
{
$route[$controller] = $controller;
$route[$controller.'/(:any)'] = $controller.'/$1';
}
unset($controller);
You might need the image route last, I'm not 100% sure. This should route everything to image/ except the controllers you define. You could even use glob() or something to scan your controller directory for PHP files to populate the array.
Another way to get one character shorter than i/string could be to use a character trigger, like example.com/*randomstring, but that's a little silly, i/ is much cleaner and obviously, easier to deploy.

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";
}

Make title string the entire URI for all pages using CodeIgniter

With CodeIgniter I'm trying to create a URL structure that uses a title string as the entire URI; so for example: www.example.com/this-is-a-title-string
I'm pretty confident I need to use the url_title() function in the URL Helper along with the routes.php config folder but I'm stuck bringing it all together.
Where do I define the URI and how is it caught by the routes folder?
Seems to be a straight forward problem but I'm getting stuck creating the URLs end-to-end. What am I missing?
I thought about a catch-all in the routes folder: $route['(.*)'] = "welcome/controller/$1"; ....but how would this work with multiple functions inside a particular controller? ...and maybe it's not even the right way to solve.
You can send all requests to a driver with something like this:
$route['(:any)'] = "welcome/function";
Then use the _remap function to route requests inside the controller.
However, using URL's as you suggest limits the CI functionality. Try something better like www.example.com/article/this-is-a-title-string
$route['article/(:any)'] = "articles/index";
and in article (controller), use _remap...
If you're going to re-route every request, you should extend CI_Router.
The actual implementation depends on what you're doing. If you customize CI_Router, you can do it AFTER the code that checks routes.php, so that you can keep routes.php available for future customization.
If the URI contains the controller, function, and parameters, you can parse it within your extended CI_Router and then continue with the request like normal.
If the URI is arbitrary, then you'll need something (file, db, etc) that maps the URI to the correct controller/function/parameters. Using blog posts as an example, you can search for the URI (aka post-slug in WordPress) in the db and grab the corresponding record. Then forward the request to something like "articles/view/ID".

Remapping Codeigniter Controller

I've been playing with Codeigniter lately, and I came to know that you can remap a function inside a Controller so that you can have dynamic pretty URL.
I just want to know can the same be done with controllers? I mean If I call http://example.com/stack, it'll look for a controller named stack and if not found, it'll call a fixed/remapped controller where I can take care of it.
Can this be done?
Maybe this can help you:
function _remap( $method )
{
/// $method contains the second segment of your URI
switch( $method )
{
case 'about-me':
$this->about_me();
break;
case 'successful':
$this->display_successful_message();
break;
default:
$this->page_not_found();
break;
}
}
Yes, it can be done, you achieve it by using uri routing.
In your application/config/routes.php you can set your custom routes to remapping URIs.
There are already 2 provided, the default one (in case no controller is called) and the 404 error routing.
Now, if you want to add custom routes, you just add them UNDER those 2 defaults, keeping in mind that they're executed in the order they're presented.
Say, for example, you want to remap 'stack' to another controller, just use:
$routes['stack'] = 'othercontroller';
In this way, whenever you access 'stack' it will be automatically mapped to 'othercontroller', and if that doesn't exists..well, you get the same 404 error.
If you're hiding index.php from the URL with .htaccess remember to insert it into the $config['index_page'] = 'index.php';.
If what you're trying to achieve, instead, is a custom error message when a controller is not found, just override the 404 route as already suggested by #Juris Malinens, using your custom default controller to handle that situation
$route['404_override'] = 'customcontroller';
You can use .htaccess to do this or config/routes.php- Codeigniter is very flexible ;-)
If controller is not found use $route['404_override']; in config/routes.php
The application/config/routes.php file would be the appropriate place to do this. The 404_override mentioned by Juris is only available in CI 2.x just in case you have an older version (I don't know, you may be working on a legacy system, or may have to in the future).
Note, you can do more than just "remap" controllers with this. The routes accept regex patterns like htaccess rewrite rules; there are also some CI patterns which are basically just more human readable alias for regexes. Say you had an Articles controller with category, search and article functions, you might have routes that looked like:
$route["category/(:any)"] = "articles/category/$1";
$route["search/(:any)"] = "articles/search/$1";
$route["(:any)"] = "articles/article/$1';
You see how you can use routes to completely remove the controller name from you URLs? These rules would fall back to assuming the page is an article if the URL doesn't specifically say it's a category page or a search query. You could then check if you had an article for the URL and display a 404 as appropriate.

Categories