I have an object of wich I just know the Class name, let's say "A". I'm trying to acess the properties of this object. Unfortunately I'm trying to access them from another object instance, created by the first object, of a completely different class (nor extended or related). Simplified code below to explain the situation.
Class A {
public $var; //some important stuff
function createObjectB() {
$b = new B();
}
}
Class B {
// a totally different class not related with A
}
This is third party code of a component in a CMS, so I can't mess with core code (or at least I think?) trying to pass the property along with the B created object without causing errors at a later time if this component gets updated.
I can acess the object from Class B due to a "layout-template" file later called in the B class, that won't be touched if the core code get's updated. This way I can't really touch neither of these classes.
Using a debug_backtrace() from object B I can see a few step back the properties of the object I need, but I think it's rather hacky to use the function this way to obtain the info I need, and I think that it's quite an intensive function to use too.
I'm quite a novice in PHP, is it just plain wrong what I'm trying to achieve? Is there any better way?
Heredity is a well-established programming principle, and PHP makes use of it in your object modeling. This principle will affect the way many classes and objects relate to each other.
For example, when extending a class, subclass inherits all public and protected methods of the parent class. Unless a class overwrite these methods retain their original functionality.
This is useful for defining and abstracting functionality and allows the implementation of additional functionality in similar objects without the need to reimplement all of the shared functionality.
Important: Unless autoloading is used, then classes must be defined before being used. If a class extends another, then the parent class must be declared before the child class structure. This rule applies to classes that inherit from other classes and interfaces.
<?php
class Foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
public function printPHP()
{
echo 'PHP is great.' . PHP_EOL;
}
}
class bar extends Foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}
$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // Salida: 'Foo: baz'
$foo->printPHP(); // Salida: 'PHP is great'
$bar->printItem('baz'); // Salida: 'Bar: baz'
$bar->printPHP(); // Salida: 'PHP is great'
?>
You must to know that you can generate new objects into another classes. But you can inherit all the properties from class A to the class B without create a new instance. For example:
<?php
Class A {
public function something() {
$var = 'Hello!';
return $var;
}
}
Class B extends A {
function createObjectB() {
echo $this->something().' I am learning classes in php';
}
}
$b = new B;
$b->createObjectB();
?>
Please visit this page http://php.net/manual/es/language.oop5.inheritance.php for more about.
Related
I have an object with some protected fields and a method that uses them. The method doesn't do exactly what I need it to do, but I cannot change the original code since I am writing an add-on.
Is it somehow possible to extend the class and override the method so that I could call it on predefined objects of the original class? I thought about monkey patching but apparently it is not implemented in php.
You can override a method by extending the parent class, initiating the new class instead of the parent class and naming your method exactly the same as the parent method, that was the child method will be called and not the parent
Example:
class Foo {
function sayFoo() {
echo "Foo";
}
}
class Bar extends Foo {
function sayFoo() {
echo "Bar";
}
}
$foo = new Foo();
$bar = new Bar();
$foo->sayFoo() //Outputs: Foo
$bar->sayFoo() //Outputs: Bar
I hope below stategy will be works. asume that class is Foo and method is bar(). for override bar() method you have to make customFoo class as mentioned below.
class CustomFoo extends Foo{
public function bar(){
parent::bar();
}
}
I dont know actually what you need because you dont have explained in detail. Still I have tried my best. :)
Try creating a child class that extends the base or parent class that the object currently derives from.
Create a new method with exactly the same name as the method in the Parent class and put your logic in there.
Now instantiate your object from your new class, you would have succeeded in overriding that particular method and still have access to the methods and properties of the base class.
Problem is, once you've loaded the class, you can't officially unload it, and you do need to load it in order to extend it. So it's pretty tied up. Your best bet is to either hack the original class (not ideal) or copy paste the original class definition into a new file:
class ParentClass {
//Copy paste code and modify as you need to.
}
Somewhere after the bootstrapping of your framework:
spl_autoload_register(function ($class) {
if ($class == "ParentClass") { //Namespace is also included in the class name so adjust accordingly
include 'path/to/modified/ParentClass.php';
}
},true,true);
This is done to ensure your own modified class will be loaded before the original one.
This is extremely hacky so first check if the framework you're using has native support for doing this.
Suppose I have,
interface Foo {
}
class FooClass implements Foo {
}
Is there a way I can add some logic to the interface outside of the FooClass so that I can do this:
$foo = new FooClass();
$foo->Bar();
where Bar is a method applicable to all Foos? What I am asking for is something similar to extension methods in C# but in my case I want to extend just interfaces.
I know I can add a custom static function Bar which accepts Foo as parameter but I want to know if there's anything in PHP which gives me the $foo->Bar() sugar.
Edit: I think I wasn't clear enough. I have a couple of similar interfaces (and many classes implementing them) from an external library. Changing them to abstract classes is not an option for me.
I think the closest you can get with PHP are the so called traits.
<?php
interface Foo {
}
trait myTraits {
function bar() { echo "BarMethod"; }
}
class FooClass implements Foo {
use myTraits;
}
$foo = new FooClass();
$foo->Bar();
?>
This will output "BarMethod".
I have a project that has quite a lot of classes, stored as separate files, and some of them inherit the same parent class. The class in question is a settings class, it holds user preferences and such.
I am wondering: What is the correct way to have these classes use the same information?
For example...
Do I use extends each time? Or does extends execute and redefine code each time?
Do I instantiate the classes in new variables, like $this->example = new Class();, in each of the inheriting classes __construct() function? Or does that use more memory?
Do I somehow instantiate the classes in new variables in a different class and pass the variables to the inheriting classes via function parameters? Or is that bad form?
I just don't know!
settings.php looks like this:
class Settings
{
public $pref = array();
function __construct() {
$this->pref['name'] = 'John';
$this->pref['age'] = 21;
$this->pref['display_dob'] = true;
...
}
}
The inheriting classes look like this:
class ShowPerson extends Settings
{
public function display()
{
echo $this->pref['name'], ' ';
echo $this->pref['age'], ' years old';
if ($this->pref['display_dob'] == true) {
echo ' born ' . $this->pref['birth_date'], ' ';
}
...
}
}
No. Inheritance is for extending classes that belong to the same type of class. For example:
Animal < Mammal < Primate < Human
How granular you make it (i.e. how many times you extend) depends on your needs.
The point, however, is that if a class has nothing to do with another class, or if they are only tangentially related, then they should not inherit from each other.
Something like settings should be passed to the class (i.e. the object).
So, paraphrasing the code in your question, you could do it like this:
// The settings should be created outside
$settings = new Settings;
// The settings are then provided to the new object
// Here we just pass it to the constructor, but you
// could also have something like a `useSettings()`
// method that sets it
$person = new Person($settings);
Extending code, like in your question, creates a tangled mess that you will be unable to untangle easily as your code matures. Writing self-contained units of code, and making use of interfaces, you can work on them separately and not worry about what the rest of your code does.
Can we create an object of a class inside another class in php?I hav made a small application in php,now I am trying to convert the entire code in a class-methods-object fashion.I m now Confused.
You you can do that, but whether you should depends on the lifetime of the two classes and their relation to each other. Basically, you have the choice between Composition and Aggregation.
Composition
You use Composition when the created object has a lifetime equal or less than the object that will use it, e.g.
class A
{
private $belongsToAOnly;
public function __construct()
{
$this->belongsToAOnly = new IBelongToA;
}
}
In this case A "owns" IBelongToA. When A is destroyed, IBelongToA is destroyed too. It cannot live on it's own and is likely just an implementation detail of A. It could be a ValueObject like Money or some other Data Type.
From Craig Larman's "Applying UML and Patterns":
the composite is responsible for creation and deletion of it's parts - either by itself creating/deleting the parts, or by collaborating with other objects. Related to this constraint is that if the composite is destroyed, its parts must be destroyed, or attached to another composite"
Aggregation
You use Aggregation when the lifetime of the created object is longer:
class A
{
private $dbAdapter;
public function __construct(DbAdapter $dbAdapter)
{
$this->dbAdapter = $dbAdapter;
}
}
Unlike with Composition, there is no implication of ownership here. A uses DbAdapter but when A is destroyed DBAdapter lives on. It's a "uses" relationship instead of an "owns" relationship.
Creator Pattern (GRASP)
A good heuristic to decide when an object may create another object at runtime can be found in the Creator Pattern in GRASP which states that objects may create other objects when
Instances of B contains or compositely aggregates instances of A
Instances of B record instances of A
Instances of B closely use instances of A
Instances of B have the initializing information for instances of A and pass it on creation.
Alternatively, you can create Factories whenever you need to create instances of something and aggregate the factory instances, which will give you a cleaner separation of collaborators and creators.
Testability
An issue stemming from creating objects within objects is that they are difficult to test. When you do unit-testing, you usually do not want to recreate and bootstrap the entire system environment but concentrate on testing just that particular class in isolation. To do that, you swap out dependencies of that class with Mock Objects. You cannot do that when you use Composition.
So depending on what the collaborators of a class do, you might want to decide to always use Aggregation, because then you are effectively doing Dependency Injection all the way, which will allow you to swap out collaborators of a class easily, for instance to replace them with Mocks.
Yes you can, but that increases code coupling and makes testing harder.
I'd suggest creating it outside the class and pass it as an argument (it is called Dependency Injection).
class Foo
{
}
class Bar
{
public function __construct(Foo $foo)
{
$this->foo = $foo;
}
}
$foo = new Foo();
$bar = new Bar($foo);
yes you can do it ..
here is one example..
a.php
<?php
class a{
public function function_1(){
echo "b";
}
}
?>
b.php
<?php
include_once ("a.php");
class b{
public function function_b(){
$a = new a;
$a->function_1();
}
}
$b= new b;
$b->function_b();
?>
Yes, you can create an object from a specific class from inside another class.
class SomeClass{
}
class SomeOtherClass {
function hello(){
$o = new SomeClass;
}
}
Yes, you can also define a function in a class. You can do everything in a class in php, please post your code where you confused.
Examples:
Object in a class.
class Foo
{
public $bar; // another object!
public __construct()
{
$this->bar = new Bar();
}
}
(global)Function in a class
<?php
class Foo
{
public function __construct()
{
function __construct()
{
echo "Yes, I'm a global function!";
}
}
}
new Foo();
__construct();
?>
I'm officially mentally retarded. [Let me explain]
I've never really given classes and their relationship any thought until today. I'm trying to figure out something that seems to be pretty obvious but since I'm stupid I can't see it.
Let's say I have a Core Class that will be extended from different files. How can children classes call functions from other siblings (that is if those are considered childs at all).
Sample Code: (don't kill me)
class cOne {
public function functionOne(){
echo "something";
}
}
Then on another file, I say:
class cOneChildOne extends cOne {
public function functionOne(){
echo "something from child one";
}
}
And yet on another file I say:
class cOneChildTwo extends cOne {
public function functionOne(){
echo "something from child two";
}
}
How would I have to create a new object, and when, so that I'm able to access functions from both childs and the parent class in a fashion similar to $newObject->Children->function(); I'm seriously considering the option that I've completely lost my brain today and can't think straight.
I've obviously doing something wrong since: $newObject = new cOne; creates the object but then the code from one of the subclasses is unable to access anything that's not directly in the core class or in itself.
Thanks
You can collect child instances in masters class static array
class C1{
static public $childs=array();
function __construct(){
self::$childs[]=$this;
}
}
class C1C1 extends C1{
function hi(){
echo 'hi from C1C1 <br />';
}
}
class C1C2 extends C1{
function hi(){
echo 'hi from C1C2 <br />';
}
}
$c1 = new C1C2();
$c2 = new C1C2();
$c3 = new C1C1();
$c4 = new C1C1();
$c5 = new C1C1();
$c6 = new C1C1();
foreach(C1::$childs as $c){
$c->hi();
}
The parent class cOne has no knowledge of the classes that extend it in php, so while you can call to the parent from a child class using parent::someFunction(), you cannot call the child classes from the parent. You also could not call functions from other classes that extend cOne from a class that extends cOne, also because cOne has no knowledge of classes that extend it.
You do have a fundamental misunderstanding.
Your two subclasses are different classes with a common ancestor. Each child essentially has knowledge of the parent, but the parent has no knowledge of the children, and the children have no knowledge of each other.
If you want child1 to be able to call methods of child2, then there is something wrong with your design. One solution would be to move the method from child2 to the parent class, so that child1 would also inherit that method.
you can use parent::functionOne(); to call functions of parent class from child class.
you can't call child classes' functions from parent class.
Help me or shoot me!!
Bang!!! =o)=o)=o)
When you create instance of class it only knows its methods and methods from its parents.
There is no way you can tell that there are other class who are extending same parent.
As kgb says, you can't create one object that will give you "access" to both sibling class' behaviour. If you instantiate a cOneChildOne, you'll get something that outputs "something from child one" (*). You could, if you use parent::functionOne(), copy cOne's behaviour, maybe to return "something\nsomething from child one" or whatever.
(*) Don't do this. Rather, return a string:
public function functionOne(){
return "something from child one";
}
This lets you compose your functions, output them to files, etc.
You could always just call cOneChildTwo from inside cOneChildOne statically if this suffices your requirement. $this in a method always points to the callee object (that's how parent::__construct() works), so you could use the callee's state inside cOneChildTwo for extended behaviour.
However, this would possibly imply that you'd require wrapper methods for every sibling's method. This is nothing Reflection can't solve though.
i think you're looking at object inheritance, classes and their relationships the wrong way.. what you've said is not really how inheritance in object oriented programming works. when you want to call a method/function of some other object, may it be an instance of the same class or not, what you need is a reference to that object that you are going to call. the keyword here is pass a reference. the one wanting to call must have a reference to the object it wants to communicate to.
child1.communicateWithAnotherChild(someOtherChild)
Why can't you have a static Array $children in the cOne class, and the __construct() methods for the classes that extend it just call cOne::addChild($this)? They could each implement a getChildren function which sends the request on to the superclass - Shouldn't that work?