Trying to access an object in a class extended from another class - php

I'm Trying to access an object in a class extended from another class. But I'm getting the error "Trying to get property of non-object".
This is the code: http://3v4l.org/ZLTWf#v500
why can i not access the $doo->var_2->var? i works fine with $foo->var_2->var (as it should) but why do i get an error when i extend the class? Is it allowed in PHP? Is there some extra code that will allow me to do that?
I'm even getting an "Undefined variable" error on $doo->$var_3

Problem is here
class TheClass extends SecondClass{
public $var_3;
function __construct(){
$this->var_3 = "Some Text...";
}
}
You have overwritten the parent constructor so when you instantiate the class the constructor of its parent will not be called since its overwritten.
You can fix it as
class TheClass extends SecondClass{
public $var_3;
function __construct(){
parent::__construct();
$this->var_3 = "Some Text...";
}
}

Related

classes interaction methods php

Lets say we have class B which extends class A. When creating new instance of class B and providing value into it that value is used in constructor of class A. Please check sample below.
I'm little bit confused about such behavior. If method "display" do not pass value into class A it should not get there, or am i missing something?
class A {
protected $changeableString = 'initial value';
public function __construct($providedText)
{
$this->changeableString = $providedText;
}
public function printString(){
echo $this->changeableString;
}
}
class B extends A {
public function display(){
echo $this->changeableString;
}
}
$test = new B('provided value');
$test->display();
edit: I have changed function __construct from protected to public according comments. It is indeed gives error, so if someone will review this issue now code is correct.
First of all the topic you are talking about is called Inheritance in Object-Oriented Programming (OOP).
If class B has no construct (__construct) then PHP will call the construct of class A.
And about display function, think of it as an addition to everything in class A but will not be available in class A
So class B is like class A but has one more function called display.
Note:
As #Brian said, if you try to call new B('provided value') that will produce the following error:
Fatal error: Uncaught Error: Call to protected A::__construct() from global scope in ..
and to solve it just make the construct of class A public so class B.

Unexpected inheritance behavior of php code

I've written this code for check behavior of my app and i don't why this code works. I have 2 classes and 1 entry point
PHP 7.2
class Base{
public function check(){
return $this->checkUnexist();
}
}
class Main extends Base
{
public function checkUnexist()
{
return 'UNEXIST METHOD CALLED';
}
}
$main = new Main();
echo $main->check();
Expected result something like called method unexist. But it calls method from child class with "this". Why? And where i can read about this issue ?
Trying to access child values from base(parent) class is a bad design. What if in the future someone will create another class based on your parent class, forget to create that specific property you are trying to access in your parent class?
As per my understanding, When you extend the class the child class have all the property, methods available for the Main class object, which are accessible outside the class.
So when you created an object of Main class your class internally looks like
class Main
{
public function checkUnexist()
{
return 'UNEXIST METHOD CALLED';
}
public function check(){
return $this->checkUnexist();
}
}
the check method exists and you will get the response. Try to make the method checkUnexist private or protected you will see the difference.

extended class constructor not fired when child class is called using call_user_func_array

