How to get rid of &get_instance() in Codeigniter - php

I have been using CI for two years now. One thing that really annoys me is the use of &get_instance(). Although it is halpful while we are inside library , helper , presenters , model etc. But everytime loading it is cumborsome. If you forget loading it somewhere and simply use $this->blah->blah() instead of $CI->blah->blah() this makes too much trouble and if you are working online you face the client who is complaining that he sees the error. I have seen in the laravel that you does not need to load the instance anywhere throughout the application. This is because laravel is autoloading all the libraries and models and both are available anywhere in the application. But this seems to me disadvantage why loading classes that are not required in some particular places. This tells me Codeigniter is flexible but still i want an alternative where i dont want to use &get_instance(). Any idea or suggestion ? Please.

In your model or Core model or library
//class MY_Model extends CI_Model
//class SomeLibrary
class Some_model extends CI_Model {
private $_CI;
public function __construct() {
parent::__construct(); //for model or core model
$this->_CI =& get_instance();
}
//if you called attributs who does not exist in that class or parent class
public function __get($key)
{
return $this->_CI->$key;
}
//if you called methods who does not exist in that class or parent class
public function __call($method, $arguments)
{
call_user_func_array(array($this->_CI, $method), $arguments );
}
public function test() {
var_dump($this->some_controller_key);
var_dump($this->some_lib_loaded);
}
}
*NOT TESTED YET
Inspired by an piece of code from the awesome Flexi Auth
//from a Model to keep access of CI_Controller attributs
public function &__get($key)
{
$CI =& get_instance();
return $CI->$key;
}
I was shocked when I saw that ^^
To explain the &__get, i think when you will call this magic method a second time PHP will do not execute it again, but will take his result from the first call.

Related

Codeigniter, why do I need CI_Controller's construct?(code below)

Why do I need to use the parent::__construct(); constructor, what does it have I need?
//CONTROLLER
class users_ctrl extends CI_Controller {
function __construct() {
parent::__construct(); //Why do I need to include it?
$this->load->model('select_model');
}
public function index()
{
$data['user_list'] = $this->select_model->get_all_users();
$this->load->view('show_users', $data);
}
}
//MODEL
class select_model extends CI_Model{
function __construct() {
parent::__construct();
}
function get_all_users()
{
$query = $this->db->get('students');
return $query->result();
}
}
In your given examples, you are calling the load class that the base controller class loads. Without the parent's constructor, you would have to load an instance of it yourself.
As for your model, you would have to manually load your db object.
Remove it and you should get something like called to undefined propery $class::load
CodeIgniter aside, it really is a basic fundamental of object-oriented programming.
If you make a class that extends another, and you declare a new constructor in the child class, the parent constructor will never run - since you've overridden it, and since CodeIgniter base controller does (most likely) a lot of things behind the scenes, if you do not run parent constructor, your controller most likely won't be injected in CI's container.

what is $this->load->view() in CodeIgniter

$this is use for current class and view is method but what is load. Is this a property?
Is this example correct?
class super{
public $property;
public function superf1()
{
echo "hello";
}
public function col()
{
$this->superf1();
}
$this->property->super1();
}
Yes, load is a property.
Think of it like this:
class Loader {
public function view() {
//code...
}
}
class MyClass {
private $load;
public __constructor() {
$this->load = new Loader();
}
public someMethod() {
$this->load->view();
}
}
This syntax is called chaining.
Your controller inherits CI_Controller. So, if you look in application/system/core/Controller.php you'll find something interesting : $this->load =& load_class('Loader', 'core'); (l.50 with CI2). So, $this->load refer to the file application/system/core/Loader.php which have a function public function view (l.418 with CI2)
In the context of a class that extends CI_Controller (in other words: a controller) the symbol $this is the Codeigniter "super object". Which is, more or less, the central object for CI sites and contains (among other things) a list of loaded classes. load is one of the classes you'll always find there because it is automatically loaded by the CI system.
Technically, the class creates objects of the type CI_Loader. view() is just one of the many methods in the load class. Other commonly used class methods are model(), library(), config(), helper(), and database(). There are others.
So, in short, load is a class used to load other resources.
load is a class belongs to the loader class
codeigniter official documentation
view, model and others are methods
In PHP 8.1
use return("viewname", $data)

Accessing CI features on non-CI class

So for example, i want to access config on CI from my class library.
Class A {
funcion x() {
$this->config->load('my_config'); // accessing my_config
}
}
that obviously won't work unless you extends and then call parent::__construct().
As far as i know, it can only be done from classes that extend CI_Controller or CI_Model. How to access CI stuff (config, helper, model, etc) on non-CI class ?
Thanks.
How about initiating the class from the construct?
include ("CI_Page.php");
class A {
protected $_CIInstance1;
protected $_CIInstance2;
public function __construct(){
$this->_CIInstance1 = new xxxx();
$this->_CIInstance2 = new yyyy();
}
public function x(){
$this->_CIInstance1->load('my_config');
}
}
You probably want to access the instance of CI as if it were the super variable, $this. In reality what you need is the ability to access the same functionality as $this and in order to do this, you'll need to use $CI =& get_instance();
You can find it directly in the documentation for Creating Libraries

