Problem regarding use of constructors in PHP - php

My problem is in using Codeigniter custom library but I think it is not specific to that and more related to use of constructors in PHP.
I am trying to create a custom controller library in Codeigniter like this...
class MY_Controller extends Controller {
var $data = array();
function MY_Controller() {
parent::Controller();
$this->data['err'] = 'no';
$this->load->helper('utilities');
}
}
Now I create a codeigniter controller class like this...
class api_controller extends MY_Controller {
function get_data() {
$this->data['view'] = "data";
$this->load->view("data_view", $this->data);
}
function get_xml() {
$this->data['part'] = "xml";
$this->load->view("data_view", $this->data);
}
}
I want to ask that if the controller class extending the MY_Controller is instantiated when I access urls like api_controller/get_data and api_controller/get_xml, does the constructor of parent class always get called upon, i.e., MY_Controller() is always called.
Am I correct in inferring the following
get_data() called
-> $data => array ('err' => 'no', 'view' => 'data')
get_xml() called
-> $data => array ('err' => 'no', 'part' => 'xml')

Your code looks like it's using the PHP4 syntax for constructors. You should switch to the PHP5 syntax.
PHP4:
class MyClassName {
function MyClassName() {...} //constructor.
}
PHP5:
class MyClassName {
function __construct() {...} //constructor.
}
You can then call the constructor of a parent class by calling parent::__constructor(); from within the child class's __constructor() method:
class MyClassName extends SomeOtherClass {
function __construct() {
//...code here runs before the parent constructor.
parent::__construct();
//...code here runs after the parent constructor.
}
}

For PHP in general the parent constructor is not called default if the child has a constructor.
Constructors. It can be called using parent::_construct();
If you're using php 5+ you should go with the new recommended style of using function __construct() instead of the old style with a function named the same as a class.
As for CI-specific stuff I can't help you, sorry!

If you do not override __construct() in MY_Controller then Controller's __construct() will get run.
If you override it and then called parent::__construct() then it will run your own and the parent's.
So if you wanted it to run the parent's and your own you would do this
class MY_Controller extends Controller
{
var $data = array();
function __construct()
{
parent::__construct();
// Your code here
}
}

Yes, the parent constructor it is always called (you may want to rewrite them as __construct() however, thinking also at codeigniter 2.0 ).
If you really are in doubt toss in it an echo and see it for yourself.
Also the $this->data part is correct to me

