How to Add a Method to an Existing Class in PHP

How to add a method to an existing class in PHP?

If you only need to access the Public API of the class, you can use a Decorator:

class SomeClassDecorator
{
protected $_instance;

public function myMethod() {
return strtoupper( $this->_instance->someMethod() );
}

public function __construct(SomeClass $instance) {
$this->_instance = $instance;
}

public function __call($method, $args) {
return call_user_func_array(array($this->_instance, $method), $args);
}

public function __get($key) {
return $this->_instance->$key;
}

public function __set($key, $val) {
return $this->_instance->$key = $val;
}

// can implement additional (magic) methods here ...
}

Then wrap the instance of SomeClass:

$decorator = new SomeClassDecorator(new SomeClass);

$decorator->foo = 'bar'; // sets $foo in SomeClass instance
echo $decorator->foo; // returns 'bar'
echo $decorator->someMethod(); // forwards call to SomeClass instance
echo $decorator->myMethod(); // calls my custom methods in Decorator

If you need to have access to the protected API, you have to use inheritance. If you need to access the private API, you have to modify the class files. While the inheritance approach is fine, modifiying the class files might get you into trouble when updating (you will lose any patches made). But both is more feasible than using runkit.

Adding methods to existing class without much changes

Try using a Trait. It basically lets you reuse (or include in your case) functions in a class.

Code example

<?php
trait SayHello {
public function sayHello() {
echo 'Hello';
}
}

class Base {
use SayHello;
}

$o = new Base();
$o->sayHello();
?>

How to add a new method to a php object on the fly?

You can harness __call for this:

class Foo
{
public function __call($method, $args)
{
if (isset($this->$method)) {
$func = $this->$method;
return call_user_func_array($func, $args);
}
}
}

$foo = new Foo();
$foo->bar = function () { echo "Hello, this function is added at runtime"; };
$foo->bar();

In PHP, how do you add functions from an include file to an existing class or object instance?

You can use Traits

trait PageFunctions {

public function ajax() {}
public function action() {}
public function logic() {}
public function css() {<? ?>}
public function html() {<? ?>}
public function js() {<? ?>}
}

class Page {
use PageFunctions;
}

$page = new Page();
$page->js();

If you need to overwrite a trait function, you can

class CustomPage {
use PageFunctions;

public function html() {
echo "<div>Welcome, <?=$this->userName?>!</div>";
}
}

$customPage = new CustomPage();
$customPage->html(); //output <div>Welcome, username!</div>

How do I append a line to a method of a class file in php?

Well I solve it by a regex like this :

/function register\(.*\)\s*{/

First I find the position of the first line of the method in the class by preg_match (with PREG_OFFSET_CAPTURE flag to have the position), and then insert the code to that position by substr_replace (with zero length to have the effect of inserting) :

preg_match('/function register\(.*\)\s*{/', $classFileContent, $matches, PREG_OFFSET_CAPTURE);
$firstLinePos = strlen($matches[0][0]) + $matches[0][1];
$newClassFileContent = substr_replace($classFileContent, $codeToInsert, $firstLinePos, 0);

Can I include code into a PHP class?

No. You cannot include files in the class body.

In a file defining a class, you may only include files in a method body or outside the class body.

From your description I take you want this:

<?php // MyClass.php
class MyClass
{
protected $_prop;
include 'myclass-methods.php';
}

<?php // myclass-methods.php
public function myMethod()
{
$this->$_prop = 1;
}

Running this code will result in

Parse error: syntax error, unexpected T_INCLUDE, expecting T_FUNCTION

What is possible though is this

<?php // MyClass.php
class MyClass
{
protected $_prop;
public function __construct() // or any other method
{
include 'some-functions.php';
foo($b); // echoes 'a';
}
}

<?php // some-functions.php
$b = 'a';
function foo($str)
{
echo $str;
}

Doing it this way, will import the contents of the include file into the method scope, not the class scope. You may include functions and variables in the include file, but not methods. You could but should not put entire scripts into it as well and change what the method does, e.g.

<?php // MyClass.php
// ...
public function __construct($someCondition)
{
// No No Code here
include ($someCondition === 'whatever') ? 'whatever.php' : 'default.php';
}
// ...

<?php // whatever.php
echo 'whatever';

<?php // default.php
echo 'foo';

However, patching the class this way to exhibit different behavior is not how you should do it in OOP. It's just plain wrong and should make your eyes bleed.

Since you want to dynamically change behavior, extending the class is also not a good option (see below why). What you really will want to do is write an interface and make your class use objects implementing this interface, thus making sure the appropriate methods are available. This is called a Strategy Pattern and works like this:

<?php // Meowing.php 
interface Meowing
{
public function meow();
}

Now you got the contract that all Meowing Behaviors must obey, namely having a meow method. Next define a Meowing Behavior:

<?php // RegularMeow.php
class RegularMeow implements Meowing
{
public function meow()
{
return 'meow';
}
}

Now to use it, use:

<?php // Cat.php
class Cat
{
protected $_meowing;

public function setMeowing(Meowing $meowing)
{
$this->_meowing = $meowing;
}

public function meow()
{
$this->_meowing->meow()
}
}

By adding the Meowing TypeHint to setMeowing, you make sure that the passed param implements the Meowing interface. Let's define another Meowing Behavior:

<?php // LolkatMeow.php
class LolkatMeow implements Meowing
{
public function meow()
{
return 'lolz xD';
}
}

Now, you can easily interchange behaviors like this:

<?php
require_once 'Meowing.php';
require_once 'RegularMeow.php';
require_once 'LolkatMeow.php';
require_once 'Cat.php';

$cat = new Cat;
$cat->setMeowing(new RegularMeow);
echo $cat->meow; // outputs 'meow';
// now to change the behavior
$cat->setMeowing(new LolkatMeow);
echo $cat->meow; // outputs 'lolz xD';

While you also could have solved the above with inheritance by defining an abstract BaseCat and meow method and then deriving concrete RegularCat and Lolkat classes from that, you have to consider what you want to achieve. If your cats will never change the way they meow, go ahead and use inheritance, but if your RegularCat and Lolkat is supposed to be able to do arbitrary meows, then use the Strategy pattern.

For more design patterns in PHP, check these resources:

  • http://www.php.net/manual/en/language.oop5.patterns.php
  • http://www.ibm.com/developerworks/library/os-php-designptrns/
  • http://www.fluffycat.com/PHP-Design-Patterns/
  • http://sourcemaking.com/design_patterns

PHP: Calling another class' method

//file1.php
<?php

class ClassA
{
private $name = 'John';

function getName()
{
return $this->name;
}
}
?>

//file2.php
<?php
include ("file1.php");

class ClassB
{

function __construct()
{
}

function callA()
{
$classA = new ClassA();
$name = $classA->getName();
echo $name; //Prints John
}
}

$classb = new ClassB();
$classb->callA();
?>


Related Topics



Leave a reply



Submit