Why is PHP private variables working on extended class? - php

Shouldn't it generate error when i try to set the value of a property from the extended class instead of a base class?
<?php
class first{
public $id = 22;
private $name;
protected $email;
public function __construct(){
echo "Base function constructor<br />";
}
public function printit(){
echo "Hello World<br />";
}
public function __destruct(){
echo "Base function destructor!<br />";
}
}
class second extends first{
public function __construct($myName, $myEmail){
$this->name = $myName;
$this->email = $myEmail;
$this->reveal();
}
public function reveal(){
echo $this->name.'<br />';
echo $this->email.'<br />';
}
}
$object = new second('sth','aaa#bbb.com');
?>

Private variables are not accessible in subclasses. Thats what the access modifier protected is for. What happened here is that when you access a variable that doesn't exist, it creates one for you with the default access modifier of public.
Here is the UML to show you the state:
Please note: the subclass still has access to all the public and protected methods and variables from its superclass - but are not in the UML diagram!

Related

Visibility Modifiers [duplicate]

Shouldn't it generate error when i try to set the value of a property from the extended class instead of a base class?
<?php
class first{
public $id = 22;
private $name;
protected $email;
public function __construct(){
echo "Base function constructor<br />";
}
public function printit(){
echo "Hello World<br />";
}
public function __destruct(){
echo "Base function destructor!<br />";
}
}
class second extends first{
public function __construct($myName, $myEmail){
$this->name = $myName;
$this->email = $myEmail;
$this->reveal();
}
public function reveal(){
echo $this->name.'<br />';
echo $this->email.'<br />';
}
}
$object = new second('sth','aaa#bbb.com');
?>
Private variables are not accessible in subclasses. Thats what the access modifier protected is for. What happened here is that when you access a variable that doesn't exist, it creates one for you with the default access modifier of public.
Here is the UML to show you the state:
Please note: the subclass still has access to all the public and protected methods and variables from its superclass - but are not in the UML diagram!

Why is the Class extend not getting private variable

The following code does not produce the output with the name Jock. I suspect because in the class Animal the $name is private, but the construct is public so should the subclass not be able to get the $name from the construct. I do not want to make $name public.
class Animal{
private $name;
public function __construct($name) {
$this->name = $name;
}
public function Greet(){
echo "Hello, I'm some sort of animal and my name is ", $this->name ;
}
}
class Dog extends Animal{
private $type;
public function __construct($name,$type) {
$this->type = $type;
parent::__construct($name);
}
public function Greet(){
echo "Hello, I'm a ", $this->type, " and my name is ", $this->name;
}
}
$dog2 = new Dog('Jock','dog');
$dog2->Greet();
You are right: delete the private variable or use protected in the first line of the class animal and you're fine.
class Animal{
protected $name; //see here!
public function __construct($name) {
$this->name = $name;
}
public function Greet(){
echo "Hello, I'm some sort of animal and my name is ".$this->name ;
}
}
$animal = new Animal("Gizmo");
$animal->greet(); //produces the desired result.
echo $animal->name; //this will throw an error - unable to access protected variable $name
$name won't be public since it is an argument used in the public constructor and is therefore confined to the scope of that function. The property name on the dog will be public however unless you use protected.
Dots are used to concat strings. However echo allows commas to output multiple expressions.
public function Greet(){
echo "Hello, I'm a ".$this->type." and my name is ".$this->name;
}
Also when using double quotes; you can put the variables inside the string:
public function Greet(){
echo "Hello, I'm a $this->type and my name is $this->name";
}
the private variable only accessed inside the same class, you need to use protected for the name variable in class Animal.
class Animal{
protected $name;
public function __construct($name) {
$this->name = $name;
}
public function Greet(){
echo "Hello, I'm some sort of animal and my name is ", $this->name;
}
}
class Dog extends Animal{
private $type;
public function __construct($name,$type) {
$this->type = $type;
parent::__construct($name);
}
public function Greet(){
echo "Hello, I'm a ", $this->type, " and my name is ", $this->name;
}
}
$dog2 = new Dog('Jock','dog');
$dog2->Greet();
You could use setter & getter methods to help you modify and retrieve your instance variables without needing to declare them as public.
If you are using eclipse:
Right click on the class > Source > Generate Getters & Setters
which will create functions for all of your variables as so:
public String getName(){return this.name;}
public String setName(String name){this. name = name; }
You could then use these methods to access and edit your class variables

PHP OOP private protected

