I am working with CodeIgniter (V:2.2.6) and I have a simple class User with some basic methods like create, update, edit, delete and index. For the index function, I am using an argument $user (which is the second URI segment) in order to display some information regarding that user. So the default URL looks like:
/user/index/john
to display some information about the user 'john'.
Now, I want to remove the term 'index' from the URL, so that it looks like:
/user/john
For that purpose I have added the following rule in routes.php.
$route['user/(:any)'] = "user/index/$1";
It serves the purpose, but it prevents accessing other functions like /user/create and goes inside /user/index automatically. To solve this problem, I can not see any other way except manually adding routing rules like
$route['user/create'] = "user/create";
for each method of the User class, which is not cool at all. So, please can anyone suggest me a better way of routing under the current circumstances?
Here are my codes:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class User extends CI_Controller {
public function index($user = '') {
echo "index!";
}
public function create() {
echo 'create!';
}
}
Note: I have gone through the CodeIgniter documentation for URI Routing and another similar question here, but could not figure out a promising solution. And please don't suggest for CodeIgniter version update.
I'm not sure, if this is the answer you like, but i think it should work.
Just put this function in your user controller.
public function _remap($method)
{
if (method_exists($this, $method))
{
$this->$method();
}
else
{
$this->index($method);
}
}
Related
I have used several codes for restricting direct access of controller page from url, but its not happening.
The below code in controller page is not preventing from direct url access. Is there any proper way to prevent from direct access from url?
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Cont extends CI_Controller
{
public function __construct()
{
parent ::__construct();
$this->load->model('test');
}
public function handle($function){
if($function=='abcd'){
$this->load->view('testpage');
}
}
}
You can use HTTP_REFERER which holds the information(address) about the page that referred you to the current page, if it's empty you can redirect it to your 404 page. Also, you should always check for $_SESSION and redirect if not set.
if( !isset($_SERVER['HTTP_REFERER'])) {
$this->load->helper('url');
redirect('/page404');
}
Alternatively, you can also use HTTP_X_FORWARDED_FOR, but it won't help you in AJAX request. Read more about it here and here.
You can use _remap() function inside your Controller, where we can define where to route the method.
The following code blocks all method call to that controller.
function _remap($method)
{
return false;
}
See the DOC here
From documentation
For the best security, both the system and any application folders should be placed above web root so that they are not directly accessible via a browser. By default, .htaccess files are included in each folder to help prevent direct access, but it is best to remove them from public access entirely in case the web server configuration changes or doesn’t abide by the .htaccess.
If you want to prevent direct access to specific methods then you can try
public function _handle(){ //adding _ before the method name
}
Or
private function handle(){ //private functions cannot access by url
}
I've altered routes.php
$route['category']='Home/category';
for making url look like www.website.com/category insteead of www.website.com/Home/category. Since Home is my default controller.
but if i am using $this->uri->segment(); inside category function, its not working. this is my controller
class Home extends CI_Controller {
public function category()
{
$value=$this->uri->segmet(3);
}
}
And my url is www.website.com/category/books
I am getting result if I dont alter routes. But by altering routes, I need this to work. Please help me. Thanks
You can debug what you have there by:
var_dump($this->uri->segment_array());
this will give you array of all segments in URI.
Also you can try to debug with this method:
var_dump($this->uri->rsegment_array());
this will give you array of all routed segments in URI
Respectivelly, you can use $this->uri->segment() or $this->uri->rsegment() what ever you find more appropriate for your application.
hello please check segment spelling in your code
class Home extends CI_Controller {
public function category()
{
$value=$this->uri->segmet(3); //wrong
$value=$this->uri->segment(3);
}
}
First of all you need to load URL library and than if your URL is:
www.website.com/category/books
And you want to get books from URL than segment should be:
$value=$this->uri->segment(2); //books
My URL libraries are in autoload. Anyway I solved it. I just configured my routes like this
$route['category/(:any)']='Home/category/$1'
I need to use a subdomain as a class. ie, instead of:
www.example.com/class/function/ID eg www.example.com/town-name/history/1
I need
class.example.com/function/ID eg town-name.example.com/history/1
I've wildcarded the subdomain in nginx, now I've googled and read
http://codeigniter.com/user_guide/libraries/uri.html
http://codeigniter.com/user_guide/general/urls.html
http://codeigniter.com/user_guide/helpers/url_helper.html
but nothing relevant. I need it to be so that if another town is added to the db, it'll resolve that new town and its details.
I see many discussions about rewrites, redirects etc, but I specifically need to use the subdomain town name as the class variable. If possible, in an idea world, I could use both together, but I doubt that's possible?
I've had it going fine in plain old php for a couple of years now; now I want to upgrade to codeigniter without ruining my old structure if possible (plus there's a good reason for it).
Thanks you.
You can do it. I'm doing it for one of my projects.
In the constructor of your controller, just explode the current url and get the subdomain and pass it in your method as a variable
public class Controller extends CI_Controller {
$subdomain = null;
public __construct()
{
// explode url here and set $this->subdomain = the actual subdomain
}
public function index()
{
if($this->subdomain == null) {
show_404();
} else {
// do what you wish
}
}
}
I am fairly new and just started to use Codeigniter, and have come across some confusion regarding sessions.
What I want to achieve is, like in regular php, I want to check if a user is logged in by using a header include file which checks the session data. I dont want to check/write that checking code in every controller while passing data to the view file.
Can someone please show me how it can be done?
Ex. I don't want to do the following in every controller:
//Controller:
if($this->session->userdata('loggedin'){
$data['loggedin'] = $this->session->userdata('loggedin');
}
//I dont want to check the above on every function in every controller
$this->load->view('some_view_file', $data);
//some_view_file
if(isset($loggedin)){
echo "You are logged in!";
}
else
{
echo "Please log in!";
}
Instead, I want something to like the following:
//some view file
if(isset($loggedin))
{
echo "your logged in";
}
else
{
echo "please log in";
}
And also, how can I use native php sessions instead of CI Sessions. Any help will be much appreciated. Thanks.
Firstly, theres no reason you can't just write something like this in your view:
<? echo ($this->session->userdata('loggedin')) ? "Logged In": "Not Logged In"; ?>
Then your controllers don't need any of that code.
However if the check is more complex or something, then theres a few places you can do it.
1) In the constructor of a custom controller: create a new file application/core/MY_Controller.php, and override the constructor with something like:
class MY_Controller extends CI_Controller
{
public function __construct()
{
parent::__construct();
if($this->session->userdata("loggedin")) {
// do something
}
}
}
then make all your controllers extend MY_Controller.
2) Or in a post_controller_constructor hook. http://codeigniter.com/user_guide/general/hooks.html (this is more transparent, and probably easier if you have tons of controllers already)
You can use native sessions with this:
http://codeigniter.com/wiki/Native_session/
I think using a construct on your controller would be the smartest approach.
I also recommend encrypting your session cookie.
class Blog extends CI_Controller {
public function __construct()
{
parent::__construct();
//always check if session userdata value "logged_in" is not true
if(!$this->session->userdata("logged_in"))
{
redirect('login');
}
}
}
Let's say that I have a website that has 100 different pages. Each page uses a common header and footer. Inside the header is some dynamic content that comes from a database.
I'd like to avoid having to have code in every single controller and action that passes this common code into the view.
function index()
{
// It sucks to have to include this on every controller action.
data['title'] = "This is the index page";
data['currentUserName'] = "John Smith";
$this->load->view("main_view", data);
}
function comments()
{
// It sucks to have to include this on every controller action.
data['title'] = "Comment list";
data['currentUserName'] = "John Smith";
$this->load->view("comment_view", data);
}
I realize that I could refactor the code so that the common parts are in a single function and the function is called by the action. Doing so would reduce SOME of the pain, but it still doesn't feel right since I'd still have to make a call to that function every time.
What's the correct way to handle this?
One way I have been doing this is to extend the default controller class. You can read up on extending classes with MY_Controller in the user guide. Inside this extended class you can include something that you ALWAYS want to do, like render the page header template before the main content, or authorise a users access etc.
class MY_Controller extends Controller {
function __construct()
{
parent::Controller();
//code to always do goes here
echo 'Always print this comment';
$this->load->view('partials/template_start');
}
}
Then you can have your normal controller class extend THIS class by using
class MyControllerNameHere extends MY_Controller {
function __construct()
{
//setup here
}
function index()
{
echo 'Only print this bit when this method is called';
$this->load->view('partials/MYPAGENAMEHERE');
}
}
There are other ways of doing this, I use a mixture of the above and William's Concepts Codeigniter Template library. Do a bit of searching - there are a few solutions for you.
I had a similar situation. I created an 'includes' folder, and in there put a file that had the repetitive code from my controllers. Then in the controllers just include('/path/to/includeFile.php');
Don't know if it's the "correct" way, but it works well for me.
I ran across this after a search of their site. http://codeigniter.com/wiki/Header_and_footer_and_menu_on_every_page/ I'll review this page and its links, then post my thoughts.