Why is __constructor needed in codeigniter - php

Why does __constructor code needs to run in codeigniter controller and models ? Without those lines, the code is working fine. I am confused !
function __construct()
{
parent::__construct();
}

The reason behind for using the _construct(magic Function) is to load your library and helpers through the controllers, so that you don't have to load libraries and helpers in each of your functions.
Example:
function __construct() {
parent::__construct();
$this->load->library('someclass');
$this->load->helper('someclass');
}

It will work as long as the class from your controller/model does not need it's constructor method to be called. If the class from where it extends defines dependencies needed (for example), you may get unwanted results.
Even though the constructor method is a so called "magic method" and it will be called automatically when you use the new keyword (note that you have to use parenthesis):
$foo = new Foo();
This does not mean that the class from where Foo is extending will get it's constructor method called automatically.

Related

Why is a PHP class method called on instantiation?

Need some help understanding what's going on in my PHP code.
index.php
include("cache.php");
$cache = new Cache();
cache.php
class Cache {
private static $URL_CACHE;
public function cache($url, $entityId) {
echo '<br>caching '.$url.' as '.$entityId;
}
When I request index.php, I get 'caching as' displayed, which is a surprise. I never called $cache->cache('', '');
What's calling the method?
As per Blake's answer, since the method name matches (somewhat) the class name, it's called on instantiation. For Java developers this will certainly be a surprise.
This is using deprecated PHP functionality to act as a __contruct() method. In older versions of PHP (Removed in 7) If you had a class named Foo and a function named foo() it was how you would call it as a constructor.
In short, this is being called by you instantiating the class. If you change your cache() method to makeCache() I bet it will go away.
Another solution is to have an empty constructor as well, thanks JimL.
public function __construct() {
}

Tell a PHP Class to always run it's constructor when it is extended

From what I understand, when a PHP Class is extended, it's constructor is not called? So in the below, the method Options_Page_Template->on_enqueue_scripts() is never actually run -
class Options_Page_Template{
function __construct(){
/** Enqueue scrips and styles for use in this plugin */
add_action('wp_enqueue_scripts', array(&$this, 'on_enqueue_scripts'));
}
function on_enqueue_scripts(){
{ do Whatever here }
}
}
class Options_Home extends Options_Page_Template{
function __construct(){
{ Add various actions here }
}
}
Is there a way of telling Options_Page_Template() to always run it's own __constructor() when it is extended? I know I can use parent::__construct(), but that involves adding the code to all the files that extend the Class.
I also tried the the old-school method of giving the constructor the same name as the Class, but PHP is obviously more clever than that, as it did not work. Thanks.
There's no way. A good rule of thumb for all your code, is to always call parent::__construct for every subclass that overrides the constructor; and explicitly comment within the constructor if you are not, and why.
In general, for functions and con/destructors, if you override something; you are also responsible for calling the parent function.
You must always use parent::__construct() if you are createing a __construct in both classes You do have an option to turn it around. You could have your parent class constructor check for the existence of a custom constructor in the child and run it.
<?php
class Options_Page_Template{
function __construct(){
if (method_exists($this,'__beforeconstruct'))
$this->__beforeconstruct();
echo "construct class<br/>";
if (method_exists($this,'__afterconstruct'))
$this->__afterconstruct();
}
function on_enqueue_scripts(){
}
}
class Options_Home extends Options_Page_Template{
function __beforeconstruct(){
echo "Extended class before<br/>";
}
function __afterconstruct(){
echo "Extended class after<br/>";
}
}
new Options_Home();
?>
output:
Extended class before
construct class
Extended class after
You could do something nasty like define your constructor as final and have a protected init method which extended classes can override but I wouldn't recommend it to be honest.
This way if someone tries to write a constructor in a child class they'll get something like:
PHP Fatal error: Cannot override final method A::__construct() in php shell code on line 5
You probably need to look at a different approach to the way you've organised your classes instead.
class Options_Home extends Options_Page_Template{
function __construct() {
parent::__construct(); // Needs to be first line so the rest of the constructor
// can assume the Options_Page_Template has been constructed.
// Various stuff here for Options_home constructor
}
}
Should work.
Just don't define a constructor the for the extending class.

Can you explain how Zend's Action controller operating?

Sorry for constantly re-editing my question but looks like this is the only way to ask it properly.
My original problem is the following pseudo-code (a controller and it's parent) isn't working as i would like to:
class Parent {
var $data = array();
public function __construct( OtherClass $otherClass ) {
$this->data = $otherClass->getData(); //contains some => thing
$this->init($otherClass->getClassName());
}
public function init( $className ) {
new $className; //new Child
}
public function __get( $name ) {
return array_key_exists($name, $this->data) ? $this->data[$name] : null;
}
}
class Child extends Parent {
public function __construct() {
echo $this->some; //won't return 'thing';
}
}
fireeyedboy helped me a lot (thank you) and pointed out Zend_Controller_Action is doing what i want but i can't understand how they do it?
Original question
I know there was some similar questions here but i cannot dump them. Also i know i can reverse the whole process so i can initialize Child first then call parent::__construct but this seems unwanted for me. How can i access Parent variables easily in my case?
Update:
Let me clarify a little bit. Child is an arbitrary controller. Parent is the mother of all controllers. Many frameworks are doing the same but controllers can utilize their parent controllers variables, methods or objects without calling parent::__construct (and therefore filling child class constructors with unnecessary arguments). I don't like to rewrite any of these frameworks but i'd like to understand how they're operating.
Your child class doesn't call parent constructor. Here's a fix:
class Child extends Parent {
public function __construct() {
parent::__construct();
echo $this->some;
}
}
Update: Parent classes' constructors aren't called automatically in PHP. See the documentation:
Note: Parent constructors are not
called implicitly if the child class
defines a constructor. In order to run
a parent constructor, a call to
parent::__construct() within the child
constructor is required.
So what you're asking does not happen. Either you have misinterpreted the class structure or how they operate. Note that PHP also supports legacy constructor naming (at least until 5.3.3): If there is no __construct() method in a class, PHP assumes the constructor is named after the class (ie. class Foo { function Foo() {}) treats the Foo() method as constructor).
Injecting ANYTHING using controller's construct is generally a BAD PRACTICE! Problem lies in your design. What kind of object is OtherClass? Is it DB adapter? Is it ACL? Is it some helper class?
If you need external class in your controller I suggest using action helpers. That's what they are created for ;) Or create an action helper that will fetch this OtherClass from somewhere when needed.
You should NEVER use __construct() to do any of your dirty work. That's what init() is used for. But it has no params. And there is a reason for that - again - you should not inject dependencies like this ;)
Update:
Note your class uses discouraged PHP4 member variable definition syntax. Try replacing your var with protected.
The problem is that your Child class does not call the base constructor.
Incidentally, Parent is not a valid class name in PHP. I have changed the class names for clarity. See below:
class ChildClass extends ParentClass {
public function __construct() {
parent::__construct(/* what goes here? */);
echo $this->some;
}
}
However, note the what goes here? part: your base class requires a reference to an OtherClass instance to be constructed. Therefore, since ChildClass IS-A ParentClass, it also needs to get such an instance somehow. You will need to either add a parameter to ChildClass::__construct and forward the value to parent::__construct, or somehow figure out a default value yourself.

__construct() vs method with same name as class

I have recently started php and was wondering the differences between __construct() and having a method with the same name as the class?
Is there a reason for using it? All I can work out is it overrides the method named Foo or is it down to which you prefer?
E.g.
class Foo {
function Foo()
{
echo 'Foo stated<br>';
}
function __construct() {
echo 'Construct started<br>';
}
}
Thanks
Using __construct() is the newer PHP5 more OOP focused method to call a constructor. Using a method with the same name as the class is the old deprecated way to do it, and it will not function as a constructor as of PHP 5.3.3 for namespaced classes.
From the constructors and destructors page:
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. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.
Unlike with other methods, PHP will not generate an E_STRICT level error message when __construct() is overridden with different parameters than the parent __construct() method has.
As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.
"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. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics."
Source: http://www.php.net/manual/en/language.oop5.decon.php
Foo() is a php4 way(deprecated), __construct() is php5 way. php will first look for __construct, then, if it's not found, it will use Foo
Is there a reason for using it? All I
can work out is it overrides the
method named Foo or is it down to
which you prefer?
The benefits of __construct() become clearer when you involve renaming and inheritance. If you rename a class, you then have to rename it's constructor. No big deal, but if class B inherits from class A you could end up with:
class B extends A {
function B() {
parent::A();
}
}
It's much easier and more maintainable to do:
function __construct() {
parent::__construct();
}
Now when you rename class A, you don't have to remember to also change the parent calls in all its children. Granted, there's still renaming to do in your code but at least this is not one of them.
Having a method with the same name as the class, which is automatically called as a constructor is a throwback to PHP4, and is to be considered deprecated... in the latest development branch of PHP, it will be treated as a normal class method. __construct is the formally accepted constructor in PHP5, although in current releases it will fall back to the PHP4 method if __construct doesn't exist.

Accessing database from bootstrap.php in CakePHP

Is there any standard method of accessing the database in the bootstrap.php file with CakePHP?
Specifically I want to set "putenv()" to a time zone that's stored in the database. Is there another way of achieving the same thing that I should be using instead?
Thanks.
I don't think it's a good idea to access database in bootstrap. You cannot use models because they haven't yet been initialized. I think that you could extract the connection data and initialize connection and run queries using PHP's mysql_* but that's an ugly thing.
However if you need to run certain action everytime your app is accessed I would suggest placing it in AppController constructor (__construct function).
class AppController extends Controller {
public function __construct() {
// do your magic here
// call parent constructor
parent :: __constructor();
}
}
class YourSpecificController extends AppController {
public function __construct() {
// call parent contructor (this) will cause your magic happen
parent :: __constructor();
// extra controller initialization instructions
}
}
If you don't declare constructor in extending class you won't even have to change anything since PHP will automatically call parent (AppController) constructor.

Categories