PHP class performance over multiple declarations - php

Let's say I have a huge class named Foo.
if I have to call this class several times in different classes, what is the best way to use it?
Note: Bar is not the only class that will use Foo.
Option #1 (create object when its needed):
class Bar
{
public function myMethod($arg)
{
$foo = new Foo();
$something = $foo->doSomething($arg);
return $something;
}
}
Option #2 (create it once):
class Bar
{
protected $foo;
public function __construct()
{
$this->foo = new Foo();
}
}
Option #3 (make Foo static):
class Bar
{
public function myMethod($arg)
{
return Foo::doSomething($arg);
}
}
Option #4:
// tell me the proper way to do it

The best way I'd say is to instantiate Foo outside the Bar class and inject it as a dependency - the best way to do this would be via constructor:
class Bar
{
private $foo;
public function __construct(Foo $foo)
{
$this->foo = foo;
}
}
$foo = new Foo();
$bar = new Bar($foo);
Then do the same for all classes that have Foo as a dependency. You can reuse the instance if it is suitable or you can create a new one if needed.

Related

PHP - How to call function from an upstream object

I have a DB interface object, DBI, that requires authentication. I have an object, foo, that doesn't extend anything. I also have a class bar that extends the DBobject If I have an instance of foo that is a member of bar thus:
$b->$f=new foo;
How can I call somefunction() in $b from a function inside the foo class? I've tried making the somefunction() static, but I don't want the authentication info sprinkled throughout my code. And if I try having foo extend the DBI or bar classes, I wind up with an issue including the files and my foo __construct function fails because the bar class is not found. Is there another construct similar to extends/parent:: that I can use with objects that are just instances amongst each other?
The way that I've done this in the past, is create the Foo object within the Bar object within the __construct(). Then utilize the __call magic method to intercept the methods and see where it is. So the code could look something like this:
public function __call($sMethod, $aArgs) {
if(method_exists($this, $sMethod){
return call_user_func_array(array($this, $sMethod), $aArgs);
}
} elseif(method_exists($this->foo, $sMethod)) {
return call_user_func_array(array($this->foo, $sMethod), $aArgs);
}
}
public function __construct() {
$this->foo = new foo();
}
Then you can call the functions from either foo or bar, even though they are not extended. Just a though, maybe there is an easier way to do this.
** EDIT **
The benefit to this is you don't need to specify whether or not you are calling a method from foo or from bar, they will just "work".
** EDIT **
Based on the comments, you want to do this, correct? Because based on the code below, if you run it it works correctly.
class foobar {
public function test() {
echo 'This is a test';
}
}
class foo extends foobar {
}
class bar {
}
$bar = new bar();
$bar->foo = new foo();
$bar->foo->test();
or the alternative:
class foobar {
public function test() {
echo 'This is a test';
}
}
class foo extends foobar {
}
class bar {
public function testFooBar() {
$this->foo->test();
}
}
$bar = new bar();
$bar->foo = new foo();
$bar->testFooBar();
Both work at long as you know the property name you are setting for the object.
In addition to call_user_func and call_user_func_array, if you want to access methods and properties of the container object (not parent class), you need a reference to it. Here is a similar post.

Never instantiate objects in the constructor?

Is it bad instantiating objects in the constructor like this below?
class Foo
{
public function fooMethod() {
return 'foo method';
}
}
class Too
{
public function tooMethod() {
return 'too method';
}
}
class Boo
{
public $foo;
public $too;
public function __construct()
{
$this->foo = new Foo();
$this->too = new Too();
}
}
If so, how bad can it be? How should it be done properly?
Manually instantiating classes inside another class creates implicit dependencies, which are quite hard to maintain - you will have a hard time detecting what needs to be changed if you ever need to change those Foo and Too classes.
So, a better way of managing dependencies is:
class Foo
{
private $_bar;
function __construct(Bar $bar)
{
$this->_bar = $bar;
}
}
This way, your object dependency is explicit. Another advantage of doing this, is that some PHP frameworks, (Laravel, Zend, Symfony), allow for an automatic dependency resolution. It means, that you don't instantiate your object manually, only via some sort of factory - like this (Laravel):
$foo = App::make('Foo');
And an App factory automatically detects your Foo class dependencies with some reflection magic and injects them appropriately. Other frameworks have similar capabilities, too.
Also, there are some general principles in OOP, called SOLID which help to develop better OOP design. One of them - D, stands for Dependency Inversion. What it means, is that you should avoid hard dependencies, like in your code. Instead, both Foo and Bar classes should depend on an interface, like this:
interface BarInterface
{
function doBar();
}
class Bar implements BarInterface
{
function doBar()
{
print "Doing BAR";
}
}
class Foo
{
/**
* #var BarInterface
*/
private $bar;
function __construct(BarInterface $bar)
{
$this->bar = $bar;
}
}
Now, if you ever need to change that Bar class with something else, all hell won't break loose, if your replacement also implements that BarInterface.
It's not inherently bad.
The downside is that it decreases the "testability" of your class, simply because Boo is now dependent on the existence Foo and Too.
This depends on the size of your project.
On large projects, or long term projects, it should be changed slightly.
Ideally, you would refactor it implement Dependency Injection pattern, and maybe use a Factory to instantiate it.
Some sample code:
interface FooInterface { function fooMethod(); }
class Foo implements FooInterface { function fooMethod(){return 'Foo';} }
interface TooInterface { function tooMethod(); }
class Too implements FooInterface { function tooMethod(){return 'Too';} }
class Boo
{
public $foo;
public $too;
public function __construct(FooInterface $foo, TooInterface $boo)
{
$this->foo = $foo;
$this->too = $boo;
}
}
class BooFactory
{
public static function create()
{
return new Boo(new Foo, new Too);
}
}
It depends of your requirement and the classes.
Let's says that every call to the constructor of Foo/Too you will execute a huge query to the database to get data, in that scenario I would opt to use lazy instantiation.
Of course, it's a good practice to initialize your properties on the constructor, but on real life performance could your enemy.
Example:
class Boo {
private $foo = null;
private $too = null;
public function __construct() {
//Do something else
}
public function getFoo() {
if (is_null($this->foo)) {
$this->foo = new Foo();
}
return $this->foo;
}
public function getToo() {
if (is_null($this->too)) {
$this->too = new Too();
}
return $this->too;
}
public function aMethodThatUsesFoo() {
$foo = $this->getFoo();
$foo->fooMethod();
}
public function aMethodThatDoesntUsesFoo() {
echo "Hello!, I don't need foo or too to execute this method";
}
}
if you use this class only to execute aMethodThatDoesntUsesFoo(), it will never call the constructors of Foo/Too.
$boo = new Boo();
$boo->aMethodThatDoesntUsesFoo();
if you will only execute aMethodThatUsesFoo(), it will only instantiate Foo
$boo = new Boo();
$boo->aMethodThatUsesFoo();
You can do this by static methods as well.

