Class Constructor Interfering With Another Class - php

Essentially, I am just creating two classes where one class, in this case class A, runs a function in another class, in this case class B, to grab some information from the database.
However, when the B_runtime() actually calls upon the database I get the error Cannot access protected property A::$db.
What I don't understand is that even though I have two __construct's in both classes the PDO statement is being very persistent on using the database connection from class A.
I am sure this has something to do with the fact that I am running the B_runtime() from within class A because this doesn't happen if I call it from outside of class A.
I know that I can simply change the protected $db; in class A to a public variable, however, I am really curious as to how I can fix this.
ob_start();
include('/config.php');
ob_end_clean();
$A = new A($db);
$B = new B($db);
echo $A->A_runtime();
class A{
protected $db;
public function __construct($db){
$this->db = $db;
}
public function A_runtime(){
return B::B_runtime();
}
}
class B{
protected $db;
public function __construct($db){
$this->db = $db;
}
public function B_runtime(){
$preparedStatement = $this->db->prepare('SELECT * FROM z_mod_html WHERE ModuleLink = :moduleid LIMIT 1');
$preparedStatement->execute(array(':moduleid' => '1'));
$rows = $preparedStatement->fetchAll();
return $rows[0]['HTML'];
}
}
Sorry for the long amount of code - if anyone has any ideas or suggestions it would be greatly appreciated. Thanks.

