I created a CalendarResource
class, that I want to call statically using a Facade:
<?php
namespace App\Models\Shared;
class CalendarResource
{
public function __construct(
public string $name = '',
public string $color = '#000000',
public string $textColor = '#ffffff'
) {
}
public function toArray(): array
{
return [
'id' => $this->name,
'name' => $this->name,
'color' => $this->color,
'textColor' => $this->textColor,
];
}
public function setColor(string $color): self
{
$this->color = $color;
return $this;
}
public function setTextColor(string $textColor): self
{
$this->textColor = $textColor;
return $this;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
This is my Facade:
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
/**
* @method static \App\Models\Shared\CalendarEvent setName(string $title)
* @method static \App\Models\Shared\CalendarEvent setColor(string $color)
* @method static \App\Models\Shared\CalendarEvent setTextColor(string $color)
* @method static \App\Models\Shared\CalendarEvent toArray()
*
* @see \App\Models\Shared\CalenderResource
*/
class CalendarResource extends Facade
{
protected static function getFacadeAccessor(): string
{
return \App\Models\Shared\CalendarResource::class;
}
}
Now I am using the facade like this:
use App\Facades\CalendarResource as Resource;
$r1 = Resource::setColor('red')->setName('Test')->toArray();
$r2 = Resource::setColor('blue')->setName('Foo')->toArray();
echo $r1['color'].PHP_EOL;
echo $r2['color'].PHP_EOL;
What outputs:
red
blue
This is fine but now my confusion starts:
If I don't set the setColor('blue')
on $r2
I get
red
red
And this is unwanted. I expect to get
red
#000000
It seems like the $r2
is using the values set for $r1
. I want every Resource be "it's own" class. What do I need to change the get that expected behaviour and how can I make the name mandatory? If I remove = ''
I get Unresolvable dependency resolving [Parameter #0 [ <required> string $name ]] in class App\Models\Shared\CalendarResource
.
The Laravel facade functionality is going to create one instance of the class and store it in the container. Every reference to the facade will reference the same instance.
You're confusing Laravel's facades with just plain static method calls. What you're looking for is a "static factory method". Laravel facades are not involved with this.
For example, get rid of all the facade stuff and add this function to your shared model class:
public static function withName(string $name): self
{
return new self($name);
}
With this, every call to withName()
will return a new instance that has the name you specify. You can also remove the default value for the name from the constructor now.
Test your code:
use App\Models\Shared\CalendarResource;
$r1 = CalendarResource::withName('Test')->setColor('red')->toArray();
$r2 = CalendarResource::withName('Foo')->toArray();
echo $r1['color'].PHP_EOL; // red
echo $r2['color'].PHP_EOL; // #000000