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".
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.
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.
What I would like to do is chain a few classes together using "extends". It kinda works, but not like I expected it to. So I must be doing something wrong.
From what I gathered, when you extend a class you inherit all of its properties. So with that in mind I like to make my config file available in all classes. To do this I want to extend all classes on an autoLoader class. This seems logical to me, but correct me if I'm wrong.
I have two classes
AutoLoader
Class AutoLoader {
public $oConf = null;
public function __construct($oConfig) {
$this->$oConf = $oConfig;
}
public function getConf() {
return $this->$oConf;
}
}
other class
Class foo extends AutoLoader {
public function bar() {
var_dump($this->getConf());
}
}
My question is, why is the var_dump NULL.
It is strange to me cause this always returns the conf:
$autoLoader = new AutoLoader($array);
var_dump($autoLoader->getConf());
What am I missing here.
You are extending and inheriting the class structure, not the object instance.
Just take this code as an example:
$foo = new Foo('foo');
$bar = new Foo;
Would you expect $bar to have access to the argument 'foo' passed into the first object somehow? No. Extension doesn't change that.
You should be using composition or dependency injection (e.g. pass an autoloader into the constructor of Foo). Don't make Foo an Autoloader, give it an Autoloader if it needs one. When you extend a class, that new class is also its parent class. That means it could be used in place of the parent class. Anywhere you'd use an Autoloader class, you could substitute Foo instead. Does that make sense? Is Foo an Autoloader? Does $foo instanceof Autoloader == true make any sense? No.
If inheriting class have an own constructor, you are probably not passing the oConfig to the parenting class (Autoloader) in the case.
also, your constructor expects an config.
So you should be doing this in your child constructor if you don't have one:
function __construct($oConfig) {
parent::__construct($oConfig);
// rest of your constructor code here
}
You should create instance of foo class and give into constructor your config variable:
$config = 'My_config';
$foo = new foo($config);
$foo->bar();
Will output:
(string) "My_config"
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();
?>
Wondering if this is possible in PHP Land:
Let's say I have a class as follows:
class myClass{
var $myVar;
...
myMethod(){
$this->myVar = 10;
}
}
and another class:
class anotherClass {
...
addFive(){
$this->myVar += 5;
}
}
The 'anotherClass' is 3500 lines long and I just want the single 'addFive' method to use in myClass.
Is there a way I can import the function and be able to call it in my class and the $this would reference the myClass object?
Is this good/bad practice?
(optional) How does this work in Python? (Just curious as I'm starting to learn Python)
The easiest way to do this is have one class extend the other
class myClass extends anotherClass {
}
The myClass class now has access to all the methods of anotherClass that are public or protected.
If you only want the class to have one method of the other, or it's not practical to have one class extends from the other, there's nothing built into PHP that will allow you to do this. The concept you're looking to Google for is "Mixin", as in Mix In one class's functionality with another. There's an article or two on some patterns you could try to achieve this functionality in PHP, but I've never tried it myself.
Good idea/Bad Idea? Once you have the technique down it's convenient and useful, but costs you in performance and makes it harder for a newcomer to grok what you're doing with your code, especially (but not limited to) someone less familiar with OO concepts.
A better approach would be to move the complex method into its own class. Then both of your classes can instantiate it, pass any necessary data, and call the method.
If your myClass extends anotherClass it inherits all the methods and properties of anotherClass (except those marked private).
class AnotherClass {
protected $myVar;
public function addFive(){
$this->myVar += 5;
}
}
class MyClass extends AnotherClass {
public function __construct() {
$this->myVar = 0;
}
public function myMethod(){
$this->myVar = 10;
}
}
$m = new MyClass;
$m->myMethod();
$m->addFive();
var_dump($m);
prints
object(MyClass)#1 (1) {
["myVar":protected]=>
int(15)
}