How can I set an object in a parent class and use it in child classes?

Here's some working code:
class A {
public $Foo;
public function GetFoo() {
$this->Foo = 'Bar';
}
}
class B extends A {
function __construct() {
$this->GetFoo();
echo $this->Foo;
}
}
$b = new B(); // Outputs "Bar"
Is there any way I can make this "prettier" (i.e. without the A::GetFoo() method)? I would've thought that wrapping the population of the $this->Foo inside a A::__construct() would work, but it doesn't.
Just to wrap it up, here's what I want: class A instantiates my DB object and that object is usable for every child class of A.
Perhaps you're overriding the parent's constructor without calling in from B?
class A {
protected $Foo = null;
public function __construct() {
$this->Foo = 'Bar';
}
}
class B extends A {
public function __construct() {
parent::__construct();
echo $this->Foo;
}
}
From the PHP manual:
"Class properties must be defined as
public, private, or protected. If
declared using var without an explicit
visibility keyword, the property will
be defined as public."
So, your class B can see $this->Foo. You don't have to call GetFoo() first. You must, however, call the parent constructor first if you need to reference $this->Foo inside of your constructor for class B.

Parent class variable

Here is my basic example:
class Foo {
public $toy = "car";
public function run() {
$this->toy = "train";
$bar = new Bar();
$bar->run();
}
}
class Bar extends Foo {
public function run() {
echo $this->toy;
}
}
$foo = new Foo();
$foo->run();
For some reason it will always echo car not train. What is the reason for this?
Foo run creates an object Bar, which has toy, initialized with car. So, the result is car, as expected.
Because you are creating a new Bar instance inside Foo::run. Changes you make to the Foo instance have no effect on the Bar instance. They are two different instances.
You can also see it this way: Whenever you instantiate an object from the child class, a new instance of the parent class will be created.
You can make the property static though, then it will be shared between all instances:
class Foo {
public static $toy = "car";
public function run() {
self::$toy = "train";
$bar = new Bar();
$bar->run();
}
}
class Bar extends Foo {
public function run() {
echo self::$toy;
}
}
What you do is "delegation": You create a new instance and call this instead of the parents method. What you are looking for is
parent::run();
This will call the parents method.

PHP Inheritance: If A then Must Set B

So, I tried to Google this but don't know what this kind of situation is called...
I'm working on my first use of class inheritance, where a parent class defines a set of methods and then several other classes extend that parent.
What I was wondering, is it possible to do something like this:
class foo {
private bar = false;
private baz = NULL;
}
Now let's say I have:
class foobar extends foo { }
I'd like to be able to have a condition in "foo" that says if any class extends "foo" and sets "bar = true" then "baz" must be set (ie. not null), or else throw an exception.
Is such a thing possible?
This seems possible by using a magic setter function that you define in foo, but comes with a serious caveat. Magic getters and setters fire only when you access an inaccessible property.
When operating inside a class, all properties, no matter whether declared private, public or protected, are usually accessible, so the magic getter and setter functions will not fire. There is only one exception: Properties that were declared private in an ancestor class. Those will be hidden (inaccessible) to descendant classes, and the magic functions will fire.
This means that you will need to declare bar and baz in foo. It wouldn't work if you would declare them in foobar, because they would become accessible.
With this in mind, the following will work as you want:
class foo {
private $bar = false;
private $baz = NULL;
public function __set($name, $value)
{
if ($name == "bar")
{ if ($value == true)
{
if ($this->baz == null)
throw new Exception();
}
}
}
}
class foobar extends foo {
function test()
{
$this->bar = "TEST";
}
}
$foobar = new foobar();
$foobar->test(); // Will throw an exception
If you want to read bar and baz from within foobar, you will also need to define a magic getter function.
Just run a construct function in the second class.
class foo {
private bar = false;
private baz = NULL;
public function __construct() {
if ($this->bar && is_null($this->baz)) // throw exception
}
}
class foobar extends foo {
public function __construct($baz) {
$this->baz = $baz;
$this->bar = true;
parent::__construct(); // Now run the parent's constructor
}
}
Many different ways to do it...

Categories