PHP - Call function from after call to another function in the class - php

I have this class:
class myClass
{
function A() {
$x = "Something ";
return $x;
}
function B() {
return "Strange";
}
}
But I want to call the function like this:
myClass()->A()->B();
How can i do that without return the class itself(return $this)?

In order to achieve method chaining, your methods from the chain (except the last one) must return an object (in many cases and also in yours $this).
If you would want to build a string with method chaining, you should use a property to store it. Quick example:
class myClass
{
private $s = "";
function A() {
$this->s .= "Something ";
return $this;
}
function B() {
$this->s .= "Strange";
return $this;
}
function getS() {
return $this->s;
}
}
// How to use it:
new myClass()->A()->B()->getS();

Related

PHP - How to call multiple functions of a class on top of each other

How to create a class that can call multiple functions?
example:
class ClassName
{
public static function func1()
{
}
public static function func2()
{
}
public static function func3()
{
}
}
ClassName::func1()->func2()->func3();
result
Uncaught Error: Call to a member function funcX() on null
In PHP you cannot call static functions "piggybacked" like you can in, say, JavaScript. You have a few options .. Call them in a list, one at a time .. Like so:
ClassName::func1();
ClassName::func2();
ClassName::func3();
Or Like
$foo = new ClassName;
$foo->func1();
$foo->func2();
$foo->func3();
Now if you want to run them all with a single call, you need to nest the functions BUT we have to rid ourselves of the static method ...
<?php
class ClassName
{
public function func1()
{
echo "1 \n";
$this->func2();
}
public function func2()
{
echo "2 \n";
$this->func3();
}
public function func3()
{
echo "3 \n";
}
}
$foo = new ClassName;
$foo->func1();
Finally, if you want to run all of your functions within a class sequentially, you can use get_class_methods and loop through all the functions ... IE
<?php
class ClassName
{
public static function func1()
{
echo "1 \n";
}
public static function func2()
{
echo "2 \n";
}
public static function func3()
{
echo "3 \n";
}
}
$functions = get_class_methods('Classname');
foreach ($functions as $function){
ClassName::$function();
}
Both methods will result in:
1
2
3
If you choose to rid yourself of the static method however (as seen in our "nested function").. And you just choose public .. Then your syntax is possible using #arkascha's method of building out.
public function func1(): ClassName { // From #arkascha's answer ..
$foo = new ClassName;
$foo->func1()->func2()->func3();
The difference is understanding public method and static method
This won't work at all with static methods as you suggest.
This is possible however with an instance object, that is called "builder pattern" or "fluent style":
<?php
class ClassName {
public function func1(): ClassName {
echo "1";
return $this;
}
public function func2(): ClassName {
echo "2";
return $this;
}
public function func3(): ClassName {
echo "3";
return $this;
}
}
(new ClassName())->func1()->func2()->func3();
The output is:
123
Firstly, you need to create static instance for making chain methods. Because your methods are static and cant use them like chain. After it, you need to return this function every time at the end method. Like this:
class ClassName
{
private static $self;
public static function func1()
{
echo ' i am '.__METHOD__." \n";
return self::instance();
}
public static function func2()
{
echo ' i am '.__METHOD__." \n";
return self::instance();
}
public static function func3()
{
echo ' i am '.__METHOD__." \n";
return self::instance();
}
public static function instance(){
return self::$self ?? self::$self = new static ;
}
}
ClassName::func1()->func2()->func3();

Add regular not antonymous function to class

I wanted to add functions to class, those functions are in separate file(s), those functions contain ($this).
class myClass {
private $myFunctions=array(); // will contain two keys (title, function_object)
private $var;
public function __construct() {
$this->var = 'Hello world';
}
public function add_function($title, $func) {
$this->myFunctions[$title] = $func;
}
}
function add($x, $y) {
echo $this->var;
return $x + $y;
}
$class = new myClass;
$class->add_function('add', 'add()');
echo $class->add(1,2);
my goal is to add regular functions (not anonymous functions) to the class or to assign those function(s) to a var which can be passed to the class!
Can this be achieved ?
You must have to understand the oops concepts here.
$this refers to your current class / object. So all functions inside a class will be able to access $this ( Current Object ).
But the function declared out side of class can not use $this of that object. (Are you clear up to here.)
But anyways nothing is impossible.
You can achieve your goal in at-least 2 ways.
2) You can use trait to implement multiple inheritance.
it will be like this
trait commonFunctions
{
function add($a, $b)
{
$this->result = $a + $b;
return $this;
}
}
class myClass
{
use commonFunctions;
public function myClassFunction()
{
//
}
}
2 ) Or you can follow below code. Source php.net
<?php
class A {
function __construct($val) {
$this->val = $val;
}
function getClosure() {
//returns closure bound to this object and scope
return function() { return $this->val; };
}
}
$ob1 = new A(1);
$ob2 = new A(2);
$cl = $ob1->getClosure();
echo $cl(), "\n";
$cl = $cl->bindTo($ob2);
echo $cl(), "\n";
Here __call will be called when undeclared method is being called. So you can dynamically append methods to class by this way.
Of course you can polyfill your object in javascript like way. But keep in mind you need to use Reflection to bind this to closure.
<?php
class A {
private $dynamic_functions=[];
public function __call($method, $args=[])
{
if(isset($this->dynamic_functions[$method]) && $this->dynamic_functions[$method] instanceof \Closure)
{
$cl = $this->dynamic_functions[$method]->bindTo($this);
return call_user_func_array($cl, $args);
}
else
{
die("Wrong method, Not yet polyfilled.");
}
}
public function __set($property, $value)
{
$this->dynamic_functions[$property] = $value;
}
}
$a = new A;
$a->sum = function($a,$b){
// var_dump($this); will give you current instance of A
return $a+$b;
};
echo $a->sum(5, 3);
It is possible, but their are limits. When calling undefined methods on an object, PHP checks if there is a magic method named __call:
public mixed __call ( string $name , array $arguments )
This function then receives the function name, and the list of arguments. For your construction you could use
public function __call($name, $args) {
// invokes the function with all arguments:
// e.g: function_name($arg[0], $arg[1], ...)
return call_user_func_array($this->myFunctions[$name], $args);
}
There is just one problem, namely you cannot use $this within your anonymous functions. In python this problem got solved by passing the instance as the first argument (which is usually called self). We can build something similar by adding the instance to the argument list:
public function __call($name, $args) {
// we add the instance at the beginning of the argument list
array_unshift($args, $this);
return call_user_func_array($this->myFunctions[$name], $args);
}
Now you could do something like
function bork($instance, $a, $b) {
return $a*$b;
}
$class = new myClass;
$class->add_function('derp', 'bork');
$class->add_function('add', function($instance, $x, $y) {
echo $instance->var;
return $x + $y;
});
echo $class->derp(1,2);
echo $class->add(35,34534);
If you have already some function which does not have $instance as a first argument, you could wrap it
function my_cool_existing_function($bla) {
echo $bla.$bla;
}
$class->add_function('super_bork', function($instance, $bla) {
return my_cool_existing_function($bla);
});
No, you can't add a function to a class like this. You can extend your class with other class having this function add(). This way inherited class will have parent's function add().

