PHP cannot access protected property error - php

I can't see anything wrong with this, but I see the above exception occasionally in the logs. What's wrong?
PHP Fatal error: Cannot access protected property Exception::$message in /web/index.php on line 23
On line 23 I have,
echo '<?xml version=\'1.0\'?><error-response status="error">
<message><![CDATA['.$e->message.']]></message>
</error-response>';

Use $e->getMessage() instead of $e->message because message is a protected property :)

$message is a protected member of class Exception, as the error message states. You want the public accessor getMessage:
$e->getMessage()

Members declared protected can be accessed only within the class itself and by inherited and parent classes.
class MyClass {
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private
You can dig more into Property Visibility here

Related

PHP private accessor

I made a private variable in my class with a set and get functions but I keep on getting the following error:
Fatal error: Uncaught Error: Cannot access private property Car::$make
in C:\xampp\htdocs\PhpOOP\index.php:16 Stack trace: #0 {main} thrown
in C:\xampp\htdocs\PhpOOP\index.php on line 16
When I change it from private to public it works fine.
Here is my class:
<?php
class Car {
private $make;
public $model;
public $color;
public function starting(){
echo "Car Starting";
}
public function setMake($make){
$this->make = $make;
}
public function getMake(): string{
return $this->make;
}
}
And here is where I am creating an instance of the class and trying to use my methods.
<body>
<?php
include "classes/Car.php";
$car1->setMake("Honda");
echo $car1->getMake();
?>
</body>
You are not instantiating your class variable. You are including your class file, but you then need to instantiate the class
<body>
<?php
include "classes/Car.php";
$car1 = new Car();
$car1->setMake("Honda");
echo $car1->getMake();
?>
</body>
Fixed I was progressively learning objects in php. Was accessing the private variable when it was public. Then I turned it private to see how that worked. And my old code that was accessing it was causing the problem not the new stuff with the set and get methods.

OOP visibility in PHP

I have recently started OOP in PHP and I am on visibility concept (public, protected, private). Here I'm confused about protected visibility. Protected members can only be accessible within the declaring clas or a subclass or child class. I have this example on PHP's site:
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->protected; // Fatal Error
echo $obj2->private; // Undefined
$obj2->printHello(); // Shows Public, Protected2, Undefined
In this code in the third last line (echo $obj2->protected; // Fatal Error) it gives fatal error. But isn't protected variable inherited into child class which is MyClass2 in this case? So why this fatal error? Can someone please enlighten me about this?
Protected members can only be accessible within the declaring class or
a subclass or child class.
You must pay attention to the within.
You're getting the fatal error because you're accessing $protected from outside both MyClass2 and MyClass.
Within means that you can access it from MyClass2 like you're doing on MyClass2::printHello() and/or MyClass::printHello() methods.

PHP change method/function visibility

I am trying to write a PHP class in which I change the visibility of a few methods from protected to public. I believe I remember you can do this in C++, but I did a few searches and I am not coming up with anything for that in PHP. Does anyone know if this is even possible in PHP?
For example, suppose this class:
class ABC {
protected function foo() {
// Do something
}
}
class DEG extends ABC {
// can I make foo public now?
}
You can change the visibility of members when deriving from a base class like this:
class Base
{
protected function foo() {}
}
class Derived extends Base
{
public function foo() { return parent::foo(); }
}
You can also do the same with properties (redefine a protected property as public).
However, be aware that if the base property is private then you will not actually increase its accessibility but rather declare a new property with the same name. This is not an issue with functions, as if you tried to call a private base method you would immediately get a runtime error.
You can overwrite a method in a derived class to highten it´s visibility (e.g. protected->public). Make the new function return it´s parent.
You cannot do so to limit it´s visibility (e.g. public->protected), but you can implement a method that checks the backtrace for the caller and thwors an exception if it´s a foreign class.
You can always use the reflection API to do all kinds of changes to the visibility.
Yes, it can be done. Quoting from PHP manual..
The visibility of a property or method can be defined by prefixing the
declaration with the keywords public, protected or private. Class
members declared public can be accessed everywhere. Members declared
protected can be accessed only within the class itself and by
inherited and parent classes. Members declared as private may only be
accessed by the class that defines the member.
And the example from there as well..
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private
Edit : Yes, you can change visibility of public and protected members. Another example from PHP manual..
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined
?>

Does a protected variable become private in an inherited class?

<?php
class Example{
public $pub="public";
private $priv = "private";
protected $prot = "protected";
}
class SubClass extends Example{
}
$ex = new Example();
$sub = new SubClass();
/* called indiviually */
echo $sub->priv; // error
echo $sub->prot; // error
echo "<br/>";
echo $ex->pub; // works
echo $ex->prot; // error
?>
As you can see calling a protected variable with either parent class or subclass is throwing error . So what I can assume is: do something like, $prot acts like private modifier in parent class and we are not allowed to call it from outside the class block . and $prot variable when inherited into subclass it starts acting like private variable because even now it wasn't allowed to call it from outside .
PS : not studied :: scope resolution operator yet . Used only -> arrow and $this
Protected variables are available inside the subclass but will throw an error in any other scope:
<?php
class Example{
public $pub="public";
private $priv = "private";
protected $prot = "protected";
}
class SubClass extends Example{
function get_protected() {
return $this->prot;
}
}
$ex = new Example();
$sub = new SubClass();
/* called indiviually */
echo $sub->priv; // error
echo $sub->prot; // error
echo $sub->get_protected() // works
echo $ex->pub; // works
echo $ex->prot; // error

From a usage standpoint, what's the difference between a private and protection class function?

I know the manual definition, but from a real life usage standpoint, what's the difference? When would you use one over the other?
EDIT:
use protected methods when you want a child class (one that extends your current (or parent) class) to be able to access methods or variables within the parent.
Here is the PHP Visibility Manual
private can be seen by no other classes except the one the variable/method is contained in.
protected can be seen by any class that is in the same package/namespace.
Code from the manual.
<?php
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined
?>
When you know that a variable will be used only in that class and not in any other or extending class you would name it private. So if you extend the class and mistakenly name the variable as the name of a private this would give you error and thus prevent you from making mistakes.
If you for example use many pages in your web application and all of the pages are classes that extend one single class that handles header and footer of the page (cause it's always the same) you can override for example the default title of the page which is set up in parent class with protected variable setting.
I hope this helps.

Categories