So I have a page:
http://www.mysite.com/controller/function
The function is defined in the controller as:
function ()
{
//some stuff here
}
However it is possible to resolve the URL:
http://www.mysite.com/controller/function/blablabla
i.e. "blablabla" can be passed to the function and forms an additional URI segment, but still brings up the same page. I have the same issue with a number of controllers / functions - how do I prevent parameters being passed to the function (or appearing as a URI segment)?
I've been working with Codeigniter and PHP for around 6 months very part time, so forgive me if the answer is obvious but my searches haven't been fruitful on this.
My goal is optimised SEO - unsure whether better to redirect the page with the extra URI segment to the correct page or to the 404 page.
You can't prevent that without changing how CI handles URI parsing.
You could force a redirect like so:
function my_happy_function($redirect=null) {
if($redirect) {
redirect('/controller/my_happy_function/');
}
}
That would strip out any variables that are given in the URI, at the cost of a page redirect.
Sounds like you want a generic catch all for pages. You can do this using routes.
For example:
$route['my_happy_function(/:any)*'] = "my_happy_function";
then in your my_happy_function index method you check the URI segments there...
public function index()
{
$something = $this->uri->segment(1);
$something_else = $this->uri->segment(2);
// etc
}
this way all calls to my_happy_function get pushed to the index method...
wait, did I understand your question correctly? If I missed the point let me know and I can update.
Related
I'm working on a project where I need to create clean URL for every products, see following pattern:-
example.com/Single_Product_Page
The original URL is example.com/browse/Single_Product_Page and I used following code:-
$route['(:any)'] = 'Products/browse/$1';
I've two page (1) example.com/Product
and (2) example.com/Products/Single_Product_Page
And it is working fine but now I'm unable to open Products page and when I tried to open it, It open Single_Product_Page
Please help me to solve this issue.
You need to update your routes similar to this example (which works OK on my site):
$route['products'] = 'controller/myfunction/argument';
$route['products/:any'] = 'controller/myfunction/another_argument/$1/1';
you can get more insight from the docs here
You can use a little hack to use just your controller name (and that's a must of course) but eliminate the need to write the method name and pass your parameters directly after the controller name so basically your url would look like this: http://localhost/controller/parameter and that would give you shorter urls as you intend but not an SEO friendly as you claimed.
You can use _remap in your controller and check if it matched a method process it normally or pass it to your index (which is your default method that's doesn't have to be written in your url) .. and now you won't need to use index in your url as you intended.
public function _remap($method)
{
if ($method === 'some_method_in_your_controller')
{
$this->$method();
}
else
{
$this->index($method);
}
}
Or you can depend on ajax for all of your crud operations and your url will be pretty much fixed all the time.
In my controller i used this way. i want to pass a variable data to my index function of the controller through redirect
$in=1;
redirect(base_url()."home/index/".$in);
and my index function is
function index($in)
{
if($in==1)
{
}
}
But I'm getting some errors like undefined variables.
How can i solve this?
Use session to pass data while redirecting. There are a special method in CodeIgniter to do it called "set_flashdata"
$this->session->set_flashdata('in',1);
redirect("home/index");
Now you may get in at index controller like
function index()
{
$in = $this->session->flashdata('in');
if($in==1)
{
}
}
Remember this data will available only for redirect and lost on next page request. If you need stable data then you can use URL with parameter & GET $this->input->get('param1')
So in the controller you can have in one function :
$in=1;
redirect(base_url()."home/index/".$in);
And in the target function you can access the $in value like this :
$in = $this->uri->segment(3);
if(!is_numeric($in))
{
redirect();
}else{
if($in == 1){
}
}
I put segment(3) because on your example $in is after 2 dashes. But if you have for example this link structure : www.mydomain.com/subdomain/home/index/$in you'll have to use segment(4).
Hope that helps.
Use session to pass data while redirecting.There are two steps
Step 1 (Post Function):
$id = $_POST['id'];
$this->session->set_flashdata('data_name', $id);
redirect('login/form', 'refresh');
Step2 (Redirect Function):
$id_value = $this->session->flashdata('data_name');
If you want to complicate things, here's how:
On your routes.php file under application/config/routes.php, insert the code:
$route['home/index/(:any)'] = 'My_Controller/index/$1';
Then on your controller [My_Controller], do:
function index($in){
if($in==1)
{
...
}
}
Finally, pass any value with redirect:
$in=1;
redirect(base_url()."home/index/".$in);
Keep up the good work!
I appreciate that this is Codeigniter 3 question, but now in 2021 we have Codeigniter 4 and so I hope this will help anyone wondering the same.
CI4 has a new redirect function (which works differently to CI3 and so is not a like for like re-use) but actually comes with the withInput() function which does exactly what is needed.
So to redirect to any URL (non named-routed) you would use:
return redirect()->to($to)->withInput();
In your controller - I emphasise because it cannot be called from libraries or other places.
In the function where you are expecting old data you can helpfully use the new old() function. So if you had a key in your original post of FooBar then you could call old('FooBar'). old() is useful because it also escapes data by default.
If however, like me, you want to see the whole post then old() isn't helpful as the key is required. In that instance (and a bit of a cheat) you can do this instead:
print'<pre>';print_r($_SESSION['_ci_old_input']['post']);print'</pre>';
CI4 uses the same flash data methods behind the scenes that were given in the above answers and so we can just pull out the relevant session data.
To then escape the data simply wrap it in the new esc() function.
More info would be very helpful, as this should be working.
Things you can check:
Is your controller named home.php? Going to redirect(base_url()."home"); shows your home page?
Make your index function public.
public function index($in) {
....
}
I have a route that needs to be redirected to another page if the data they're pulling doesn't exist. The route is:
Route::get('{link}/{data}', 'LinkController#getLink');
Where {link} and {data} are model bound with:
Route::model('link', 'Link');
Route::model('data', 'Data');
As is, when the data for this link doesn't exist it 404's, and if it does exist, it's taken to the page as it should. What I would like to do is redirect to another page if the link would otherwise 404. I've found suggestions on how to do this globally, but I only want it to happen on this one route.
Any ideas?
// Link Controller
public function getLink($linkId, $dataId)
{
if ( is_null($link) or is_null($data) ) {
return Redirect::to('some/path');
}
}
If either of the passed models are null when it hits your controller method, just redirect them. As for your /{link} route that you refer to but don't show code for, do something similar in whatever closure/controller you handle that in.
Get rid of the model binding - you've left the cookie cutter realm.
Route::get('{link}/{data?}', 'LinkController#getLink');
// note I made the data ^ parameter optional
// not sure if you want to use it like this but it's worth pointing out
Do all of the model checking in the controller, something like this:
public function getLink($linkId, $dataId)
{
$link = Link::find($linkId);
$data = Data::find($dataId);
if(is_null($link)){
throw new NotFoundHttpException;// 404
}
elseif(is_null($data)){
return Redirect::to('some/view');// redirect
}
// You could also check for both not found and handle that case differently as well.
}
It's hard to tell from your comments exactly how you'd like to treat missing link and/or data records, but I'm sure you can figure that out logically. The point of this answer is that you don't need to use Laravel's model binding since you can do it yourself: find the record(s) else redirect or 404.
I have a page /discussion and I want to implement pagination in it. Now, I want that for the first time the page should load as /discussion, which means that this act as if it was /discussion/page/1. For the other page the url will be /discussion/page/$pagenumber.
Now, the problem is index(). Normally, I initialize all the page data in the index() and then load the view with the initialized data. But, here I’ll have to initialize default page stuff in index() and then the pagination stuff in page(). So, is there a way of sending another set of data from page() to the view? I don’t want to load the view since it will be loaded by the index().
However, I think it is not possible to do what I mentioned above. So, maybe I should keep my index() empty and do all the initialization in the page() and then load the view there. What do you say?
You don't need both the "page" and "index" methods, just use a route.
Using an index() method and dropping the page() method:
$route['discussion/page/(:num)'] = 'discussion/index/$1';
/discussion still gives you page 1, requesting discussion/page/32 will map to discussion/index/32
This assumes you're grabbing the page number as an argument (url segment), like so:
function index ($page = 1) {}
If you are doing something else, a route is still appropriate, maybe just not the one provided.
I suggest to have a look at PEAR's awesome Pager package. It automatically generates a pager and gives you the correct indexes depending on the (GET) input variables.
It sounds like you're trying to have your page method decorate your index method. Without knowing more about the overall structure of the controller, there really isn't terribly much to say, but it sounds like the below will help:
function page( $pos )
{
$this->index( $pos );
}
// a default parameter lets you ensure that this does not neet to have a page set.
function index( $pos = 0 )
{
// when calling the DB (I'm guessing that is where the pagination really happens)
// COUNT should be defined in the config if possible.
$this->db->where/*... add more here...*/->limit( COUNT, $pos );
}
Realistically, you should look into your URI routing class or using the _resolve method, but this should do what you need it to.
I'm not quite sure what your problem is.
If you have a index() method you can set all the pagination information there, remember you have to tell the pagination library which uri segment will be using to get the page number, and that doesn't have anything to do with the index().
There is no page() method in the controller, all of the pages are the same index() with a different set of paginated data, given by the uri_segment defined as the page number, that means all the stuff that is not related to the paginated queryset are intact through the pages.
I am currently working on CMS for a client, and I am going to be using Codeigniter to build on top of, it is only a quick project so I am not looking for a robust solution.
To create pages, I am getting to save the page details and the pull the correct page, based on the slug matching the slug in the mysql table.
My question is however, for this to work, I have to pass this slug from the URL the controller then to the model, this means that I also have too have the controller in the URL which I do not want is it possible to remove the controller from the URL with routes?
so
/page/our-story
becomes
/our-story
Is this possible
I would recommend to do it this way.
Let's say that you have : controller "page" / Method "show"
$route['page/show/:any'] = "$1";
or method is index which I don't recommend, and if you have something like news, add the following.
$route['news/show/:any'] = "news/$1";
That's it.
Yes, certainly. I just recently built a Codeigniter driven CMS myself. The whole purpose of routes is to change how your urls look and function. It helps you break away from the controller/function/argument/argument paradigm and lets you choose how you want your url's to look like.
Create a pages controller in your controllers directory
Place a _remap function inside of it to catch all requests to the controller
If you are using the latest version of CI 2.0 from Bitbucket, then in your routes.php file you can put this at the bottom of the file: $routes['404_override'] = "pages"; and then all calls to controllers that don't exist will be sent to your controller and you then can check for the presence of URL chunks. You should also make pages your default controller value as well.
See my answer for a similar question here from a few months back for example code and working code that I use in my Codeigniter CMS.
Here's the code I used in a recent project to achieve this. I borrowed it from somewhere; can't remember where.
function _remap($method)
{
$param_offset = 2;
// Default to index
if ( ! method_exists($this, $method))
{
// We need one more param
$param_offset = 1;
$method = 'index';
}
// Since all we get is $method, load up everything else in the URI
$params = array_slice($this->uri->rsegment_array(), $param_offset);
// Call the determined method with all params
call_user_func_array(array($this, $method), $params);
}
Then, my index function is where you would put your page function.