Can I call inherited parent method without a name in PHP?

Is there a way to call an inherited method, without specifying it's function name?
Something like:
class Child extends Parent {
function some_function(){
// magically inherit without naming the parent function
// it will call parent::some_function()
parent::inherit();
// other code
}
function another_function(){
// it will call parent::another_function()
$result = parent::inherit();
// other code
return $result;
}
}
I could think of a hack to do this using debug_backtrace(), get the last function where inherit() was called and access it's parent with the same function name. I was wondering if there's a nicer way instead of using debug functions which are clearly not meant for this.
You can use the magic __FUNCTION__ constant.
class A
{
function some_function()
{
echo 'called ' . __METHOD__;
}
}
class B extends A
{
function some_function()
{
call_user_func(array('parent', __FUNCTION__));
}
}
$b = new B;
$b->some_function(); // prints "called A::some_function"
Instead of
call_user_func(array('parent', __FUNCTION__));
you can also do
parent::{__FUNCTION__}();
Dirty, but:
class Adult {
function mummy(){
return 'Walk like an Egyptian';
}
function daddy(){
return 'Luke, I am your father';
}
}
class Child extends Adult {
function mummy(){
echo 'Mummy says: ';
$me = explode('::',__METHOD__)[1];
echo parent::$me();
}
function daddy(){
echo 'Daddy says: ';
$me = explode('::',__METHOD__)[1];
echo parent::$me();
}
}
$o = new Child();
$o->mummy();
$o->daddy();
EDIT
Actually giving you a parent method called inherit();
class Adult {
private function mummy(){
return 'Walk like an Egyptian';
}
private function daddy(){
return 'Luke, I am your father';
}
protected function inherit($method) {
$beneficiary = explode('::', $method)[1];
return $this->$beneficiary();
}
}
class Child extends Adult {
public function mummy() {
echo 'Mummy says: ',
parent::inherit(__METHOD__),
PHP_EOL;
}
public function daddy() {
echo 'Daddy says: ',
parent::inherit(__METHOD__),
PHP_EOL;
}
}
$o = new Child();
$o->mummy();
$o->daddy();
Dynamically calling functions:
static::$functionName();
In your case:
$func = __FUNCTION__;
parent::$func();
Note: the function name must be a string, if it's the actual function (not really relevant in this context) then it first needs to be converted to its string name first.
Other stuff that your question will probably lead you towards in the long run.
Check out late static binding it's what you're looking for.
Example taken from the linked page.
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();

