Laravel’s ForwardsCalls trait
Tags: php, laravel, programming, oop
Published: 2023-06-21 14:01:23

In [the previous article](https://dev.to/giuliano1993/the-power-of-magic-methods-and-late-static-binding-4bj3), [Giuliano](https://dev.to/giuliano1993) showed us how to leverage PHP’s Magic Methods and Late Biding to create a powerful architecture.

This, however, is neither a secret nor a new cutting-edge OOP pattern.

This same system has been used in Laravel since version 4.0* albeit in the more PHP plain way, using `call_user_func_array` ([Laravel Model Class](https://github.com/laravel/framework/blob/4.0/src/Illuminate/Database/Eloquent/Model.php)).

The `ForwardsCalls` trait has been present since version 5.7 and if you read the first part of this series you are already familiar with the concept of using this method to simplify your development. Pretty cool, right?

The devs working on the Laravel Framework thought the exact same thing (I suppose), and created the `ForwardsCalls` trait.


> NOTE
> In this article we will reference Laravel 9.x, but the principles should be valid for all the versions that implement the `ForwardsCalls` trait. 

## Table of contents
- [Everyone's using it!](#everyone-s-using-it)
- [The Model Class](#the-model-class)
- [The ForwardsCalls trait](#the-forwardscalls-trait)
  - [Digging deeper](#digging-deeper)
    - [Pre-requisite: ExportData - part one](#pre-requisite-exportdata-part-one)
    - [The Exporter Logic](#the-exporter-logic)
    - [ExportManager](#exportmanager)
    - [IExporter, CsvExporter, XmlExporter](#iexporter-csvexporter-xmlexporter)
    - [ExportData - part two](#exportdata-part-two)
    - [Run the command](#run-the-command)
- [In conclusion](#in-conclusion)


## Everyone's using it!

One of the first instances where every developer using Laravel takes advantage of this approach is when they query their database through a `Model`. 

Look at this line of code extracted from a class called `ProjectController`:

```php
$projects = Project::orderByDesc('id')->get();
```

Pretty ordinary, right?

If you would dive deeper in the `orderByDesc` method, where would you go looking?
Probably inside the `Project` class.

Now, if you have some experience with Laravel, you already know this `Project` class is almost empty because it inherits all of its properties and methods from the `Model` abstract class.

Inside the `Model` class we go!  


## The Model Class

Once here we can see that this abstract class implements a lot of interfaces and uses a good number of traits, but we are looking for a specific method: `orderByDesc`.

So we open the find window, type our string and find… nothing.

The method is not defined in this class. We can search inside every trait but without results. Seems like the `orderByDesc` method is non-existent.

Every good developer should now think: how is this possible?

The answer lies in the `ForwardsCalls` trait, **PHP Magic Methods** (`__call` and `__callStatic`), and in the **Late Binding**!
In the first part of this series, Giuliano did a great job explaining how to re-create this pattern with a couple of classes in plain PHP, so I will not repeat what he already said.

Long story short: the `Model` class makes use of the `ForwardsCalls` trait (you can see that just by opening the class).
If you start to explore this class you will find both the `__call` and `__callStatic` methods and see the `__callStatic` method do a Late Binding to invoke the requested method as non-static:

```php
return (new static)->$method(...$parameters);
```

This way every static method not defined inside the `Model` class will be redirected to a non-static method (still not defined in this class) and will trigger the `__call` magic method.

Inside the `__call` magic method we can see a couple of if-blocks, but what we are looking for is the last line:

```php
return $this->forwardCallTo($this->newQuery(), $method, $parameters);
```

What’s going on here?
  

## The ForwardsCalls trait

The previous code is calling the `forwardCallTo` method, defined inside the `ForwardsCalls` trait (*what a surprise!*), passing along 3 parameters:

- the first is a `Query Builder` instance (where the `orderByDesc` method is defined!)
- the second is the name of the method we invoked (again, `orderByDesc`)
- the third is the parameters we used (`'id'` in the previous example)

Now is the right moment to ask: why didn’t the developers keep using the more straightforward `call_user_func_array` method?

There are a good number of reasons understandable by looking at the `ForwardsCalls` trait:

- the framework has better exception management (look at how the exceptions are handled inside this trait)
- the framework has more flexibility (look at both `forwardCallTo` and `forwardDecoratedCallTo` methods)
- the developers avoid code repetition inside every class (they just need to use the trait and write a couple of lines for the magic methods)
- and more...

This is a great example of a developer-friendly pattern 🙂


### Digging deeper

How could we take advantage of this pattern?
It's time to put our hands on some code!

Just imagine this scenario: you are developing an e-commerce and now you have the need to export your data in various formats (i.e. XML and CSV).
Because you don't need a UI to get these exports, you will create an Artisan Command to run your code right from the terminal.


#### Pre-requisite: ExportData - part one

Don't be scared if you are not familiar with the creation of Artisan Commands: the code is super simple and you don't need to understand it to follow this tutorial.
To keep things even more simple our export classes will not really export data. 

> NOTE
> If you want to learn about Artisan Commands check out the corresponding section inside the [Laravel documentation](https://laravel.com/docs/9.x/artisan)

To create a new command we just need to run:
```
php artisan make:command ExportData
```

This command will create the `ExportData` class inside `app\Console\Commands`.
Looking at the code we can clearly see two properties and the `handle` method. Maybe another time I will better explain how Artisan Commands works, but it's not the point of this article.

Quoting directly from the documentation:

>After generating your command, you should define appropriate values for the `signature` and `description` properties of the class. These properties will be used when displaying your command on the `list` screen. The `signature` property also allows you to define [your command's input expectations](https://laravel.com/docs/10.x/artisan#defining-input-expectations). The `handle` method will be called when your command is executed. You may place your command logic in this method.

So let's copy this code for the `$signature` property:
```php
protected $signature = 'data:export
                        {type : The export format: XML, CSV}
                        {class : The class to export: Product, User}';
```

And this is for the `$description` property:
```php
protected $description = 'Export selected data in the given format';
```

In the `handle` method we will `echo` the sentence `"it works"` and test everything running the command:
```
php artisan data:export xml product
```

If you see `it works` in the terminal, great! You just successfully ran your custom command!
Now it's time to create the export logic and make use of the `ForwardsCalls` trait.


#### The Exporter Logic

Our exporter will be structured this way:
- The main `ExportManager` class, taking care of the general logic
- The `IExporter` interface, defining how the single exporter is implemented
- A couple of classes for the exporter logic: `CsvExporter` and `XmlExporter` implementing `IExporter`

All these classes are placed inside `app\Support` (the full project is available on [GitHub](https://github.com/DonnieRich/file-exporter-app)).
How do they work?


##### ExportManager

The `ExportManager` use the `ForwardsCalls` to redirect most of the calls to the dedicated exporter class.
Inside this class, you can see both `__call` and `__callStatic` magic methods, a couple of static methods (`list` and `sendExport`), and the private method `getExporter`.
If you read the first part of this article's series you are already familiar with how these magic methods work.

The `__call` method gets the *type* and *model* from the `$parameters` array and capitalizes them (i.e. `xml` -> `Xml`, `PRODUCT` -> `Product`).
After that it calls the `forwardCallTo` method, passing an instance of the selected Exporter, the `$method` called by our code, and the `$parameters` array (just in case we should need it).

To get the correct Exporter instance (i.e. `CsvExporter`, `XmlExporter`, etc...) the `ExportManager` use the `getExporter` method.
This method returns an instance created dynamically from both `$type` and `$model` parameters.

```php
/**
 * Create an exporter instance
 * 
 * @param string $type the Exporter type (i.e. Csv)
 * @param string $model the model to use in the export (i.e. Product)
 * 
 * @return mixed an instance of the exporter (i.e. CsvExporter, XmlExporter, etc...)
 */
private function getExporter($type, $model)
{
	try {

		// $type = Csv -> App\Support\Exporters\CsvExoporter
		$exporter = "App\\Support\\Exporters\\{$type}Exporter";

		// $model = Product -> App\Models\Product
		$data = "App\\Models\\{$model}";

		// new App\Support\Exporters\CsvExoporter(App\Models\Product)
		return new $exporter($data);
	} catch (Error | Exception $e) {
		throw $e;
	}
}
```

This way we get the instance of the export, initialized with the model it will use to get the data from the database.
The `ExportManager` class act both as a manager for the exports (it can list them or send a particular report to the administrator) and as a switch to call the class needed for the selected type of export (using the *Dynamic Class Instantiation*).


##### IExporter, CsvExporter, XmlExporter

The `IExporter` interface allows us to create code that specifies which methods the *exporters* must implement, without having to define how these methods are implemented:

```php
interface IExporter
{
    /**
     * Get the data from the model and prepare the export
     */
    public function prepareExport();

    /**
     * Create the export
     */
    public function export();

    /**
     * Save the export inside the database
     */
    public function save();
}
```

Using an `interface` we define the basic standard for all the *exporters* we will create, allowing us to create objects of different classes that may be used interchangeably because they implement the same interface.
This is what we want for all our current and future *exporters*.

Now let's take a look at one of the exporters (for the sake of simplicity both the exporters do almost the same things, but of course, they can do different operations).

```php
class CsvExporter implements IExporter
{
    public static $filetype = "CSV";
    private $items;
    private $model;
    public $lastExportId;

    public function __construct($_model)
    {
        $this->model = $_model;
    }

    public function prepareExport()
    {
        $this->items = $this->model::all();

        echo "Preparing export of " . get_class(new $this->model);
        echo "\n";
    }

    public function export()
    {
        $this->prepareExport();

        echo "{$this->items->count()} records exported in " . static::$filetype . " format";
        echo "\n";

        return $this;
    }

    public function save()
    {
        $this->lastExportId = rand(1, 1305);

        echo "Export n. {$this->lastExportId} saved inside database";
        echo "\n";

        return $this;
    }
}
```

>Feel free to download the example project and add your custom exporter! Get your hands dirty it's a great way to wrap your head around this kind of pattern.
>
>Remember to create a DB and run all the migrations and seeder before running the `data:export` command.

Basically, every exporter is instantiated with a model, use this model to get all the records and simulate a DB writing.
The `export` and `save` methods return an instance of the export class so that we can chain the methods calls and also get the instance in our `DataExport` class.

>NOTE
>We get the exporter instance (`CsvExporter`, `XmlExporter`, etc...) because we are using the `forwardCallTo` method inside `__call` in our `ExportManager` class.
>
>If we had used the `forwardDecoratedCallTo` method, we would have got an instance of `ExportManager`. Try it!

With all this logic out of the way we have only one more thing to do: add the correct code in the `DataExport` `handle` method.


##### ExportData - part two

Remember our `handle` method that does nothing more than echo `"it works"`? It's time to make it work for real!
We need to import the `ExportManager` class by writing `use App\Support\ExportManager;` before the class definition.

In the `handle` method we can now call the `export` method on the `ExportManager` (even if it's defined on the specific exporter) and get the correct instance.
With this instance we can then call `sendReport`, pass it the ID of the export we just created, and have it sent to the administrator inbox.

```php
public function handle()
{
	$export = ExportManager::export($this->argument('type'), $this->argument('class'))->save();
	ExportManager::sendExport($export->lastExportId);
}
```


##### Run the command

Finally, you can test if everything it's working by running this command:

```
php artisan export:data csv product
```

Our data is exported in the format we want! Yay!
The logic we implemented allowed us to create a very flexible exporter: we can export all the `Models` defined in our Laravel application and should we need a different kind of exporter (i.e. `PdfExporter`, `ExcelExporter`, etc...) we just need to create a new class caring only about the exporting logic and nothing more!


## In conclusion

It was a wild ride, wasn't it?
I hope this helped you better understand one of the gems hidden inside the Laravel Framework!

The `ForwardsCalls` trait gives us a powerful pattern to leverage when developing inside a Laravel application. It gives us a lot of flexibility and the possibility to keep our classes clean, well defined but still able to communicate.

Giuliano also showed us how to bring this pattern outside Laravel and use it virtually in every PHP project we want.

I enjoyed writing this article's series with Giuliano and I really hope this article inspired you to dig a little bit inside the code of the libraries and frameworks you use.

[Here](https://dev.to/giuliano1993/the-power-of-magic-methods-and-late-static-binding-4bj3) you can find the first half made by Giuliano. ;)

If this article was helpful or want to start a conversation, feel free to reach out in the comments or here [@gosty93](https://twitter.com/gosty93) and [@donato-riccio-wda](https://www.linkedin.com/in/donato-riccio-wda/)
We'll be happy to receive any feedback or ideas for future articles and tutorials.
Happy Coding | _ 0

* This is the earliest version you could find on their public repository