I have the following code:
Class definition:
<?php
class Person{
var $name;
public $height;
protected $socialInsurance = "yes";
private $pinnNumber = 12345;
public function __construct($personsName){
$this->name = $personsName;
}
public function setName($newName){
$this->name = $newName;
}
public function getName(){
return $this->name;
}
public function sayIt(){
return $this->pinnNumber;
}
}
class Employee extends Person{
}
And the part with instances:
<!DOCTYPE html>
<HTML>
<HEAD>
<META charset="UTF-8" />
<TITLE>Public, private and protected variables</TITLE>
</HEAD>
<BODY>
<?php
require_once("classes/person.php");
$Stefan = new Person("Stefan Mischook");
echo("Stefan's full name: " . $Stefan->getName() . ".<BR />");
echo("Tell me private stuff: " . $Stefan->sayIt() . "<BR />");
$Jake = new Employee("Jake Hull");
echo("Jake's full name: " . $Jake->getName() . ".<BR />");
echo("Tell me private stuff: " . $Jake->sayIt() . "<BR />");
?>
</BODY>
</HTML>
Output:
Stefan's full name: Stefan Mischook.
Tell me private stuff: 12345
Jake's full name: Jake Hull.
Tell me private stuff: 12345 // Here I was expecting an error
As I understand, the private variable is accessible only from it's own class, and the protected variable is accessible also from the classes that extend the class. I have the private variable $pinnNumber. So I expected, that I get an error if I call $Jake->sayIt(). Because $Jake is member of class Employee that extends class Person. And the variable $pinnNumber should be accessible only from class Person, not from the class Employee.
Where is the problem?
Actually, that's not how it works.
As you didn't extend the sayIt() method, there is no "accessibility problem", there would be one if you did something like this:
<?php
class Person{
var $name;
public $height;
protected $socialInsurance = "yes";
private $pinnNumber = 12345;
public function __construct($personsName){
$this->name = $personsName;
}
public function setName($newName){
$this->name = $newName;
}
public function getName(){
return $this->name;
}
public function sayIt(){
return $this->pinnNumber;
}
}
class Employee extends Person{
public function sayIt(){
return $this->pinnNumber;//not accessible from child class
}
}
Protected, public and private are just enviroment scopes, in your case, for a Class. Since your satIt() function is public, you can access the function which then has the correct enviroment scope to access any private or protected variables.
If you tried to do:
$Jake->pinnNumber
Outside the Class, then you'd get the error.
You should research more about Scopes in methods and Classes, then you can move onto anonymous functions ;)

what is the protected mode in php

I Protected works only one inherited class know ,
In this code , the protected works in third class ,
Is It true or any mistake i made in my code ,
<?php
class sample_visibility{
public function my_first_public(){
$MSG = "THIS IS MY PUBLIC FUNCTION ";
return $MSG;
}
private function my_first_private(){
$MSG = "THIS IS MY PRIVATE FUNCTION ";
return $MSG;
}
protected function my_first_protected(){
$MSG = "THIS IS MY PROTECTED FUNCTION ";
return $MSG;
}
}
class sample_visibilit2 extends sample_visibility{
public function my_first_child_public(){
$MSG = "THIS IS MY CHILD PUBLIC FUNCTION ".$this->my_first_protected();
return $MSG;
}
}
class sample_visibilit3 extends sample_visibility{
public function my_first_child_public_3(){
$MSG = "THIS IS MY CHILD PUBLIC FUNCTION ".$this->my_first_protected();
return $MSG;
}
}
$OBJ_CLASS_1 = new sample_visibility();
echo $OBJ_CLASS_1->my_first_public();
$OBJ_CLASS_3 = new sample_visibilit3();
echo $OBJ_CLASS_3->my_first_child_public_3();
?>
You have made no mistake in your code. Protected elements (members or functions) are accessible by children, grandchildren, (great-)*grandchildren. Any number of inheritances is ok. They are only "protected" from unrelated classes.
public - accessible anywhere
protected - derived classes only (any number of inheritances)
private - only accessible internally
Although your question is not very clear, your code is correct and will work.
Inside the classes sample_visibilit2 and sample_visibilit3 you can access my_first_protected(), because both classes are subclasses of sample_visibility.

Is there a way define a global variable which is accesible from a class method?

Here is the situation
I create a instance of a class
$newobj = new classname1;
Then I have another class writtern below and I want to this class to access the object above
class newclass {
public function test() {
echo $newobj->display();
}
}
It is not allowed, is there a way define a variable globally through a class?
It is allowed, but you need to use the appropriate syntax: either the global keyword or the $GLOBALS superglobal:
http://es.php.net/manual/en/language.variables.scope.php
http://es.php.net/manual/en/reserved.variables.globals.php
<?php
class classname1{
private $id;
public function __construct($id){
$this->id = $id;
}
public function display(){
echo "Displaying " . $this->id . "...\n";
}
}
$newobj = new classname1(1);
class newclass {
public function test() {
global $newobj;
echo $newobj->display();
}
public function test_alt() {
echo $GLOBALS['newobj']->display();
}
}
$foo = new newclass;
$foo->test();
$foo->test_alt();
?>
However, global variables must always be used with caution. They can lead to code that's hard to understand and maintain and bugs that are hard to track down. It's normally easier to just pass the required arguments:
<?php
class classname1{
private $id;
public function __construct($id){
$this->id = $id;
}
public function display(){
echo "Displaying " . $this->id . "...\n";
}
}
$newobj = new classname1(1);
class newclass {
public function test(classname1 $newobj) {
echo $newobj->display();
}
}
$foo = new newclass;
$foo->test($newobj);
?>
Last but not least, you might be looking for the singleton OOP pattern:
http://en.wikipedia.org/wiki/Singleton_pattern
Make the instance a global:
$newobj = new classname1;
class newclass {
public function test() {
global $newobj;
echo $newobj->display();
}
}
Since I got a downvote for the first line, I removed it.
you can also inherit your newclass from classname1 and then you will be able to call the methods of the class 'classname1'
like this:
class newclass extends classname1 {
public function test() {
echo parent::display();
}
}
Could look at using the singleton pattern.
This basically is a class that creates an instance of itself and subsequent calls will access this instance and therefore achieving what I think you might be up to...

Categories