I have some variables and functions which need to be available for different classes. Hence, I put all definitions (Variables / functions) to some class:
class common_functions() {
function __construct() {
$this->define_variables();
$this->connect_to_database();
echo "EXEC";
}
function define_variables() {
$this->var1 = "foo";
$this->var2 = "bar";
}
function connect_to_database() {
mysql_connect(...)
}
function do_something() {
//...
}
}
which is the parent of all the others:
class orders extends common_functions {
private $order_item;
function __construct() {
parent::__construct()
$order_item = new item();
}
function show_something() {
echo $order_item->get_something()*$this->var1;
}
}
class item extends common_functions {
pivate $some_number;
function __construct() {
parent::__construct()
$this->number = 123;
}
function get_something() {
return $this->var2*$this->var1*$this->number;
}
}
class some_other_class extends common_functions {
function __construct() {
parent::__construct()
}
// ..
}
However, as executing
$o = new order();
$o->show_something();
the output is
EXEC
EXEC
since the common_functions class is called twice. Especially also mysql-connection is established several times which is quite unefficient.
What I need is some technique so that all the functions and variables (and database-connections) from common_functions are available to all classes without the drawback that e.g. connect_to_database() is executed several times. Some ideas?
If I were you I'd redesign my implementation. Why? Well because it seems to me that neither some_other_class nor item is a common_functions. However they both have common_functions. Thus I'd create only one instance of that class and pass it into the constructor.
Something like this:
class Item {
private $common_functions;
public function __construct($common_functions) {
$this->common_functions = $common_functions;
}
}
class Order {
private $common_functions;
public function __construct($common_functions) {
$this->common_functions = $common_functions;
}
}
What happens now is that both the item and some_other_class objects has a dependency which we inject to common_functions. This obviously means that you have to pass some values to the methods in common_functions but that is a very small price to pay considering what you gain from not inheriting common_functions, like only one db-connection.
Inheritance is cool but in practice it isn't used all that much. It's often much better compose objects than to inherit a bunch of stuff. When designing OO-classes always consider wether an objects relation is an is a or has a relation.
So what you could do using the above example of the orders constructor is the following:
class orders {
private $common_functions;
public function __construct($common_functions) {
$this->common_functions = $common_functions;
$order_item = new Item($common_functions);
}
}
That way both item and order will share the same common_functions object.
Assign a static null variable initially in parent class and check if its null or not.
class common_functions {
private static $dbInstance = null;
function __construct() {
if(self::$dbInstance == null) {
self::$dbInstance = $this->connect_to_database();
}
}
...
return the the database connection handler or any other than the null value in $this->connect_to_database();
Related
I'm a bit confused on whether or not this is possible. I've checked a couple of posts here on SO and they don't really explain what I'm looking for.
I have 3 classes. One main class and two classes extending that main class. (see code below). Is it possible to run a method in one of the two extended classes from it's sibling (the other extended class)?
If it's not possible, how can I change my code to accomplish what I'm doing in the example below?
DECLARATION
class A {
public function __construct() {
//do stuff
}
}
class B extends A {
private $classb = array();
public function __construct() {
parent::__construct();
//do stuff
}
public function get($i) {
return $this->classb[$i];
}
public function set($i, $v) {
$this->classb[$i] = $v;
}
}
class C extends A {
public function __construct() {
parent::__construct();
//do stuff
}
public function display_stuff($i) {
echo $this->get($i); //doesn't work
echo parent::get($i); //doesn't work
}
}
USAGE
$b = new B();
$c = new C();
$b->set('stuff', 'somestufftodisplay');
$c->display_stuff('stuff'); // <----- Displays nothing.
Your code shows an additional problem apart from the main question so there are really two answers:
No, you cannot run a method from a sibling class in another sibling class. If you need that, the method should be in the parent class. The same applies to properties.
You cannot use the value of a property from one object in another object, even if they are both of the same class. Setting a property value in one object sets its value only there as different objects can have the same properties with completely different values. If you need to share the value of a property between the objects and also be able to modify it, you should use a static property. In this case you would have to define that in the parent class, see my previous point.
So to make it work, you would need something like
class A {
private static $var = array();
public function get($i) {
return self::$var[$i];
}
public function set($i, $v) {
self::$var[$i] = $v;
}
}
class B extends A {
}
class C extends A {
public function display_stuff($i) {
echo $this->get($i); // works!
}
}
$b = new B();
$c = new C();
$b->set('stuff', 'somestufftodisplay');
$c->display_stuff('stuff');
An example.
Imagine two classes which share almost the same exact methods and properties, both extending a parent class, but the differences are minimal.
class fields {
public function __construct() {
global $id;
$this->id = $id++;
}
}
class input extends fields {
public function __construct() {
parent::__construct();
}
public function draw() {
echo '<input>';
}
}
class textarea extends fields {
public function __construct() {
parent::__construct();
}
public function draw() {
echo '<textarea>';
}
}
I'm thinking it would be more efficient to rewrite the textarea class in this psuedo-code fashion:
class textarea extends fields {
public function __construct() {
$this = new input(); // <<------
}
public function draw() {
echo '<textarea>';
}
}
Basically, I'm unsure how this would best be done so that the class acts like the class from the first example.
In essence, I would like to do the following using OOP, but be able to use the object as it can be in the first example above (be able to call the possibly overloaded methods, have different properties, etc.):
function a() {echo '123';}
function b() {a();}
I have just copied the entire class and modify a few lines, but I feel it is wasteful.
Final Answer
Thanks to those people, here is the combined answer with example calls:
abstract class fields {
private static $masterid = 0;
public function __construct() {
$this->id = self::$masterid++;
}
}
class input extends fields {
public $data;
public function __construct($new = '') {
parent::__construct();
if ($new) $this->data = $new;
else $this->data = 'Hello';
}
public function draw() {
echo '<input>'.$this->export().'</input>';
}
public function export() {
return 'ID '.$this->id.' = '.$this->data;
}
}
class textarea extends input {
public function __construct($new = '') {
parent::__construct($new);
}
public function draw() {
echo '<textarea>'.$this->export().'</textarea>';
}
}
$a = new textarea();
$a->draw();
$a = new textarea('World');
$a->draw();
$a = new input('!');
$a->draw();
//Outputs:
// <textarea>ID 0 = Hello</textarea>
// <textarea>ID 1 = World</textarea>
// <input>ID 2 = !</input>
Make the fields class an abstract class, and like Darren suggested, make the 'draw' method a function of the fields class.
Now heres the trick, you want the input class to extend fields, but override the draw method. This will allow you to customize the functionality of that method, and you can still call the parent variation from within it.
Finally, since the textarea class is going to have many similarities to the input class, make textarea extend input. Thereby inheriting the properties and methods of both fields and input.
Make the "fields" class have a draw method:
public function draw($msg) {
echo $msg;
}
Then in the textarea or input class put:
parent::draw("<input>");
This cuts down on the number of methods you have, and can call one method for both types of field.
Also in your "fields" class, change the id code to be like this:
public $id
public function __construct($id) {
$this->id = $id;
}
Then in the subclass:
parent::__construct(1); //Or whatever ID you want
The way you have it, ID is the same value every time you set it, which will result in every subclass of fields having the same id. This way each subclass will have a seperate ID.
Also because I'm nice, here's it all put together:
public class field {
$id;
public __construct($id) {
$this->id = $id;
}
public function draw($msg) {
echo $msg;
}
}
public class input extends field {
public __construct() {
parent::__construct(1);
parent::draw("<input>");
}
}
public class textarea extends field {
public __construct() {
parent::__construct(2);
parent::draw("<textarea>");
}
}
That's how I'd put it together from what you've said. I may have mistaken what you were asking for though. Can you tell I'm primarily a Java programmer from that?
It's not exactly clear what you want to do. For the example you've given, I think the structure is OK, but you should make a few changes, particularly with the constructor. I think the constructor should be abstract, with an abstract method draw().
abstract class fields {
// Use a static member to keep track of id's instead of making it global
private static $id = 0;
// Use an instance variable to keep track of a particular instance's id
private $myId;
public function __construct() {
// Increment the static ID & assign it to the instance id.
$this->myId = self::$id++;
}
// Provide a public getter, so that the ID can't be changed
// externally to this class
public function getId() {
return $this->myId;
}
public abstract draw(); // Make sure all sub classes implement a draw() method.
}
class input extends fields {
// Don't need to call the parent constructor if you're not adding anything
// else. It will be called automatically.
public function draw() {
echo '<input>';
}
}
class textarea extends fields {
public function draw() {
echo '<textarea>';
}
}
Basically this is what i want to do:
<?php
class App {
public $var = "main-class";
public function load() {
$this->var = "child-class";
$child = new Child;
$child->echo_var();
}
}
class Child extends App {
public function echo_var() {
echo $this->var;
}
}
$app = new Child;
$app->load();
?>
It outputs "main-class", i want it to output "child-class" without having to modify the child class (because i want it to be sort of a "clean" and dynamic class).
I accept suggestions for another course of action
PS: This is part of an Small MVC Framework i'm trying to develop.
There are two ways that you could do this. Both are going to need to use constructors. With the first one, the child will declare itself when created
<?php
class App {
public $var = "main-class";
public function __construct($var=null) {
if($var !== null) {
$this->var = $var;
}
}
public function load() {
$child = new Child ();
$child->echo_var();
}
}
class Child extends App {
public function __construct(){
parent::__construct("child-class");
}
public function echo_var() {
echo $this->var;
}
}
$app = new Child();
$app->load();
?>
The second one allows the parent to declare the name of the child.
<?php
class App {
public $var = "main-class";
public function __construct($var=null) {
if($var !== null) {
$this->var = $var;
}
}
public function load() {
$child = new Child ("child-class");
$child->echo_var();
}
}
class Child extends App {
public function echo_var() {
echo $this->var;
}
}
$app = new Child();
$app->load();
?>
Both of those examples work and do what you want, I believe.
This isn't how inheritance works - By creating a new Child object, its data members are all initialized with their default values. When you do $this->var = "" in the parent class, you're setting the data members for the $app object, not the $child object.
You can modify the child class to incorporate a constructor that accepts parameters, and that constructor would set its data members properly. To achieve something similar to what you want, you can use constructors:
<?php
class App {
public $var = "main-class";
public function __construct() {
$this->var = "child-class";
}
public function load() {
$child = new Child;
$child->echo_var();
}
}
class Child extends App {
public function __construct()
{
parent::__construct();
}
public function echo_var() {
echo $this->var;
}
}
$app = new App;
$app->load();
I find it very strange that your parent class instanciates it's child. Generally, you would instanciate the child, and you get all the functionality of the parent.
$app = new Child();
$app->load();
The problem is that you actually have 2 different instanciations. You have an object of App and it's holding a separate object of Child.
The other way to do this would be to make $var a static variable and then it would be available independent of the instantiation. I don't generally recommend making properties static though. It's generally considered bad form (for numerous reasons).
HI!
basicly what I ask u to tell me is how to put a "parent" reference into the object
I need it to make example of "extracting method with method object" - one of mostly used refactoring in Java or C#
in Java refering to "parent object" looks like this:
class someClass {
MyObject myObj = new MyObject(this);
}
and thats it :)
but I dont know, how to do the same in PHP
maybe if its imposible you would tell me how you extract your methods out of your classes to new class, that has to do what that method did.
so in other words...
1 - I have class with big and hard to read / refactor method.
2 - I extract that method to new class, giving it fields in place of parameters and method like "execute" - to proced all that this class has to do for me.
3 - I put object of my class to my old function class and I call its method "execute" - so the all logic that was in my_big_method is done.
The best method is inheritance, where you call the parent keyword to access the parent class like so:
class Child extends Father
{
public function __construct()
{
parent::__construct();
}
}
class Father
{
public function __construct()
{
echo "Father says hello";
}
}
new Child();
using the parent keyowrd you can call the constructor like so parent::__construct()
Example: http://codepad.org/kW6dfVMs
if your looking at Injection then you could do something like this.
class Master
{
private $Slave;
public function __construct(Slave $Slave)
{
$this->Slave = $Slave;
}
}
$Master = new Master(new Slave);
if your unsure of the object that should be passed in but you know that it should have a certain interface / set of methods you can get a little more complex and do something like so:
class Master
{
private $Slave;
public function __construct(ISlave $Slave)
{
$this->Slave = $Slave;
}
}
interface ISlave
{
//Declaration of methods
}
class SomeSlaveObject implements ISlave{}
$Master = new Master(new SomeSlaveObject);
Have you tried using the $this keyword?
Easiest way is to pass a reference to the parent object in the constructor, though I may be misunderstanding your goal.
class myClass {
private $parent = false;
function __construct ($parent=false) {
$this->parent = $parent;
}
}
If you are extending a base class, you can use the parent operator:
class otherClass {
function someMethod() {
return 1;
}
}
class myClass extends otherClass {
function aMethod() {
// parent keyword here would refer to "otherClass"
return $this->someMethod();
}
}
Check out the doc on parent: http://php.net/manual/en/keyword.parent.php
PHP version of your example:
class someClass {
public function createObject() {
$myObj = new MyObject($this);
}
}
not much different than java, just less types and more $ signs.
"parent" is a keyword in php, like the java "super" so your question is a little confusing.
I tried with "$this", but "php guy" in my company told me that I cant use $this that is not refering to field or function of current class (that it cant refer to whole class)
my code looks like this:
class to refactor:
class AccountBeforeRefactoring {
// (...)
public function makeTransfer($amount, $destinationAccount){
$transferFee = 1;
if ($amount > 1000){
$transferFee = 1 + $amount * 0.0001;
}
$this->connectToElixir();
// (...)
// (...)
// (...)
$this->debit($amount + $transferFee);
}
}
and it becomes:
class extracted - that was my method:
class TransferMaker {
private $account;
private $amount;
private $destinationAccount;
private $transferFee;
public function __construct($source, $amount, $destinationAccount){
$this->account = $source;
$this->amount = $amount;
$this->destinationAccount = $destinationAccount;
$this->transferFee = 1;
}
public function make(){
if ($this->amount > 1000){
$this->transferFee = 1 + $this->amount * 0.0001;
}
$this->account->connectToElixir();
// (...)
// (...)
// (...)
$this->account->debit($this->amount + $this->transferFee);
}
}
is constructor there made in right way?
and now I need, to make object of MakeTransfer inside my Account class - I tried it this way - is it ok?
class Account {
// (...)
public function makeTransfer($amount, $destinationAccount){
new TransferMaker($this, $amount,
$destinationAccount).make();
}
}
and again - can I just this "$this" just like this? ;)
will my code work? it does compile in Eclipse, but that can mean none.
sorry for that weird subject but I don't know how to express it in an other way.
I'm trying to access a method from a calling class. Like in this example:
class normalClass {
public function someMethod() {
[...]
//this method shall access the doSomething method from superClass
}
}
class superClass {
public function __construct() {
$inst = new normalClass;
$inst->someMethod();
}
public function doSomething() {
//this method shall be be accessed by domeMethod form normalClass
}
}
Both classes are not related by inheritance and I don't want to set the function to static.
Is there any way to achieve that?
Thanks for your help!
You can pass a reference to the first object like this:
class normalClass {
protected $superObject;
public function __construct(superClass $obj) {
$this->superObject = $obj;
}
public function someMethod() {
//this method shall access the doSomething method from superClass
$this->superObject->doSomething();
}
}
class superClass {
public function __construct() {
//provide normalClass with a reference to ourself
$inst = new normalClass($this);
$inst->someMethod();
}
public function doSomething() {
//this method shall be be accessed by domeMethod form normalClass
}
}
You could use debug_backtrace() for this. It is a bit iffy but for debugging purposes it is usefull.
class normalClass {
public function someMethod() {
$trace = debug_backtrace();
$trace[1]['object']->doSomething();
}
}
You have a few options. You can use aggregation like so
class normalClass
{
protected $superClass;
public function __construct( superClass $superClass )
{
$this->superClass = $superClass;
}
public function someMethod()
{
$this->superClass->doSomething();
}
}
class superClass
{
public function __construct()
{
$inst = new normalClass( $this );
$inst->someMethod();
}
public function doSomething()
{ //this method shall be be accessed by domeMethod form normalClass
}
}
Or just a straight-up setter
class normalClass
{
protected $superClass;
public function setSuperClass( superClass $superClass )
{
$this->superClass = $superClass;
}
public function someMethod()
{
if ( !isset( $this->superClass ) )
{
throw new Exception( 'you must set a superclass' );
}
$this->superClass->doSomething();
}
}
class superClass
{
public function __construct()
{
$inst = new normalClass();
$inst->setSuperClass( $this );
$inst->someMethod();
}
public function doSomething()
{ //this method shall be be accessed by domeMethod form normalClass
}
}
Depending on your use case, you might want to pass the instance to the function only:
class normalClass {
public function someMethod($object) {
$object->doSomething();
}
}
If normalClass::someMethod() can be called by multiple, distinct $objects, this might be the better choice (instead of providing the $object to the whole normalClass instance).
But regardless of that you might consider creating an Interface to use for type hinting:
interface ISomethingDoer {
public function doSomething();
}
class normalClass {
public function someMethod(ISomethingDoer $object) {
# Now PHP will generate an error if an $object is passed
# to this function which does not implement the above interface.
// ...
class superClass implements ISomethingDoer {
// ...
woah I had the same problem than you but instead of going with the so simple pass the reference to the object, I went with an event manager, Basically, when something would happen in the normal class, it would trigger an event which was listened by a class and that said class(the listener) would call the super class to execute that functionality and if necessary pass it new arguments.
Anyways, whether you pass it as a parameter to your object or you go with an event based approach, both solutions work. Choose the one you prefers.
For more information on events, sympony explains it quite good.
http://symfony.com/doc/current/components/event_dispatcher/introduction.html