Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mooseh's avatar

Chaining functions?

Hi everyone, so basically Im building my first Facade (mainly due to everyone having some kind of api i can use). and What I really need to figure out is how to chain functions together in a facade for example

Im working on a Vtiger Facade So i want to do the following

      $Vclient = VClient::Auth();

        $array = ['name' => 'Louis', 'password' => 'ilovemonkeys'];

        $Vclient->Create($array);

but i just get FatalErrorException in HomeController.php line 86: Call to a member function Create() on null.

here is what i've done so far with the facade

    static function Auth()
    {
        $token = VClient::generateToken();

        $request = new GuzzleHttpClient();

        $login_url = "https://sharpstreamltd1.od2.vtiger.com/webservice.php?operation=login";

        $auth_token = md5($token.config('VClient.access_key'));

        $postData = [
            'operation' => 'login',
            'username' => config('VClient.username'),
            'accessKey' => md5($token.config('VClient.access_key')),
        ];

        $response = $request->request('POST', $login_url, [
            'form_params' => $postData
        ])->getBody();

        return json_decode($response);

    }

    public static function generateToken(){

        $url = "https://sharpstreamltd1.od2.vtiger.com/webservice.php?operation=getchallenge&username=".config('VClient.username');

        $client = new GuzzleHttpClient();

        $response = $client->get($url)->getBody();

        $data = json_decode($response);

        $token = $data->result->token;

        return ($token);

    }

So how do i chain functions?

like()->this();

Thanks in advance for any help given

0 likes
6 replies
martinbean's avatar
Level 80

@mooseh I don’t think you quite understand façades. You make a service, and then can create a façade to reference that service; you don’t create the façade first and put the methods in there.

You should:

  1. Create a class.
  2. Register it in the service container.
  3. Create a façade that points to the key in the service container.

You can then use your façade, or the key in the container, to retrieve your class.

As for method chaining, in each method you just need to simple return $this, i.e.

class SomeClass
{
    public function someMethod()
    {
        // Do something

        return $this;
    }

    public function anotherMethod()
    {
        // Do something else

        return $this;
    }

    public function yetAnotherMethod()
    {
    }
}

You can then use the methods in chaining:

$instance = new SomeClass;

$instance->someMethod()->anotherMethod()->yetAnotherMethod();

Or via a façade:

SomeFacade::someMethod()->anotherMethod()->yetAnotherMethod();
1 like
Hathaway's avatar

True! A facade is just like a layer.

'Mail' for example is just a facade for a layer. To shorten the path and to make easily accessible.

<?php

namespace Illuminate\Support\Facades;

/**
 * @see \Illuminate\Mail\Mailer
 */
class Mail extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'mailer';
    }
}
AddWebContribution's avatar

Without changing the original class, you can do this chaining function. And for that you need to create wrapper proxy class like:

class ChainableProxy {
  private $instance = null;
  public function __construct(){
    $pars = func_get_args();
    $this->instance = is_object($obj=array_shift($pars))?$obj:new $obj($pars);
  }

  public function __call($name,$pars){
    call_user_func_array([$this->instance,$name],$pars);
    return $this;
  }
}

Now you can wrap you class with ChainableProxy and chain methods calls :

$objChainable = new ChainableProxy('yourClassName');

For Example:

class YourClassName {
    function foo(){ echo "foo called"; }
    function baz(){ echo "baz called"; }
    function bar(){ echo "bar called"; }
}

$objChainable = new ChainableProxy('YourClassName');

$objChainable->foo()->baz()->bar();
1 like
mooseh's avatar

Apologies, I have created the facade layer and its provider, but I just cannot get the commands to chain, but the returning $this is the bit i think i may not understanding, i'll give it a go and see how it works out :)

Thank you for all of your answers, the people on this forum are the best :)

mooseh's avatar

bah i tried it but it returns this

Call to undefined method App\VTiger\Facades\VClient::Auth()

mooseh's avatar

okay so Im not sure why, I thought a Facade is just a shortcut to a number of functions... If i cut out the Facade and just use use App\VTiger\VClient\VClient;

Then it works perfect.

using the facade it does not :(

Please or to participate in this conversation.