PHP, return class as object

I am testing the way writing PHP like js, and I wonder if this will be possible.
If say I have A, B function in Class C.
Class C{
function A(){
}
function B(){
}
}
$D = new C;
$D->A()->B(); // <- Is this possible and how??
In Js, we can simple write like D.A().B();
I tried return $this inside of function A(), didnt work.
Thank you very much for your advice.
What you are looking for is called fluent interface. You can implement it by making your class methods return themselves:
Class C{
function A(){
return $this;
}
function B(){
return $this;
}
}
Returning $this inside the method A() is actually the way to go.
Please show us the code that supposedly didn't work (there probably was another error in that code).
Its rather simple really, you have a series of mutator methods that all returns the original (or other) objects, that way you can keep calling functions.
<?php
class fakeString
{
private $str;
function __construct()
{
$this->str = "";
}
function addA()
{
$this->str .= "a";
return $this;
}
function addB()
{
$this->str .= "b";
return $this;
}
function getStr()
{
return $this->str;
}
}
$a = new fakeString();
echo $a->addA()->addB()->getStr();
This outputs "ab"
Returning $this inside the function allows you to call the other function with the same object just like jQuery does.
I tried it and it worked
<?php
class C
{
public function a() { return $this; }
public function b(){ }
}
$c = new C();
$c->a()->b();
?>

PHP OOP Multicall

i have seen in some libraries something like this :
$this->getResponse()->setRedirect($returnUrl);
How is this 'multicall' done, or, how should the class be build to do something like this?
I think :
class greeting
{
public function hi()
{
public function howAreYou()
{
echo 'How are you?';
}
}
}
$greet = new greeting;
$greet->hi()->howAreYou();
But i think it's not so good, i would better use something like extends, but i don't know. Thx for your suggestions.
If this is a class instance calling itself, it is called "method chaining".
In PHP, can be done by using return $this; note that this is a very different mechanism than class inheritance - it doesn't really make sense to treat them as interchangeable.
See also: https://stackoverflow.com/search?q=method+chaining+php
getResponse() is returning a class instance which has a setRedirect() method.
Example:
class Foo
{
public function getResponse()
{
$redirect = new Bar();
return $redirect;
}
}
class Bar
{
public function setRedirect($returnUrl)
{
// do something
}
}
$foo = new Foo();
$foo->getResponse()->setRedirect("returnUrl");
No.
All you have to do is return self at very end of each function.
So Your example would be like>
class greeting
{
public function hi()
{
echo "Hi";
return $this;
}
public function howAreYou()
{
echo 'How are you?';
return $this;
}
}
$greet = new greeting;
$greet->hi()->howAreYou();
Or even:
$greet->hi()->howAreYou()->hi()->howAreYou();
class stutter{
public function a(){
echo 'h';
return $this;
}
public function b(){
echo 'hello world!';
}
}
$var=new stutter();
var->a()->b();
Output is:
h hello world
Chaining methods is not the same as declaring functions within a method... in fact the latter will spit an error (not the function declaration, but the way you're calling it). In order to chain a method, just have it return the object itself:
Class chainableObject
{
public $name=null;
public function __construct($name='')
{
$this->name=$name;
return $this;
}
public function setName($name)
{
$this->name = $name;
return $this;//makes chainable
}
public function greet()
{
echo 'Hello, '.$this->name;
return $this;
}
}
$chain = new chainableObject('Frank')->greet();//outputs: Hello, frank
The explanation: All methods return the instance itself, so basically, read the last line of the snippet like this [create object with name:Frank]=>call method greet on the return value of this action. Since the return value is $this, the object that has a greet method, that's what will happen... easy, for more info: just google php method chaining

Categories