Say I have a controller, "Articles" but I want it to appear as a sub-folder (e.g. "blog/articles"), I can add a route like this:
$route['blog/articles'] = 'articles';
$route['blog/articles/(:any)'] = 'articles/$1';
This works fine, the only problem now is that example.com/articles and example.com/blog/articles both use the Articles controller and thus resolve to the same content. Is there a way to prevent this?
To add a little more clarity in case people aren't understanding:
In this example, I don't have a 'blog' controller, but I want 'articles' etc to appear to be in that subfolder (it's an organization thing).
I could have a blog controller with an 'articles' function, but I'm likely to have a bunch of 'subcontrollers' and want to separate the functionality (otherwise I could end up with 30+ functions for separate entities in the blog controller).
I want example.com/articles to return a 404 since that is not the correct URL, example.com/blog/articles is.
Shove this in your controller:
function __construct()
{
parent::Controller();
$this->uri->uri_segment(1) == 'blog' OR show_404();
}
You can use subfolders in Codeigniter controllers, so in CI, the following directory structure works:
application/controllers/blog/articles.php and is then accessed at
http://example.com/blog/articles/*.
If, for some reason, you're set on routing instead of accessing the controllers in folders (you want to have a blog controller, for example, and don't want to route to it), you can do as suggested above and add the test for 'blog' to the constructor.
If you're in PHP5, you can use the constructor function like this:
function __construct()
{
parent::Controller();
$this->uri->uri_segment(1) == 'blog' OR redirect('/blog/articles');
}
or, in PHP4, like this:
function Articles()
{
parent::Controller();
$this->uri->uri_segment(1) == 'blog' OR redirect('/blog/articles');
}
I would suggest using redirect('blog/articles') instead of show_404(), though, so that you're directing users who hit /articles to the correct location, instead of just showing them a 404 page.
Routing there does not mean it will use a different controller, it just creates alias url segment to same controller. The way will be to create another controller if you are looking to use a different controller for those url segments.
If both /blog/ and /articles/ use the same controller, you can reroute one of them to a different one by just adding a new rule in your routes file.
Related
I tried to understand how the routing in CodeIgniter work.
I want to use normal access to sides which are not a kind of user area or something special - only normals links in the main root of the website.
So I try this.
I've set in the routes.php
$route['/'] = "index";
I've created controller names Frontend.php and a model named Frontend_modell.php
The Controller (nothing to do)
public function index()
{
redirect(site_url('index'));
}
The Modell
public function __construct()
{
parent::__construct();
}
I've added an index.php inside the view-folder Frontend and I add the index.php (for test) in the main folder from appilation and in the view folder.
If I try to access www.domain.com I see the URL will change to www.domain.com/index, but no side will come up. "the page you requested was not found."
What I do wrong ? I hope somebody can explain to me how it works correctly and why.
First of all routes uses controller_name/method_name and here you tried to use method_name directly.
Secondly, most of cases you don't need to play with routes unless you need a special handler or rerouting, so mostly keep it to default.
Btw the url rerouted to www.domain.com/index cause it looked for a controller named index as you specified and there in no controller found with that name it should be frontend if that's your controller.
The reason for the problem was from another point.
The Controller i've create had some bugs, after checking the function of the CR Controller, the routing works fine :-))
If I want to create RESTful APIs, which one should I choose?
How do the URLs as index.php/id/1 work? I think it's a file path, not a URL.
If I want to get an image as abc.com/img/1.png, it may have conflicts with abc.com/img/{param}. How do I solve?
BTW, I use Laravel now.
Thanks so much.
The difference is in route model binding
https://laravel.com/docs/5.7/routing#route-model-binding
This allows you to get the model with the id that is passed into the route
So for example a route like this:
Route::get('users/{user}', 'UsersController#getUser');
Will allow you to do this in you method:
use App\User
public function getUser(User $user) {
return $user;
}
This means that you get the full record for the id that is in the route.
So your Questions:
1: I would use this for sending model id's
2: the variables in the route are passed in that order to the method allowing you to get access to them.
3: You will need to be careful with your routes as you can have conflicts. having said that Laravel does not use a traditional directory structure for storage. I believe that if you have a folder stucture of /public/img and that folder contains an img named 1.png it will get the image but I have not tested this.
Lets say I have a controller 'standard' with an action 'main'.
If I go to www.myapp.com/standard/main it will invoke the main action in the standard controller.
Now if I want to change the URL I go into the routes.php and set sth like the following:
$route['welcome'] = "standard/main";
Now I can visit www.myapp.com/welcome and it will invoke the same action.
However it is still possible to visit www.myapp.com/standard/main. I now have two routes which lead to the same controller action.
Is this the usual way or should I somehow disable the now unwanted www.myapp.com/standard/main route? If so, how would I do that?
Thanks in advance.
That is completely for you to decide the default behavior. If you decide to disable the original url, you can write something like
$route['standard/main'] = 'standard/404';
Or any custom location, it depends on your project and how you wish it should look like, for example you can 'block' any method from being accessed directly:
$route['standard/(:any)'] = 'standard/404';
But bear in mind, if you route like you did $route['welcome'] = "standard/main";, then you should always remember that the function $this->uri->segment(n) will show different values, for example if I will go to url yoursite.com/welcome/123, the value of $this->uri->segment(2) will be 123, but if I visit the original URL yoursite.com/standard/main/123, it's value will change to main.
Bear that in mind and decide for yourself!
Assuming that this is a common structure you'll be using, for each action, you can check the segment's in the URL and then redirect appropriately. In the case of going from standard/main to welcome, you would have the following:
class Standard extends CI_Controller {
public function main() {
if($this->uri->segment(1) == 'standard') {
redirect('welcome', 'location', '301');
}
}
}
This would then check the first segment in the URL and if it sees that you've come to this URL, redirect you to the appropriate route. This can then be applied to each action you want to do the same thing for. Supplying a 301 signifies a permanent redirect.
Update
Just found a similar (the same?) question: Only allow URL's specified in routes to be seen in Codeigniter
I'm trying to create a default page controller for a site with urls like http://www.example.com/about. So, if there isn't an 'about' controller, then go looking for a page with that url string in the database.
I've set the 404_override to my 'page' controller and am using the _remap() function to determine where to go next, either load the homepage (the page controller's index() method) or load a page.
However, as it stands right now if I use a different controller (product, in this case) with a method in the path (http://www.example.com/product/widget, which doesn't exist) I am being served the index() method of the page controller.
I thought the problem comes from the way I'm checking if the requested page is the homepage in my _remap() so I added an echo to the beginning of my remap to see if it mattered. The _remap() doesn't appear to be called. Instead, in attempting to handle the 404_override CI just shows the index method.
Any ideas how I can accomplish this more effectively?
public function _remap($method)
{
echo 'Method '.$method;
if($this->uri->segment(1) == null)
{
// $this->index();
} else {
$this->view();
};
}
I seem to have found a workable solution in this blog post: http://pinoytech.org/blog/post/codeigniter-route-everything-except-these-controllers
Using a regular expression in the route definition allows for other controllers (product, order, etc.) to be ignored while still sending everything else to the page controller.
$route['^(?!product|order|misc_controller)\S*'] = "page/$1";
Haven't tested it out just yet, but as far as I can tell it should work swimmingly.
I've got a lot controller in my Codeigniter apps, ex: Signup, Profile, Main, etc..
Now I want to build "User" controller.
what I want:
if people goes to url: example.com/signup, I want use default route to "Signup" Controller
if people goes to url: example.com/bobby.ariffin, I want to reroute this to "User" Controller because the url not handled by any Controller in my apps.
I had create this in my config/routes.php:
$route['(:any)'] = "user";
but it's override all the route in my apps to "User" Controller.
Is there any simple route for Codeigniter that doesn't override the other controller routes?
Update---
I've got simple regex for this problem, from: Daniel Errante's Blog
$route['^(?!ezstore|ezsell|login).*'] = “home/$0″;
where ezstore, ezsell, and login are the name of controller in Your Apps.
You can also use a foreach statement for this. That way you can keep your controllers in a nice neat list.
$controller_list = array('auth','dashboard','login','50_other_controllers');
foreach($controller_list as $controller_name)
{
$route[$controller_item] = $controller_name;
}
$route['(:any)'] = "user/display/$1";
You're going to have to explicitly define all of those routes. Otherwise you will always end up at the "user_controller".
$route['signup'] = "signup";
$route['(:any)'] = "user/display/$1";
or something similar. They are ran in order, so what ever is defined first, is going to happen first. So if you catch (:any), you're going to send ANYTHING to that controller.
Also keep in mind that you can use regular expressions, so if you know there is always going to be a '.' in there, you could test for that.