I have a quite strange issue and I don't know if this is due to call_user_func_array or not.
Testing on PHP 5.4
Current setup
I have, for example, an AuthController class that extends a base controller named Controller:
class AuthController extends Controller
{
public function login() {
return Response::json(array('error' => false, 'message' => 'I\'m in AuthController#login'));
}
}
In the extended Controller class, I have a constructor that sets up, for example, a database connection (I have a var_dump + exit added for testing purposes):
class Controller
{
protected $db;
protected function __construct() {
$database = Config::env('database');
var_dump($database);
exit;
}
}
Now to call the AuthController, I'm using call_user_func_array
call_user_func_array(array($controller, $route['action']), $data);
Now what should have happened:
What should have happened is that Controller's constructor should have fired, produced a dump on screen and exited the execution.
Instead:
Instead I'm actually getting the response from AuthController's login method Response::json().
The Controller's constructor never gets fired.
I am having a difficult time understanding why it doesn't work since the PHP manual states that constructors get fired on every new object instance and if a parent class has a constructor and the child class doesn't overwrite it, the parent class constructor is called automatically.
Does call_user_func_array not fire parent class constructors autmatically or have I misunderstood something about PHP constructor entirely?
I'll take a stab in the dark here, and say that you're actually doing this:
call_user_func_array(array('AuthController', 'login'), $data);
In other words, you're not passing an instance to call_user_func, you're just passing the string 'AuthController'. That means your method will get called statically. If you had error reporting and/or strict error reporting enabled, you should see a notice warning you about calling non-static methods statically.
The problem is (probably) that you're never actually instantiating your class, so no constructor is ever run. call_user_func won't instantiate it for you. You'll need to do that yourself:
call_user_func_array(array(new $controller, $route['action']), $data);
// ^^^
As PHP Document at http://php.net/manual/en/language.oop5.decon.php
PHP 5 allows developers to declare constructor methods for classes. Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.
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. If the child does not define a constructor then it may be inherited from the parent class just like a normal class method (if it was not declared as private).
Example #1 using new unified constructors
<?php
class BaseClass {
function __construct() {
print "In BaseClass constructor\n";
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "In SubClass constructor\n";
}
}
class OtherSubClass extends BaseClass {
// inherits BaseClass's constructor
}
// In BaseClass constructor
$obj = new BaseClass();
// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();
// In BaseClass constructor
$obj = new OtherSubClass();
?>
Hope this will explain you about use of parent class constructor in child class.
also you can refere http://php.net/manual/en/function.call-user-func-array.php , here they mentioned how to call parent class function in call_user_func_array.
Example:
call_user_func_array(array($this, 'parent::__construct'), $args);
Edit 1
See below example:
class BaseClass {
protected function __construct() {
print "In BaseClass constructor<br />";
}
}
//class SubClass extends BaseClass {
// function __construct() {
// parent::__construct();
// print "In SubClass constructor<br />";
// }
//}
class OtherSubClass extends BaseClass {
// inherits BaseClass's constructor
function test(){
echo 'in test';
}
}
call_user_func_array(array('OtherSubClass', 'test'), array()); //
// In BaseClass constructor
$obj = new OtherSubClass(); //produce fatel error
output:
Strict Standards: call_user_func_array() expects parameter 1 to be a valid callback, non-static method OtherSubClass::test() should not be called statically in /var/www/html/test/test1.php on line 22
in test
Fatal error: Call to protected BaseClass::__construct() from invalid context in /var/www/html/test/test1.php on line 24
So if string give in call_user_func_array function then it is producing out put but with strict standard error, and while creating new object of the class producing fatal error.
Remember that the constructor is a special method called when a new object is created. call_user_func_array() does not call any constructor because it doesn't create any new object.
call_user_func_array(array($controller, $route['action']), $data);
From your question I assume $controller is an object of type AuthController. It is already created at the moment when you pass it to call_user_func_array(). It's constructor was called when the object was created.
But wait a minute? What constructor? The class AuthController doesn't define any constructor. It inherits the parent class constructor that is protected. Because it is not public it cannot be called and the object is not created; the script throws a fatal error and exits.
You can either change the visibility of Controller::__construct() to public (this way both classes can be instantiated and the constructor of Controller runs for both). Or, if you want to keep class Controller not instantiable for some reason you define a public constructor for class AuthController that calls the protected constructor of class Controller to do the job:
class AuthController extends Controller
{
public function __construct()
{
parent::__construct();
}
// other methods here...
}

why do we still need parent constructor when controller class extends a parent controller?