You are right in your affirmations about the data array contents. In you code you wrote:
function MY_Controller() {
parent::Controller();
so the parents's class constructor is being called. There are lots of comments about PHP4 and PHP5 syntax, but basically everithing is ok.
In your question you wrote
that if the controller class extending the MY_Controller is instantiated
that is not correct. The instance is an object of class api_controller, calling the MY_Controller constructor is made using the same object. That is not the same, that is basic for polimorphism.

class Blog extends CI_Controller {
public function __construct()
{
parent::__construct();
// Your own constructor code
}
}

Related

What means every word of the string $this->load->model('name_model') in codeigniter?

What exactly means every part in string $this->load->model in codeigniter? In the code below "$this" makes reference to the User class(controller)? Also, does it invoke the method load that invokes model? Or does $this make reference to the name of every function where is put?
<?php
class User extends CI_Controller {
function __construct()
{
parent::__construct();
$this->template->set_layout('adminLayout.php');
$this->load->model("User_model");
$this->load->Model('Auth_model');
}
function index()
{
$this->Auth_model->isLoggedIn();
$this->template->title('Admin ::');
$this->template->build('admin/index');
}
?>
$this refers to the class you are in.
$this isn't something from CodeIgniter, but from PHP. $this refers to the current object.
models are build usually to handle all database relations so basically the line
$this->load->model("User_model");
Says "Load the model "name of model" so we can use it.
Whenever you create a class
$something = new SomeClass();
Then $this refers to the instance that is created from SomeClass, in this case $something. Whenever you are in the class itself, you can use $this to refer to this instance. So:
class SomeClass {
public $stuff = 'Some stuff';
public function doStuff()
{
$this->stuff;
}
}
$this refers to global CodeIgniter object. If you var_dump($this) in constructor or in called method, you will see all invoked and initialized code. You can track changes in way that you could load some library, helper, method, language, package or config or anything else allowed by Loader.php class of framework. You will get similar output to outputting get_instance() function.
That contstruction uses load() method of Config.php core system file you could check with start on line 119. Model in line means type of file need to be loaded.
Basically it is refered to load method of Config class that act on needed Loader class methods (model, helper etc).
That means you are loading models(User_model and Auth_model) so you can use the functions which are inside those models.
For example: if you have Auth_model as follow
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Auth_model extends CI_Model {
function __construct()
{
// Call the Model constructor
parent::__construct();
}
function insert_valid_val($valid_data)
{
//Write queries here and return some values.
}
Then in controller you can invoke the insert_valid_val() as follow.
<?php
class User extends CI_Controller {
function __construct()
{
parent::__construct();
$this->template->set_layout('adminLayout.php');
$this->load->model("User_model");
$this->load->Model('Auth_model');
}
function index()
{
$this->Auth_model->isLoggedIn();
$this->template->title('Admin ::');
$this->template->build('admin/index');
$returned_val = $this->Auth_model->insert_valid_val("send some array");
print_r($retunred_val);
}
?>

in magento use the method from parent class not the overriden class

is it possible in magento php to invoke the method from parent class rather than from the overridden one,
I have extension overrides (A_CustomOptions_Model_Catalog_Product_Option extends Mage_Catalog_Model_Product_Option) and it overrides the construct method and I have got another extension wants to use the construct of parent class Mage_Catalog_Model_Product_Option
is there a way to do this???
more explanation:
class A_CustomOptions_Model_Catalog_Product_Option extends Mage_Catalog_Model_Product_Option {
protected function _construct() {
parent::_construct();
$this->_init('customoptions/product_option');
}
}
in another extension i'm getting collection for options
public function getOptions($srcId) {
$options = Mage::getModel('catalog/product_option')
->getCollection()
->addTitleToResult(Mage::app()->getStore()->getId())
->addPriceToResult(Mage::app()->getStore()->getId())
->addProductToFilter($srcId)
->addValuesToResult();
return $options;
}
however because this parent class Mage_Catalog_Model_Product_Option is overridden, it doesn't return me the parent options not overridden ones
Thanks
yes you can call parent constructor with use of below code
class A_CustomOptions_Model_Catalog_Product_Option extends Mage_Catalog_Model_Product_Option
{
public function __construct()
{
parent::__construct();
}
}
As your updated answer i think override class loaded at the last that might be not work.
hope this will sure work for you in simple OOP concept,

Can't extend my Controller

I am trying to write an extension to my Controller class. The problem is I can't seem to figure out how..
I have the following class named test in which there is one function which simply returns aaaa and in in the same file, at the end, as my Controller:
class test extends Controller
{
function test()
{
parent::Controller();
}
function echoMe(){
return 'aaaaaaaaaaaaaaaaa';
}
}
Within my Controller class I have a function which is the general output for a clients homepage. I'm trying to call the function echoMe from the extension above, but I keep getting
Call to undefined method Controller::echoMe()
Here is the client function (the call to echoMe() is right at the top):
function controller_client1($controlData = NULL)
{
echo $this -> echoMe();
//as the client page is content from the xml, mmodel needs the page number
$pageNumber = '';
if(isset($_GET['number']))
{
$num = htmlentities($_GET['number']);
if(ctype_digit($num) && $num >= 0)
{
$pageNumber = $num;
}
}
else{
$pageNumber = 0;
}
//loading the page content
$data = $this->model->model_loadXMLdata($pageNumber);
if(!empty($controlData))
{
//check if there is any info in the control data sent
foreach($controlData as $key => $value)
{
//add the info to the data array
$data[$key] = $value;
}
}
$this->load->load_clientHomePage($data);
}
I know this is a very simple question. I've been trying to follow this guide, but something isn't clicking...
Could somebody please help? How can I call the function echoMe() from test?
I know how to write just a brand new class and call it, but I'm trying to learn how to extend properly and keep failing.
Am I meant to call the "test" from within the Controller somewhere?
In the config.php you set the prefix for the file you want to extend. So it should be My_test, unless you have changed this preset(displayed below)
/*
|--------------------------------------------------------------------------
| Class Extension Prefix
|--------------------------------------------------------------------------
|
| This item allows you to set the filename/classname prefix when extending
| native libraries. For more information please see the user guide:
|
| http://codeigniter.com/user_guide/general/core_classes.html
| http://codeigniter.com/user_guide/general/creating_libraries.html
|
*/
$config['subclass_prefix'] = 'MY_';
Make sure you have the controller in the right folder (application/core in codeigniter 2.1.0) then you shouldn't have a problem. Hope that helps
here is my controller that i extend. The file is called My_Controller.php (creative I know)
<?php
class MY_Controller extends CI_Controller {
function __construct()
{
parent::__construct();
//constructor code here
}
//Custom functions here
}
//sencond controller I extend in the same file
class MY_Admin extends CI_Controller {
function __construct()
{
//more custom stuff for admin stuff
}
//more custom functions for admin stuff
}
?>
Has you see I have two extended controllers in the same file.
My extending code looks like this:
<?php
class home extends MY_Controller
{
and then just replace My_Controller with My_Admin if I want to extend the admin.
echoMe() function is defined in test class and not in Controller class. When controller_client1 function is called with the instance of Controller class, echoMe does not exist because it is not defined within Controller class.
The best way to achieve this is to create empty echoMe function in base Controller class. This way polymorphism works. When calling controller_client1 function from instance of test class, method from that class will be executed. Otherwise, method from base class will be executed.
I hope I didn't miss the point of the question :)
echo $this -> echoMe(); will fail because its created in the child(extended) class and your calling it in the parent class. The question is a little hard to understand.
abstract class Controller{
public function __construct(){
}
public function echoMe($str){
echo $str;
}
}
class test extends Controller{
public function __construct(){
parent::echoMe('aaaaaaaaaa');
}
}
Try this (general idea, not CodeIgniter only):
$test = new test();
echo $test->echoMe();
Remember, test extends your Controller class, not the other way round - so you can't call your methods outside the test class/object instance.
Also, it might be a good idea to upgrade to a new version of CodeIgniter - beware of the new parent controller name, though.
EDIT
Ok, this should be enought to get you started - note that it's PHP5, not PHP4, so constructors are called __construct and not the class name:
class Controller {
public $mainvar;
function __construct() {
$this->mainvar = '<br />';
}
function echoMe() {
return 'aaaaaaaaaaaaaaaaa';
}
}
class Test extends Controller {
function __construct() {
parent::__construct();
}
function echoMeAgain(){
return 'bbb';
}
}
$test = new Test();
echo $test->echoMe();
echo $test->mainvar;
echo $test->echoMeAgain();
I think the question has actually already been answered by Kosta, but there might be some misunderstanding at your side. So let me extend that by some example code:
class Controller {
public function run() {
$this->echoMe();
}
}
class test extends Controller {
public function echoMe() {
echo "works";
}
}
// This does NOT work, because Controller::echoMe does not exist
$controller = new Controller();
$controller->run();
// This DOES work, because $this will be instance of test, and
// test::echoMe exists and is callable.
$test = new Test();
$test->run();
"extends" does not mean, that the actual Controller class gets extended. The new class "test" just inherits every single method and property that is not declared "private" from the Controller class. The Controller class itself remains untouched.

loading file on class construct

I'm working on a sql class, and trying to figure out how to retrieve data from an external php file, to be available in the entire class.
Im guesing i have to do something like this:
class sqlQuery {
protected $database = array();
function __construct(){
require_once (config.php);
}
}
class model extends sqlQuery {
function __construct() {
$this->connect($this->database['hostname'], $this->database['user'], $this->database['pass'], $this->database['database']);
}
}
The file might contain other information in the future, so I want it available to more then just the extended class.
Firstly you should call parent constructor in class model:
function __construct() {
parent::__construct();
// your other logic there
}
Then just change constructor of your parent class for filling $this->database array

Calling method X from each parent

what i'm trying to do is call each method "init" from current class's parents.
I'm doing that to avoid programmers to have to call init method (parent::init()) each time they create an init method in a new controller.
Example:
class Aspic\Controller { } // main controller
class ControllerA extends Aspic\Controller { public function init() {/* do something 1 */}
class ControllerB extends ControllerA {}
class ControllerC extends ControllerB { public function init() { /* do something 2 */ }
class ControllerD extends ControllerC {}
As you can see the init methods do not call parent init method but i want my app (there is an option) do it.
Thus when I'm loading ControllerD, before calling it's init method (there isn't in the example but the app test it), i want to call each parent init method.
sound like this:
parent::init(); // Controller C init
parent::parent::parent::init(); // Controller A init
So i did :
if($this->_autoCallParentsInit) {
// Aspic\Controller is the main controller, which is the mother of all others
$aspicControllerRc = new \ReflectionClass('Aspic\\Controller');
$rc = new \ReflectionClass($this); // We are in D
$currPrefix = '';
// Calling each init methods of current class parent
// Avoid using parent::init() in each controller
while(($parentClass = $rc->getParentClass()) AND $aspicControllerRc->isInstance($parentClass)) {
/*
$aspicControllerRc->isInstance($parentClass)
=> because Aspic\Controller extends a "Base class". Thus, we stopped at Aspic\Controller
*/
$currPrefix .= 'parent::';
// Must have explicit method (not inherited from parent) BUT actually hasMethod does not care
if($parentClass->hasMethod('init')) {
call_user_func($currPrefix.'init');
}
}
}
This is not working because ReflectionClass::isInstance does not accept others argument than the object we want to test (and the not a ReflectionClass object representing it as in the example)
**
Simply:
I have an object $x, and i want to call the init method of each parent of the class of $x.
**
Is it possible ?
I hope i was clear :)
Thanks
ControllerB has an init() method by virtue of extending ControllerA, so you shouldn't have to call parent::parent::init() to get to A's from C. You should be fine to call parent::init() from ControllerD, which will call ControllerC's init() method. If ControllerC calls parent::init() it will be calling ControllerA's init() method.
If you're trying to skip the Controller's specific init() code when being called by a subclass, you could add a flag function init($call_parent = false) and then, from lower controllers, call parent::init(true);
If you're not using the classes statically (which, from your code not stating static function, I assume you're not), have you tried using the __construct() method? It gets automatically called when you instantiate the class, for example:
class MyClass {
public function __construct() {
echo 'Hello!';
}
}
$class = new MyClass();
That will automatically output 'Hello!', however if you extend the class and that child class contains a __construct() method you will have to put parent::__construct() inside the childs construct method, however you wont have to do it for every parent, just the once, for example:
class MyClassB extends MyClass {
public function __construct() {
parent::__construct();
echo 'World!';
}
}
class MyOtherClass extends MyClassB
public function __construct() {
parent::__construct();
echo 'How\'s it going!';
}
}
$class = new MyOtherClass();
That will output "Hello! World! How's it going!"

Categories