I'm creating a small, multiclass system that extends each other. Lets say class a is a "core" and work as a checking/administration wrapper. class b is to check what $d is and call a method of class c, a user class, if it exists or trigger an error to class a back.
Here's my code:
<?php
class a {
private $error;
private $ok;
public function __construct() {
$this->error = array();
$this->ok = array();
// do other stuff here
}
}
class b extends a {
private $head;
private $out;
public function __construct() {
parent::__construct();
global $d;
$this->head = "";
$this->out = "";
if(method_exists($this,$d)) {
$this->{$d}();
} else
$this->error[] = "method '$d' not found";
}
public function output() {
return ($this->head==""?"":'<h1>'.$this->head.'</h1>').$this->out;
}
}
class c extends b {
private $me = "inside c";
public function standard() {
$this->head = "Heading";
$this->out = "it works!";
}
}
$d = "standard";
$c = new c();
echo "<pre>".print_r($c,true)."</pre>";
echo $c->output();
?>
if i ran $c->output() it returns nothing, but the print_r() returns this:
c Object
(
[me:c:private] => inside c
[head:b:private] =>
[out:b:private] =>
[error:a:private] => Array
(
)
[ok:a:private] => Array
(
)
[head] => Heading
[out] => it works!
)
Could anyone please help me with this?
It's because you've declared all your class variables as private. This makes it so that only the class where they were declared can access them. Not even subclasses (derived classes) can see them.
If you need subclasses to access the variables of a parent class, you should declare them as protected.
http://php.net/manual/en/language.oop5.visibility.php
You should use protected instead of private!
Try
protected $head;
protected $out;
Related
class MyAppClass {
protected $_config = array();
protected $_template = '';
public function init( ){
require_once('core_config.php'); // Inside is $_SC_config with an array of values
$this->_config = $_SC_config;
$this->_template = new template;
echo $this->_template->echo_base();
}
}
class template extends MyAppClass{
public function echo_base() {
var_dump($this->_config); // returns empty array
}
}
$myApp = new MyAppClass;
$myApp->init();
What's wrong with code above so
var_dump($this->_config)
in template class returns empty array after init function?
Thanks in advance.
I think you don't get object programming yet. In MyAppClass::init method you create new object of template class which extends your MyAppClass class. I have no idea what do you want to acheve but I will show you snippet which works.
<?php
class MyAppClass {
protected $_config = array();
protected $_template = '';
protected function init( ){
//require_once('core_config.php'); // Inside is $_SC_config with an array of values
$this->_config = 'foo';
}
}
class template extends MyAppClass{
public function __construct(){
$this->init();
}
public function echo_base() {
var_dump($this->_config); // returns empty array
}
}
$myApp = new template;
$myApp->echo_base();
I created a parent class (A) and modified some of its public and protected properties.
I created a child class (B) that extends A.
I can see the parent properties at B instance after creating it.
Problem is: The inherited properties of B have the default values of A, from before I modified them.
I want B to hold the modified values of the inherited properties.
How?
class Dashboard {
protected $testBusinessesIds = '';
public function test_bids($a){
$this->testBusinessesIds = $a;
}
}
class DashboardDBHelper extends Dashboard{
protected $withoutTestBids = '';
public function __construct(){
if($this->testBusinessesIds != '')
$this->withoutTestBids = " AND B.`id`";
}
}
$d = new Dashboard();
$d->test_bids(23);
$dh = new DashboardDBHelper();
print_r($dh->withoutTestBids);
I see: '' instead of 'AND B.id'
You may need to put your property as static. Here's an example:
class A {
protected $value = 1;
protected static $staticValue = 1;
public function printStatic() {
self::$staticValue++;
echo self::$staticValue;
}
public function printNonStatic() {
$this->value++;
echo $this->value;
}
}
class B extends A {
public function printStatic() {
echo self::$staticValue;
}
public function printNonStatic() {
echo $this->value;
}
}
$a = new A();
$b = new B();
/* Class A */
$a->printStatic(); // 2
$a->printNonStatic(); // 2
/* Class B */
$b->printStatic(); // 2
$b->printNonStatic(); // 1
Static variables does not share the same class/object so if you modify the value it will be changed everywhere.
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;
define('anActionType', 1);
$actionTypes = array(anActionType => 'anActionType');
class core {
public $callbacks = array();
public $plugins = array();
public function __construct() {
$this->plugins[] = new admin();
$this->plugins[] = new client();
}
}
abstract class plugin {
public function registerCallback($callbackMethod, $onAction) {
if (!isset($this->callbacks[$onAction]))
$this->callbacks[$onAction] = array();
global $actionTypes;
echo "Calling $callbackMethod in $callbacksClass because we got {$actionTypes[$onAction]}" . PHP_EOL;
// How do I get $callbacksClass?
$this->callbacks[$onAction][] = $callbackMethod;
}
}
class admin extends plugin {
public function __construct() {
$this->registerCallback('onTiny', anActionType);
}
public function onTiny() { echo 'tinyAdmin'; }
}
class client extends plugin {
public function __construct() {
$this->registerCallback('onTiny', anActionType);
}
public function onTiny() { echo 'tinyClient'; }
}
$o = new core();
$callbacksClass should be admin or client. Or am I missing the point here completely and should go about this another way? It should be noted that I will only accept an answer that does not require me to send the classname as an argument to the registerCallback method.
If anyone came here looking for how to get the name of a calling class from another class like I did, check this out https://gist.github.com/1122679
EDIT: pasted code
function get_calling_class() {
//get the trace
$trace = debug_backtrace();
// Get the class that is asking for who awoke it
$class = $trace[1]['class'];
// +1 to i cos we have to account for calling this function
for ( $i=1; $i<count( $trace ); $i++ ) {
if ( isset( $trace[$i] ) ) // is it set?
if ( $class != $trace[$i]['class'] ) // is it a different class
return $trace[$i]['class'];
}
}
EG
class A {
function t() {
echo get_calling_class();
}
}
class B {
function x() {
$a = new A;
$a->t();
}
}
$b = new B;
$b->x(); // prints B
Use get_class():
$this->callbacks[$onAction][] = $callbackMethod;
$className = get_class($this);
// Call callback method
$className->$callbackMethod();
You should really do something like:
$this->registerCallback(array($this, 'onTiny'), anActionType);
That is how PHP works with handles to object methods.
From PHP 8+ you can use static::class rather than get_class($this).
This one is also auto-fixed with PHP Code Sniffer and rule SlevomatCodingStandard.Classes.ModernClassNameReference
I want to have a static method in a parent class that creates instances of whatever subclass i call this method on.
An example to make this more clear:
class parent {
public static method make_objects($conditions){
for (...){
// here i want to create an instance
// of whatever subclass i am calling make_objects on
// based on certain $conditions
}
}
}
class sub extends parent{
...
}
$objects = sub::make_objects($some_conditions);
As of php 5.3 you can use the static keyword for this
<?php
class A {
public static function newInstance() {
$rv = new static();
return $rv;
}
}
class B extends A { }
class C extends B { }
$o = A::newInstance(); var_dump($o);
$o = B::newInstance(); var_dump($o);
$o = C::newInstance(); var_dump($o);
prints
object(A)#1 (0) {
}
object(B)#2 (0) {
}
object(C)#1 (0) {
}
edit: another (similar) example
<?php
class A {
public static function newInstance() {
$rv = new static();
return $rv;
}
public function __construct() { echo " A::__construct\n"; }
}
class B extends A {
public function __construct() { echo " B::__construct\n"; }
}
class C extends B {
public function __construct() { echo " C::__construct\n"; }
}
$types = array('A', 'B', 'C');
foreach( $types as $t ) {
echo 't=', $t, "\n";
$o = $t::newInstance();
echo ' type of o=', get_class($o), "\n";
}
prints
t=A
A::__construct
type of o=A
t=B
B::__construct
type of o=B
t=C
C::__construct
type of o=C
I think you want something like this:
class parent {
public static function make_object($conditionns) {
if($conditions == "case1") {
return new sub();
}
}
}
class sub extends parent {
}
Now you can create an instance like this:
$instance = parent::make_object("case1");
or
$instance = sub::make_object("case1");
But why would you want all the sub classes to extend the parent? Shouldn't you much rather have a parent for your models (sub classes) and then a factory class, that creates the instances for this models depending on the conditions given?
Umm, wouldn't that be:
class sub extends parent {
public static function make_objects($conditions) {
//sub specific stuff here
//....
}
}
make the parent class an abstract class and make the parent method also an abstract
abstract static class parent {
abstract function make_method() {
// your process
}
}
class child extends parent {
public function __construct() {
parent::make_method();
}
}