I've just started learning CodeIgniter, and I'm following this authentication tutorial by nettuts+. I did not understand one thing in it:
He added the following constructor code in the Welcome controller, which basically can be accessed only if the Session has variable username, otherwise it will redirect to admin controller.
function __construct()
{
session_start();
parent::__construct();
if ( !isset($_SESSION['username'])){
redirect('admin');
}
}
He said:
If you have multiple controllers, then
instead of adding the above code in
every controller, you should Create a
new library, which extends the
controller you will paste the code in,
and autoload the library into
project. That way this code runs
always when a controller is loaded.
Does it mean, I should
Create a file in application/libraries (eg. auth.php)
Paste this code in the auth.php
.
if ( !isset($_SESSION['username'])){
redirect('admin');
}
Now how to autoload this library and make it run every time a controller is loaded as he said?
Thanks
1) to autoload a library, just add it to the array in the file application/config/autoload.php, look for the 'library' section and paste the name of the library(without extension) there, as an element of the array.
$autoload['libraries'] = array ('auth');
2) I suggest you use the native session handler (session library), which works pretty well and avoids you to use php $_SESSION. You set a width $this->session->set_userdata(array('username' => 'User1', 'logged' => 'true'), and then you retrieve the values with $this->session->userdata['logged'], for ex.
Works like a charm and don't have to call session_start() and so on. Go check the help because it's really really clear on that.
3) As for your problem, I'll go, instead, for 'hooks'. There are different hooks, depending on their 'position', i.e. the moment in which you're calling them.
You can use, for ex.. the 'post_controller_constructor', which is called after controller initialization but BEFORE the methods, so it's in a midway between the constructor and the actual method. I usually insert this controls here.
You define hooks in application/config/hooks.php, and give them an array:
$hook['post_controller_constructor'] = array(
'class' => 'Auth',
'function' => 'check',
'filename' => 'auth.php',
filepath' => 'hooks',
'params' => array()
);
Anyway, for all these needs, the docs are pretty clear and straightforward, I suggest you read about hooks and session and you'll see everything gets much clearer!
The other way to do this. This is what he means in tutorial.
Create a library called MY_Controller in your application/libraries folder and extend it from CI_Controller:
Class MY_Controller extends CI_Controller {
public function __construct()
{
parent::__construct();
// do the stuff you want to execute on every page.
// like auth.
}
}
Autoload the auth class in autoload.php config file. There is no need to autoload MY_Controller CodeIgniter will automaticly recognise it and run it. You can also load the Auth library within MY_Controller
Extend your controllers with MY_Controller class. (Not CI_Controller)
Extending your controller will give to more control of your project. You can add extra methods to use everywhere on your project.
For more information about extending native libraries of CodeIgniter check Creating Libraries: CodeIgniter.
Add the new library to the autoload library array in config/autoload.php.
$autoload['libraries'] = array ('database', 'session', 'auth');
Then when you want to call the function in controller constructors use $this->auth->function_name();.
You may want to make it a hook if there's a lot of repeat functionality that you don't want to call in every single constructor.
Related
So I have my codeigniter setup in which I have a whole bunch of autoloaded helpers, libraries etc. I have a function written which I want to execute before the application bootstraps. Lets call the function init() and assume its defined in one of the helpers. Problem is that it uses functions from other autoloaded helpers and libraries etc so calling the init() in the autoloaded file itself does not help because it runs into 'call to undefined function X' etc..
So I want to make the init() call after everything has loaded..I cannot call it in the default controller, because users might have a different URL bookmarked.
What is the best way to call init() in this case?
Add a hook in application/config/hooks.php
$hook['pre_controller'] = function()
{
// ...
};
You may use a function declared in another file, for example:
$hook['pre_controller'] = array(
// ...
'function' => 'init'
);
There are many hooks available but in your case, the 'pre_controller' hook seems appropriate to me because pre_controller called immediately prior to any of your controllers being called. All base classes, routing, and security checks have been done.
I want to add products via my script which is not connected with OpenCart.
For example: somedir/index.php. I try to do it in this way:
$productData = array(
'model' => 'ABC123',
'name'=>'aaa',
'description'=>'aaa',
'tag'=>'aaa',
...
);
require_once ('../../system/engine/model.php');
require_once ('../../admin/model/catalog/product.php');
$a= new ModelCatalogProduct();
$a->addProduct($productData);
But there are many functions that need to be triggered. How can this be achieved?
OpenCart uses a so called MVC-pattern. This patteren works within OpenCart in a very specialised and deeply coupled way, so you need the context of the routing system in case you would like to use controllers and models in your code.
Also, it really depends on which version you use, what semantics would be right, so that is hard to tell. Conceptually, you would do something like this:
- define a new contoller in the /admin/controller directory structure, i.e. /admin/controller/tool/product_import.php
Call that controller ControllerToolProductImport which extends Controller;
Create a public function index()
Have it load the model like $this->load->model("catalog/product");
Now the model function becomes available and you would use it like $this->model_catalog_product->addProduct($productData);
This public function index can be triggerd by https://hostname:port/admin/index.php?route=too/product_import&token=ABC (you'll see what the token should be, once logged in into the admin section). To trigger another function within that controller directly (it needs to be public), you could extend the route easily. So for public function doSomething() it would become https://hostname:port/admin/index.php?route=too/product_import/doSomething&token=ABC.
When triggering this function from within the admin section, you would use the OpenCart functions to do so. Depending on your version, this would go like this for 2.2.0.0:
$this->url->link('tool/product_import', 'token=' . $this->session->data['token'], true)
I'm new to CodeIgniter and currently in my project I have several Models, loaded by several Controllers, which need to work with the database.
My question is - can I call $this->load->database() in just one place for the entire project, or should I do it in each method in my Models?
Thanks
In your autoload.php which is located in /application/config/autoload.php in which you see
$autoload['libraries'] array just add
$autoload['libraries'] = array('session', 'database','other_libraries');
If your project scope involves the database interaction you should use the autoload while including in each function would be a headache for you
Hope it makes sense
You have three choices (that I can think of).
If you require it almost everywhere in your project, use the
/application/config/autoload.php file, in which you'll find the
following statement:
$autoload['libraries'] = array();
which you can change to
$autoload['libraries'] = array('database');
This is the easiest method, but it does add overhead since the database class will be loaded even when you do not require it.
If you find that you need to use it for almost every method in a particular model you can call $this->load->database(); in the constructor of that particular model, for example:
class Forums_model extends CI_Model{
function __construct()
{
// Call the parent constructor
parent::__construct();
$this->load->database();
}
function get_records()
{
$this->db->get('table');
//this now works in every method in this model
}
}
which will make the database class available to every method in that model. This is a more efficient option than the second and not as tedious as the third, probably making it the most balanced option.
You can also, of course, choose to load it in every method that requires it using $this->load->database(); This adds the least overhead, theoretically making it the most efficient. However, doing this is very tedious.
All three will work, it's your choice whether you want it to be easy, or efficient. (My personal recommendation is choice 2)
If only some of your pages require database connectivity you can manually connect to your database by adding this line of code
$this->load->database();
in any function where it is needed, or in your class constructor to make the database available globally in that class.
The "auto connect" feature will load and instantiate the database class with every page.just
add the word 'database' to the library array, as indicated in the following file:
application/config/autoload.php
http://ellislab.com/codeigniter/user-guide/database/connecting.html
I know this is not the best of all methods, but since you are beginner.. you just call load data base $this->load->database() in that method just above the code where your database related query begins.. just suppose $this ->load->database(); is exactly the same thing for you as you were using include_once('connection.php') this script in you simple php script (without CI).
I'm having some trouble using CodeIgniters implementation of sessions getting deleted after a redirect so I'm reverting to normal PHP sessions.
Where would the best place for session_start(); be, assuming I want it called on every page without adding it to every controller constructor?
I'd guess putting it at the top of main index.php would be would work ok, would just like to make sure that doing this doesn't break anything or if there's a better/standard place to put it?
This is why I always use an extended controller that contains application wide code.
To extend the codeigniter controller, place this code in a file called MY_Controller.php and save it to the core folder.
class MY_Controller extends CI_Controller
{
public function __construct()
{
parent::__construct();
session_start();
}
}
If you decide to use this solution all your controllers will need to extend MY_Controller.
Creating Core System Classes
YOu can easily put them in index.php. THis is the entry point to your codeigniter application and is called on every request.
although this is generally not recommended becuase when you upgrade your codeigniter versions you will need to remember to copy your customizations to index.php.
instead of index.php, you could use a prerequest hook
You cannot use session_start(); directly in codeigniter.
Instead you must use:
$this->library->load('session');
$this->session->set_userdata(array('name' => 'name','age' =>
'age','etc' => 'etc');
I am trying to include a small code in each page of my site.
Is there any way to do this without modifying each controller?
For example - I want to read/unread message from Message model.
Can i do this using the app_controller? I have add following function in app_controller.php.
I need suggestion. Please help me.
function messageStatus() {
App::import('Model','Message');
$new_message = $this->Message->find(
'first',
array (
'conditions' => array (
'Message.status' => '1'
)
)
);
$this->set("new_message",$new_message);
}
Depending on when you want to execute your actions, you will have to override in the app_controller.php file one of the following functions (according to the documentation), :
beforeFilter()
afterFilter()
beforeRender()
Since all your other controllers will be inheriting the methods of this class, your actions will be executed every time (as specified in the docs) one of your controllers are executed.
If you want to have a controller that does not run the code in the app_controller simply override the method again locally.
As user559744 mentioned you can use AppController within your application to create attributes and methods that can be accessed by your controllers. AppController is the parent class of your controllers.
You should copy app_controller.php from /cake/libs/controller/ to YOURAPP/app_controller.php to avoid making changes to the core files.
http://book.cakephp.org/view/957/The-App-Controller