Using CodeIgniter libraries through static methods

I am having trouble trying to call CodeIgniter methods in my static functions, just using $this doesn't work because its not in object context, the static keyword doesn't work either. This an example of the code in my core model, the $table variable is successfully defined from another model like posts.
class MY_Model extends CI_Model {
protected static $table;
public function __construct() {
parent::__construct();
}
public static function find_all() {
$this->db->select('*');
$sql = $this->db->get(static::$table);
return $sql->result();
}
}
If $this doesn't work you can get around this like this:
$CI =& get_instance();
$CI->db->...
The codeigniter built in loader class automatically instantiates the class. There is no support to use classes without instantiating. You can manually include your file in the model file then you can use it. For more details check out this thread:
http://codeigniter.com/forums/viewthread/73583/
What you want is a refence to the static var in the class, so use:
class MY_Model extends CI_Model {
protected static $table;
public function __construct() {
parent::__construct();
}
public static function find_all() {
$this->db->select('*');
$sql = $this->db->get(self::$table);
return $sql->result();
}
}
And, of course, $table does need to have a value!
Codeigniter doesn't generally support static methods I believe and they are really an attempt to shoehorn procedural code into object oriented code.
Anyway, I think your best bet is to either use the class without static methods, or turn your code into a "helper". A helper is just an old school function library. You would create it under the helpers folder and it can be loaded with $this->load->helper('helper_name'). You can then call the function as in normal procedural code, in other words 'find_all()'
Hope this helps.
First time contributor :)

Why are two controller methods being called in CodeIgniter?

Should I not be using Index as the name for a controller class in CodeIgniter? I have an Index controller, and I'm seeing its methods being called multiple times. More specifically, I always see its index method called first, whether or not I'm visiting a path that should be routed there.
In application/controllers/index.php
class Index extends CI_Controller
{
public function index()
{
echo "index";
}
public function blah()
{
echo "blah";
}
}
When I visit index/blah, I see indexblah printed. When I visit index/index, I see indexindex. If I rename the controller to something else (e.g. Foo), it doesn't have a problem. That's the obvious workaround, but can anyone tell me why this is happening? Should I report this as a bug to CodeIgniter?
(Notes: I have no routes set up in configs/routes.php; my index.php is outside the CodeIgniter tree)
To further clarify what the issue is, in PHP4 Constructors were a function that had the same name as the Class...
example
class MyClass
{
public function MyClass()
{
// as a constructor, this function is called every
// time a new "MyClass" object is created
}
}
Now for the PHP5 version (Which codeigniter now, as of 2.0.x, holds as a system requirement)
class MyClass
{
public function __construct()
{
// as a constructor, this function is called every
// time a new "MyClass" object is created
}
}
So To answer the question that addresses the problem...
Should I not be using Index as the name for a controller class in CodeIgniter?
I believe it would be best to not choose Index as a controller name as the index() function has a reserved use in codeigniter. This could cause issues depending on your PHP configuration.
can anyone tell me why this is happening?
When your controller get's instantiated, index as the constructor is getting called.
Compare Constructors and DestructorsDocs:
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class . [highlighting by me]
In your case your Controller does not have any __construct() function but a function that has the same name as the class: index. It is getting called in the moment Codeigniter resolves and loads and then instantiates your Index Controller.
You can solve this by just adding the constructor to your Controller:
class Index extends CI_Controller
{
public function __construct() {}
public function index()
{
echo "index";
}
public function blah()
{
echo "blah";
}
}
After this change, it does not happen again.
Should I report this as a bug to CodeIgniter?
No, there is not really a need to report this as a bug, it's how the language work and as Codeigniter supports PHP 4 it must remain backwards compatible and needs to offer PHP 4 constructors. (Note: The Codeigniter project documents, they need server support for PHP version 5.1.6 or newer, but the actual code has PHP 4 compatiblity build in, I'm referring to the codebase here, not the documentation.)
Here is another solution using Codeigniter3
require_once 'Base.php';
class Index extends Base
{
public function __construct()
{
parent::index();
$classname=$this->router->fetch_class();
$actioname=$this->router->fetch_method();
if($actioname=='index' || $actioname == '')
{
$this->viewall();
}
}
}
And the viewall() had the following
$this->siteinfo['site_title'].=' | Welcome';
$this->load->view('templates/header', $this->siteinfo);
$this->load->view('templates/menu', $this->siteinfo);
$this->load->view('index/viewall', $data);
$this->load->view('templates/footer', $this->siteinfo);
The Base controller does all the library and helper loading for the entire application which is why it is being required in the default class
Basically from my short understanding of CodeIgniter, having a default action as index is a wrong. I found this out by using the printing the result of $this->router->fetch_method(); in the construct() of my index class. The default action by CodeIgniter is index, you may only set the default controller within application/config/routes.php and not the default action.
So my advice, never use index() as the default action especially if you are using index as the default controller

Categories