I'm a beginner in CodeIgniter and OOP. I was reading a page of CI tutorial here. I found something that made a question in my mind.
Look at this code:
<?php
class News extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('news_model');
}
I think if we made a class that extends CI_Controller, we assume it must have all methods and properties in its parent class (Although we can override them). So, why there is parent::__construct(); in the code?
__construct() is the constructor method of a class. It runs if you declare a new object instance from it. However, if a class implemented its own __construct(), PHP would only run the constructor of itself, not of its parent. For example:
<?php
class A {
public function __construct() {
echo "run A's constructor\n";
}
}
class B extends A {
public function __construct() {
echo "run B's constructor\n";
}
}
// only B's constructor is invoked
// show "run B's constructor\n" only
$obj = new B();
?>
In this case, if you need to run class A's constructor when $obj is declared, you'll need to use parent::__construct():
<?php
class A {
public function __construct() {
echo "run A's constructor\n";
}
}
class B extends A {
public function __construct() {
parent::__construct();
echo "run B's constructor\n";
}
}
// both constructors of A and B are invoked
// 1. show "run A's constructor\n"
// 2. show "run B's constructor\n"
$obj = new B();
?>
In CodeIgniter's case, that line runs the constructor in CI_Controller. That constructor method should have helped your controller codes in some way. And you'd just want it to do everythings for you.
To answer your question directly from the Code Iginiter documentation:
The reason this line is necessary is because your local constructor will be overriding the one in the parent controller class so we need to manually call it.
http://ellislab.com/codeigniter/user-guide/general/controllers.html#constructors
Extension used for all classes.
__construct() used for that class that you use.
Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.
I believe the need of calling the parent constructor/method is a code smell, known as Call super. Besides the error-sensitivity (forgetting this call, you can get unexpected results), it's procedural instead of OOP. After all, the order of statements can lead to unexpected results too.
Read more here: https://martinfowler.com/bliki/CallSuper.html
Inheritance is being used via the keyword extends. The parent class could be setting some values when its constructor is being called. If the parent constructor is not called the values are not set and the child class will not get those values.
Example:
class Super {
protected $a;
public function __construct(){
$this->a = 'Foo';
}
}
class Child extends Super{
protected $b = 'Bar';
public function __construct() {
parent::__construct();
echo $this->a;
}
}
$x = new Child();
Here, the class Child would echo out nothing if the parent constructor was not called.
So in Codeigniter the parent class is probably setting some values that are of help to its children when you call its constructor and those values are only available to its children if the parent constructor is called.

'Fatal error call to private method' but method is protected

First time extending a class in PHP and I'm getting a fatal error that says the method is private when it's not. I'm sure it's something elementary, but I've studied books and forums, and I just can't pin down what I've done to generate this error. Any help greatly appreciated. Details below:
Error message:
Fatal error: Call to private method testgiver::dbConnect() from context 'testprinter' in /root/includes/classes/testprinter.php on line 726
Line 726 of testprinter in the code below:
private function buildquestionarray()
{
$query = "etc etc";
**$conn = $this->dbConnect('read');
$result = $conn->query($query);
...
Testprinter extends testgiver. Here's the extension of the class:
require_once('testgiver.php');
class testprinter extends testgiver
{...
And the declaration of the method in testgiver:
protected function dbConnect($userconnecttype)
{...
Thanks again!
As already Alexander Larikov said that you can't access protected methods from class instance but not only protected methods but also you can't access private methods from class instance. To access a protected method of a parent class from the instance of a subclass you declare a public method in the subclass and then call the protected method of the parent class from the public method of the subclass, i.e.
class testgiver{
protected function dbConnect($userconnecttype)
{
echo "dbConnect called with the argument ".$userconnecttype ."!";
}
}
class testprinter extends testgiver
{
public function buildquestionarray() // public instead of private so you can call it from the class instance
{
$this->dbConnect('read');
}
}
$tp=new testprinter();
$tp->buildquestionarray(); // output: dbConnect called with the argument read!
DEMO.
You can't access protected methods from class instance. Read documentation which says Members declared protected can be accessed only within the class itself and by inherited and parent classes
The Alpha, great write-up!
I feel like I've almost got it where I want it, but am getting
Fatal Error, call to undefined method NameofClass::myFunction() in line 123456
Is there something I am missing here?
My original class, and the extending class are both in the same .php file, but the call to myFunction is happening in a different file. Is that not allowed?
NOTE: I would put this in a comment, but the system won't let me include comments until I have a reputation of 50.

Categories