You could pass the instance of B to the method. This way you also define the dependancy of your method on class B.
$A = new A($db);
$B = new B($db);
echo $A->A_runtime($B);
class A{
//...
public function A_runtime($instance){
return $instance -> B_runtime();
}
}
You can even use type hinting in PHP 5 to signal that you are expecting an instance of class B there:
public function A_runtime(B $instance){

Oy.
first, you are calling a non-static method as a static method.
B::B_runtime();
should only be used in this way if B_runtime were declared as a static method
static public function B_runtime(){
second, your class has an external dependency which is generally considered not good. a class should only rely on what is given to it, not on globals. this is called the dependency inversion principle. if a class is dependent on somthing, you should have to give this dependency to it via an argument, and even better, use type hinting to make sure that the dependency has the methods you expect it to.
public function A_runtime(B $object_b){
To take this a step further, you should also be using abstracts or interfaces for type hinting instead of concrete classes. this way you can switch B out with a different version of B if it ever becomes necessary.
interface BInterface {
public function B_runtime();
}
then
public function A_runtime(BInterface $object_b){
read up on SOLID principles of OO design.
http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

Related

self:: referring to derived class in static methods of a parent class

I liked the idea presented in this answer allowing having something like multiple constructors in PHP. The code I have is similar to:
class A {
protected function __construct(){
// made protected to disallow calling with $aa = new A()
// in fact, does nothing
};
static public function create(){
$instance = new self();
//... some important code
return $instance;
}
static public function createFromYetAnotherClass(YetAnotherClass $xx){
// ...
}
class B extends A {};
$aa = A::create();
$bb = B::create();
Now I want to create a derived class B, which would use the same "pseudo-constructor", because it is the same code. However, in this case when I do not code the create() method, the self constant is the class A, so both variables $aa and $bb are of class A, while I wish $bb be class B.
If I use $this special variable, this of course would be class B, even in A scope, if I call any parent method from B.
I know I can copy the entire create() method (maybe Traits do help?), but I also have to copy all "constructors" (all create* methods) and this is stupid.
How can I help $bb to become B, even if the method is called in A context?
You want to use static, which represents the class in which the method is called. (self represents the class in which the method is defined.)
static public function create(){
$instance = new static();
//... some important code
return $instance;
}
Refer to the documentation on Late Static Bindings.
You'll need PHP 5.3+ to use this.

PHP accessing variables from the parent class CLOSED

I've seen a few questions with really similar titles but they where irrelevant to my specific problem.
Basically, I want to access the variables from my core class in a class which extends core, but things seem to be quite complicated compared to other examples. I am using a MVC framework. I've simplified the code below to remove anything that was irrelevant.
index.php
// Load the core
include_once('core.php');
$core = new Core($uri, $curpath);
$core->loadController('property');
core.php
class Core
{
public $uri;
public $curpath;
function __construct($uri, $curpath)
{
$this->uri = $uri;
$this->curpath = $curpath;
}
// Load the controller based on the URL
function loadController($name)
{
//Instantiate the controller
require_once('controller/'.$name.'.php');
$controller = new $name();
}
}
property.php
class Property extends Core
{
function __construct()
{
print $this->curpath;
}
}
Printing $this->curpath just returns nothing. The variable has been set but it is empty.
If I print $this->curpath inside core.php it prints fine.
How can I access this variable?
You are doing it wrong tm
You should be utilizing an autoloader, instead of including files with each class manually. You should learn about spl_autoload_register() and and namespaces, and how to utilize both of them.
Do not generate output in the __construct() methods. That's an extremely bad practice
The variables are still there. That is not the problem. In PHP, when you extend a class, it does not inherit the constructor.
You do not understand how inheritance works. When you call method on instance of extended class it will not execute parent class's method , before calling extended class's methods. They get overwritten , not stacked.
Object variables should not be exposed. You are breaking the encapsulation. Instead og defining them as public you should use protected.
You should extend classes of they are different type same general thing. The extends in PHP means is-a. Which means that, when you write class Oak extends Tree, you mean that all the oaks are trees. The same rule would mean, that in your understanding all Property instances are just a special case of Core instances. Which they clearly ain't.
In OOP, we have principle. One of which is Liskov substitution principle (shorter explanation). And this is the thing your classes are violating.
The problem, I think, lies here:
If you consider a simple inheritance like this one:
class Dog{
public $color;
public function __construct($color){
$this->color = $color;
}
}
class TrainedDog extends Dog{
public $tricks;
public function __construct($color, $tricks){
$this->tricks = $tricks;
parent::__construct($color);
}
}
//Create Dog:
$alfred = new Dog('brown');
//Create TrainedDog
$lassie = new TrainedDog('golden',array('fetch'));
In this example $alfred is a brown dog and $lassie is a golden dog. The two instances are separate from each other, the only thing they have in common is that they both have a property called $color.
If you want a variable that is available in all Dogs for example, you need a class variable:
class Dog{
public $color;
public static $numberOfLegs; //Class variable available in every instance of Dog.
public function __construct($color, $numberOfLegs){
$this->color = $color;
self::$numberOfLegs = $numberOfLegs;
}
}
class TrainedDog extends Dog{
public $tricks;
public function __construct($color, $tricks){
$this->tricks = $tricks;
parent::__construct($color);
echo parent::$numberOfLegs;
}
}
This does not make much sense in many cases though, because if you have two instances of the parent class (in you're case Core), they also share the class variable.
Unless you can ensure that Core is instanciated only once, this approach will not work. If it does only exist once, you can just as well use constant variables to store the 2 properties.
If there exist multiple instances/objects of Core, I'd recommend using a composition (as suggested by Alvin Wong).
class Core{
//Just as you programmed it.
}
class Property{
private $core;
public function __construct($core){
$this->core = $core;
echo $core->curPath;
}
}
Try this
include_once('core.php');
$core = new Core('test', 'path');
$core->loadController('property');
class Property extends Core
{
function __construct($date)
{
print $date->curpath;
}
}
class Core
{
public $uri;
public $curpath;
function __construct($uri, $curpath)
{
$this->uri = $uri;
$this->curpath = $curpath;
}
// Load the controller based on the URL
function loadController($name)
{
//Instantiate the controller
require_once($name.'.php');
$controller = new $name($this);
}
}

PHP Singleton extending class

I am new to OOP (PHP) and just met the design pattern - singleton.
I have found a DB class which uses mysqli (singleton class). I have added some custom methods to it (insert_id(), query(), fetch_result(), etc).
Then I created a new class called UserTools and I want to extend the database class to use the methods I've created previously (query(), fetch_result(), etc).
But I get this error:
Fatal error: Call to private Database::__construct() from invalid context in (...)
when I try to create instance of the new class (User Tools).
What should I do? Is it a right structure?
There are several way to achieve what you want.
One would be :
class UserTools {
private $db;
function __construct() {
$this->db = Database::db_connect();
}
function login() { /* ... */}
}
Although it would be better to directly pass the database instance to the constructor like this :
class UserTools {
private $db;
function __construct($db) {
$this->db = $db;
}
function login() { /* ... */}
}
// Usage
$userTools = new UserTools(Database::db_connect());
If you're really lazy you could just modify your database class and make the constructor public :
class Database {
/* ... */
public function __construct(){/* ... */}
/* ... */
}
class UserTools extends Database {/* ... */}
But I really discourage you to use the latter one. It's really bad code and it doesn't make sense in a logical point of view. Your UserTools class use a database instance. It is not a database.
It is my understanding that only protected and public methods and variables are inherited through extension, not private ones. Try changing your methods/variables from private to protected. public ones are visible to all.
For more information, See: PHP Visibility (Manual)
Edit
Understand the Singleton pattern. It is called 'singleton' because only one instance of a class is expected. Because of this, most classes implementing the singleton pattern define the constructor as private to restrict you from creating more than one.
To create an instance of a singleton, most classes define some kind of getInstance static method, which is public. This public method calls the private constructor, which probably sets flags indiciating that the class has been instantiated in order to prevent further attempts to instantiate the class. The getInstance method returns the results of calling the constructor, essentially the instance of the class.
You could write something like
class UserTools extends DB {
....
}
A quick example on inheritance in PHP:
class A {
public $a;
public function set_a($new_a) { $this->a = $new_a; return $this; }
public function get_a() { return $this->a; }
}
class B extends A {
public $b;
public function set_b($new_b) { $this->b = $new_b; return $this; }
public function get_b() { return $this->b; }
}
$objb = new B();
$objb->set_a("Some Value")->get_a(); //Some Value
The singleton pattern in most cases prevents instantiating the Singleton class by defining the constructor as private (ie private function __construct()).
So if you try to instantiate either your custom class or the original one that you're extending you will get the message above. You should either create a different class or define and use your function as static (eg public static function query($sql, $dbconnection)).
See http://php.net/manual/en/language.oop5.patterns.php

Basic php class problem

Bear with me cos I'm new to oop!
Is it possible to assign the result of a function to an attribute?
This probably doesn't make sense so here's what I think the code might look like!
Class b extends a
{
public $conn= $this->connect();
public function operation() { ...}
}
connect() is a function from class a that connects to a database and returns $result if successful.
Yes that is possible but you need to do that in a method like the constructor:
Class b extends a {
public $conn;
public function __construct() {
$this->conn = $this->connect();
}
public function operation() { /* ... */ }
}
You need to put the call to connect within a method, and then call the method once you've instantiated the class to initialize the connection - or use the constructor method to do so automatically.
Generally, this is bad form, as you cannot be certain what implementation of the connect() method will be called. Is it the one from the current class or the one from the superclass? In fact, I would be surprised if PHP even allowed this.
Initialisation should be done in the constructor, but even then it depends on what the initialisation involves. If it requires calling another method, then the same issue as above exists: which version of the method to call?
However, for the scenario you describe, I would neither initialise the member variable at declaration, nor from within a constructor. Instead, I would pass $conn to the constructor. This is the basis of dependency-injection.
i usually do something like this
$link = mysql_connect(.....,......,......);
Class b extends a {
public $conn;
public function __construct($link) {
$this->conn = $link;
}
public function operation() { /* ... */ }
}
$a = new b($link);
then if your connection details change you change them in one place and if you need to connect to a different server you can and pass in the other link variable.
Another tip for oop database integration is always have a DBable base class to do your basic save() load() find() count() etc, much quicker to work with db savable objects
BaseDBClass
A
B
C
D
X
Y
Z

Can I extend a class using more than 1 class in PHP?

If I have several classes with functions that I need but want to store separately for organisation, can I extend a class to have both?
i.e. class a extends b extends c
edit: I know how to extend classes one at a time, but I'm looking for a method to instantly extend a class using multiple base classes - AFAIK you can't do this in PHP but there should be ways around it without resorting to class c extends b, class b extends a
If you really want to fake multiple inheritance in PHP 5.3, you can use the magic function __call().
This is ugly though it works from class A user's point of view :
class B {
public function method_from_b($s) {
echo $s;
}
}
class C {
public function method_from_c($s) {
echo $s;
}
}
class A extends B
{
private $c;
public function __construct()
{
$this->c = new C;
}
// fake "extends C" using magic function
public function __call($method, $args)
{
$this->c->$method($args[0]);
}
}
$a = new A;
$a->method_from_b("abc");
$a->method_from_c("def");
Prints "abcdef"
You cannot have a class that extends two base classes. You could not have the following:
// this is NOT allowed (for all you google speeders)
Matron extends Nurse, HumanEntity
You could however have a hierarchy as follows...
Matron extends Nurse
Consultant extends Doctor
Nurse extends HumanEntity
Doctor extends HumanEntity
HumanEntity extends DatabaseTable
DatabaseTable extends AbstractTable
and so on.
You could use traits, which, hopefully, will be available from PHP 5.4.
Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way, which reduces complexity and avoids the typical problems associated with multiple inheritance and Mixins.
They are recognized for their potential in supporting better composition and reuse, hence their integration in newer versions of languages such as Perl 6, Squeak, Scala, Slate and Fortress. Traits have also been ported to Java and C#.
More information: https://wiki.php.net/rfc/traits
Classes are not meant to be just collections of methods. A class is supposed to represent an abstract concept, with both state (fields) and behaviour (methods) which changes the state. Using inheritance just to get some desired behaviour sounds like bad OO design, and exactly the reason why many languages disallow multiple inheritance: in order to prevent "spaghetti inheritance", i.e. extending 3 classes because each has a method you need, and ending up with a class that inherits 100 method and 20 fields, yet only ever uses 5 of them.
There are plans for adding mix-ins soon, I believe.
But until then, go with the accepted answer. You can abstract that out a bit to make an "extendable" class:
class Extendable{
private $extender=array();
public function addExtender(Extender $obj){
$this->extenders[] = $obj;
$obj->setExtendee($this);
}
public function __call($name, $params){
foreach($this->extenders as $extender){
//do reflection to see if extender has this method with this argument count
if (method_exists($extender, $name)){
return call_user_func_array(array($extender, $name), $params);
}
}
}
}
$foo = new Extendable();
$foo->addExtender(new OtherClass());
$foo->other_class_method();
Note that in this model "OtherClass" gets to 'know' about $foo. OtherClass needs to have a public function called "setExtendee" to set up this relationship. Then, if it's methods are invoked from $foo, it can access $foo internally. It will not, however, get access to any private/protected methods/variables like a real extended class would.
Use traits as base classes. Then use them in a parent class. Extend it .
trait business{
function sell(){
}
function buy(){
}
function collectMoney(){
}
}
trait human{
function think(){
}
function speak(){
}
}
class BusinessPerson{
use business;
use human;
// If you have more traits bring more
}
class BusinessWoman extends BusinessPerson{
function getPregnant(){
}
}
$bw = new BusinessWoman();
$bw ->speak();
$bw->getPregnant();
See now business woman logically inherited business and human both;
EDIT: 2020 PHP 5.4+ and 7+
As of PHP 5.4.0 there are "Traits" - you can use more traits in one class, so the final deciding point would be whether you want really an inheritance or you just need some "feature"(trait). Trait is, vaguely said, an already implemented interface that is meant to be just used.
Currently accepted answer by #Franck will work but it is not in fact multiple inheritance but a child instance of class defined out of scope, also there is the `__call()` shorthand - consider using just `$this->childInstance->method(args)` anywhere you need ExternalClass class method in "extended" class.
Exact answer
No you can't, respectively, not really, as manual of extends keyword says:
An extended class is always dependent on a single base class, that is,
multiple inheritance is not supported.
Real answer
However as #adam suggested correctly this does NOT forbids you to use multiple hierarchal inheritance.
You CAN extend one class, with another and another with another and so on...
So pretty simple example on this would be:
class firstInheritance{}
class secondInheritance extends firstInheritance{}
class someFinalClass extends secondInheritance{}
//...and so on...
Important note
As you might have noticed, you can only do multiple(2+) intehritance by hierarchy if you have control over all classes included in the process - that means, you can't apply this solution e.g. with built-in classes or with classes you simply can't edit - if you want to do that, you are left with the #Franck solution - child instances.
...And finally example with some output:
class A{
function a_hi(){
echo "I am a of A".PHP_EOL."<br>".PHP_EOL;
}
}
class B extends A{
function b_hi(){
echo "I am b of B".PHP_EOL."<br>".PHP_EOL;
}
}
class C extends B{
function c_hi(){
echo "I am c of C".PHP_EOL."<br>".PHP_EOL;
}
}
$myTestInstance = new C();
$myTestInstance->a_hi();
$myTestInstance->b_hi();
$myTestInstance->c_hi();
Which outputs
I am a of A
I am b of B
I am c of C
<?php
// what if we want to extend more than one class?
abstract class ExtensionBridge
{
// array containing all the extended classes
private $_exts = array();
public $_this;
function __construct() {$_this = $this;}
public function addExt($object)
{
$this->_exts[]=$object;
}
public function __get($varname)
{
foreach($this->_exts as $ext)
{
if(property_exists($ext,$varname))
return $ext->$varname;
}
}
public function __call($method,$args)
{
foreach($this->_exts as $ext)
{
if(method_exists($ext,$method))
return call_user_method_array($method,$ext,$args);
}
throw new Exception("This Method {$method} doesn't exists");
}
}
class Ext1
{
private $name="";
private $id="";
public function setID($id){$this->id = $id;}
public function setName($name){$this->name = $name;}
public function getID(){return $this->id;}
public function getName(){return $this->name;}
}
class Ext2
{
private $address="";
private $country="";
public function setAddress($address){$this->address = $address;}
public function setCountry($country){$this->country = $country;}
public function getAddress(){return $this->address;}
public function getCountry(){return $this->country;}
}
class Extender extends ExtensionBridge
{
function __construct()
{
parent::addExt(new Ext1());
parent::addExt(new Ext2());
}
public function __toString()
{
return $this->getName().', from: '.$this->getCountry();
}
}
$o = new Extender();
$o->setName("Mahdi");
$o->setCountry("Al-Ahwaz");
echo $o;
?>
I have read several articles discouraging inheritance in projects (as opposed to libraries/frameworks), and encouraging to program agaisnt interfaces, no against implementations.
They also advocate OO by composition: if you need the functions in class a and b, make c having members/fields of this type:
class C
{
private $a, $b;
public function __construct($x, $y)
{
$this->a = new A(42, $x);
$this->b = new B($y);
}
protected function DoSomething()
{
$this->a->Act();
$this->b->Do();
}
}
Multiple inheritance seems to work at the interface level.
I made a test on php 5.6.1.
Here is a working code:
<?php
interface Animal
{
public function sayHello();
}
interface HairyThing
{
public function plush();
}
interface Dog extends Animal, HairyThing
{
public function bark();
}
class Puppy implements Dog
{
public function bark()
{
echo "ouaf";
}
public function sayHello()
{
echo "hello";
}
public function plush()
{
echo "plush";
}
}
echo PHP_VERSION; // 5.6.1
$o = new Puppy();
$o->bark();
$o->plush();
$o->sayHello(); // displays: 5.6.16ouafplushhello
I didn't think that was possible, but I stumbled upon in the SwiftMailer source code, in the Swift_Transport_IoBuffer class, which has the following definition:
interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream
I didn't play with it yet, but I thought it might be interesting to share.
I just solved my "multiple inheritance" problem with:
class Session {
public $username;
}
class MyServiceResponsetype {
protected $only_avaliable_in_response;
}
class SessionResponse extends MyServiceResponsetype {
/** has shared $only_avaliable_in_response */
public $session;
public function __construct(Session $session) {
$this->session = $session;
}
}
This way I have the power to manipulate session inside a SessionResponse which extends MyServiceResponsetype still being able to handle Session by itself.
If you want to check if a function is public see this topic : https://stackoverflow.com/a/4160928/2226755
And use call_user_func_array(...) method for many or not arguments.
Like this :
class B {
public function method_from_b($s) {
echo $s;
}
}
class C {
public function method_from_c($l, $l1, $l2) {
echo $l.$l1.$l2;
}
}
class A extends B {
private $c;
public function __construct() {
$this->c = new C;
}
public function __call($method, $args) {
if (method_exists($this->c, $method)) {
$reflection = new ReflectionMethod($this->c, $method);
if (!$reflection->isPublic()) {
throw new RuntimeException("Call to not public method ".get_class($this)."::$method()");
}
return call_user_func_array(array($this->c, $method), $args);
} else {
throw new RuntimeException("Call to undefined method ".get_class($this)."::$method()");
}
}
}
$a = new A;
$a->method_from_b("abc");
$a->method_from_c("d", "e", "f");
You are able to do that using Traits in PHP which announced as of PHP 5.4
Here is a quick tutorial for you, http://culttt.com/2014/06/25/php-traits/
One of the problems of PHP as a programming language is the fact that you can only have single inheritance. This means a class can only inherit from one other class.
However, a lot of the time it would be beneficial to inherit from multiple classes. For example, it might be desirable to inherit methods from a couple of different classes in order to prevent code duplication.
This problem can lead to class that has a long family history of inheritance which often does not make sense.
In PHP 5.4 a new feature of the language was added known as Traits. A Trait is kind of like a Mixin in that it allows you to mix Trait classes into an existing class. This means you can reduce code duplication and get the benefits whilst avoiding the problems of multiple inheritance.
Traits
PHP does not yet support multiple class inheritance, it does however support multiple interface inheritance.
See http://www.hudzilla.org/php/6_17_0.php for some examples.
PHP does not allow multiple inheritance, but you can do with implementing multiple interfaces. If the implementation is "heavy", provide skeletal implementation for each interface in a seperate class. Then, you can delegate all interface class to these skeletal implementations via object containment.
Always good idea is to make parent class, with functions ... i.e. add this all functionality to parent.
And "move" all classes that use this hierarchically down. I need - rewrite functions, which are specific.
class A extends B {}
class B extends C {}
Then A has extended both B and C

Categories