Here is my code:
class Parent1
{
static $db = null;
public function __construct()
{
self::$db = 'a';
}
}
class Child extends Parent1
{
public function __construct()
{
parent::__construct();
self::$db = 'b';
}
}
$myParent = new Parent1();
echo $myParent::$db; //"a"
$myChild = new Child();
echo $myChild::$db; //"b"
echo $myParent::$db; //"b" it should be "a"
Why $myParent::$db is changing to b? How to prevent it??
Why?
static $db = null;
$db is static, it's not linked to the instance.
self::$db = 'b'; will change the unique and shared instance of $db.
How to prevent it?
You can't. It's how static fields work.
By the way, calling static from an instance ($aa::field) is not a good think.
Take a look at the documentation about static in PHP because you probably don't understand how it work.
You are using static variables. These are class level and shared across all instances. You might want to change them to instance variables... see below.
<?php
class Parent1
{
public $db = null;
public function __construct()
{
$this->db = 'a';
}
}
class Child extends Parent1
{
public function __construct()
{
parent::__construct();
$this->db = 'b';
}
}
However, writing to $myChild->db WILL change the variable from the parent because it is an inherited variable but it won't affect the $db value from $myParent.
I found solution. I redeclare static in Child - now it works.
Thanks for explaining static
class Parent1
{
static $db = null;
public function __construct()
{
self::$db = 'a';
}
}
class Child extends Parent1
{
static $db = null;
public function __construct()
{
parent::__construct();
self:$db=parent::$db;
self::$db = 'b';
}
}
$myParent = new Parent1();
echo $myParent::$db; //"a"
$myChild = new Child();
echo $myChild::$db; //"b"
echo $myParent::$db; //"a" => as it should
Related
I want to build class that implement a lot of methods based on it's id,
so I want to have one class parent that implement the methods!
and when i want to use this class I will extend it and just override the id variable :
class parent
{
$id = "parent";
private __construct()
{
}
public static function create_instance()
{
$instance = new self();
return $instance;
}
public static function print_id()
{
echo $this->id;
}
}
class child extend parent
{
$id = "child";
}
$instance = child::create_instance();
$instance->print_id();
the result will be "parent", but I want the result to be child ?
How to do that ?
EDIT : I also tried this and got parent instead of child:
class parent1 {
private $id = "parent";
public function __construct() {
}
public static function create_instance() {
$instance = new static ();
return $instance;
}
public function print_id() {
echo $this->id;
}
}
class child extends parent1 {
private $id = "child";
}
$instance = child::create_instance ();
$instance->print_id ();
The problem is that the visibility of $id is private whereas it should be protected because print_id() is only defined on the parent; as such it can only reach its own $id.
class parent1 {
protected $id = "parent";
// ...
}
class child extends parent1 {
protected $id = "child";
}
The alternative is, of course, to override print_id() in the child class.
Currently when you call create_instance method on child class as a result instance of parent class is created not child class as you expect.
Use late static binding in parent class "create_instance" method:
public static function create_instance()
{
$instance = new static();
return $instance;
}
More details http://php.net/manual/en/language.oop5.late-static-bindings.php
Edit: Original example removed as it was complex.
The codes provided below doesn't work. I am trying to access the methods defined in a class which is declared in the parent class.
Here is a sample code. Its not working and I'd like to know why
<?php
function & get_instance()
{
return Main::get_instance();
}
class Db{
function select($var)
{
echo $var;
}
}
class Main
{
public $db ;
public $process ;
private static $instance;
function __construct()
{
self::$instance = &$this;
$this->db = new Db ;
$this->process = Process;
}
public static function & get_instance()
{
return self::$instance;
}
}
class Process{
private $main ;
function __construct()
{
$this->main = get_instance() ;
}
function processPayment()
{
$this->main->db->select("hello");
}
}
$main = new Main ;
$main->process->processPayment();
To access members of a parent class, you will have to declare those members protected or public.
For example:
public var $db;
protected var $orders;
I've 3 classes. [1]Singleton [2]Load [3]Dashboard . In Load class there is one method called 'model()'. Where i'm initializing data for singleton object by using this code.
$obj = Singleton::getInstance();
$obj->insertData('email', 'mail#domain.com');
Again, from Dashboard class there is one method called 'show()' from where i'm trying to print the Singleton object data. But, here i can see all the data of Singleton object except the data which has been initialized by 'model' method of 'Load' class.
Here is my full code...
<?php
//---Singletone Class---
class Singleton
{
// A static property to hold the single instance of the class
private static $instance;
// The constructor is private so that outside code cannot instantiate
public function __construct() {
if(isset(self::$instance))
foreach(self::$instance as $key => &$val)
{
$this->{$key} = &$val;
}
}
// All code that needs to get and instance of the class should call
// this function like so: $db = Database::getInstance();
public static function getInstance()
{
// If there is no instance, create one
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
// Block the clone method
private function __clone() {}
// Function for inserting data to object
public function insertData($param, $element)
{
$this->{$param} = $element;
}
}
//---LOAD class---
class Load
{
function __construct()
{
$obj = Singleton::getInstance();
$obj->insertData('country', 'INDIA');
}
function model()
{
$this->name = 'Suresh';
$obj = Singleton::getInstance();
$obj->insertData('email', 'mail#domain.com');
}
function msg()
{
return('<br><br>This message is from LOAD class');
}
}
$obj = Singleton::getInstance();
$load = new load();
$obj->load = $load;
//---Dashboard Class---
class Dashboard extends Singleton
{
function __construct()
{
parent::__construct();
}
function show()
{
echo "Default data in current Object";
echo "<br>";
print_r($this);
echo $this->load->msg();
$this->load->model();
echo "<br><br>Data in current Object after post intialization";
echo "<br>";
print_r($this);
}
}
$dashboard = new dashboard();
$dashboard->show();
If your singleton was truly a singleton then the update would have worked. I'm suspecting that you may have multiple instances of the singleton class that is initialized.
Edit:
Also its not a good idea to inherit from a true singleton class.
You need to remove the inheritance that Dashboard has on Singleton
Edit:
Best practice on PHP singleton classes
I don't like your direct access to an object like an array. This one is a better approach [see here]:
You should call it like this:
$obj = Singleton::getInstance();
$load = new Load();
$obj->insertData( 'load', $load );
Implementation of Singleton:
class Singleton
{
// A static property to hold the single instance of the class
private static $instance;
// my local data
protected $_properties;
// You might want to move setter/getter to the end of the class file
public function __set( $name, $value )
{
$this->_properties[ $name ] = $value;
}
public function __get( $name )
{
if ( ! isset( $this->_properties[ $name ] )) {
return null;
}
return $this->_properties[ $name ];
}
// No need to check, if single instance exists!
// __construct can only be called, if an instance of Singleton actually exists
private function __construct() {
$this->_properties = array();
foreach(self::$instance as $key => &$val)
{
$this->_properties{$key} = &$val;
}
}
public static function getInstance()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
// Function for inserting data to object
public function insertData($param, $element)
{
$this->_properties{$param} = $element;
}
// Block the clone method
private function __clone() {}
}
we have two class A & B:
class A{
var $settings;
function getinfo(){
$settings['domain']="mydomain";
$settings['pass']="1234";
return $settings;
}
}
class B extends A{
$ads = A::getinfo();
function makeurl(){
return "template/".$ads['domain'];
}
}
now i have an instance of B in my page, but i need "pass" , maybe some code like this:
$theme=new B();
$mypass = $theme->A->getinfo;
echo $mypass[$pass];
I know this code is full of faults , but i could not write a better one. is there any solution to access to password without making an instance of A?
Yes. It is as simple as this:
$theme = new B();
$mypass = $theme->getinfo();
echo $mypass['pass'];
You can also improve your classes a bit:
class A
{
var $settings;
function getinfo()
{
$this->settings['domain'] = "mydomain";
$this->settings['pass'] = "1234";
return $this->settings;
}
}
class B extends A
{
function makeurl()
{
$this->getinfo();
return 'template/' . $this->settings['domain'];
}
}
Why not call the settings variable in A from the B instance since B is a subclass of A?
Try this code:
<?php
class A
{
var $settings;
function getinfo()
{
$settings['domain'] = "mydomain";
$settings['pass'] = "1234";
return $settings;
}
}
class B extends A
{
function makeurl()
{
$ads = $this->getinfo();
return "template/" . $ads['domain'];
}
}
$theme=new B();
$mypass = $theme->getinfo();
echo $mypass['pass'];
What about making settings a public static variable in A? By making it a class variable you won't need an instance of A.
class A {
public static $settings;
// getter and setter methods here
}
// code elsewhere
echo A::$settings['pass'];
Also because your class B extends A it inherits the methods and properties, so you could call
$theme = new B();
$mySettings = $theme->GetInfo();
if B extends A, all protected and public members of A are inherited into B, so you can access them directly.
class A {
protected $foo;
public function __construct() { $this->foo = 1; }
}
class B extends A {
public function bar() {
echo $this->foo;
}
}
$b = B();
$b->bar();
If I understand you correctly, you're pretty close:
$theme=new B();
$settings = $theme->getinfo();
$mypass = $settings['pass'];
echo $mypass;
How can I define a variable before or while initializing the class?
<?php
class class{
public $var;
public function __construct(){
echo $this -> var;
}
}
$class = new class;
$class -> var = "var";
?>
If you mean instantiating the class, then use the constructor:
class Foo {
private $_bar;
public function __construct($value) {
$this->_bar = $value;
}
}
$test = new Foo('Mark');
You can do it 2 ways - see this example:
class bla {
public static $yourVar;
public function __construct($var) {
self::yourVar = $var
}
}
// you can set it like this without instantiating the class
bla::$yourVar = "lala";
// or pass it to the constructor while it's instantiating
$b = new bla("lala");
The first part you can only do with a static, but if you don't want to use a static, you'll have to initialize it via the constructor.
Hope that's what you were looking for...
$myVariable; // variable is defined
$myVariable = new myClass(); // instance of a class
class myClass {
protected $theVariable;
protected function myClass($value) {
$this->$theVariable = $value;
}
}
$theVariable = 'The Value';
$theClass = new myClass($theVariable);
echo $theClass->theVariable;