Rohan
Rohan

Reputation: 13781

How to refresh values in laravel models where enums are replaced with values?

So I came across a weird issue while writing tests in laravel using factories. So this is a test I wrote:

/**
 @test
 */
public function document_belongs_to_a_patent()
{
    $patent = factory(Patent::class)->create();

    $document = factory(Document::class)->create([
        'documentable_id' => $patent->id,
        'documentable_type' => 'patent'
    ]);

    $this->assertArraySubset($patent->toArray(), $document->documentable->toArray());
}

So this should work, right because both should return the same thing and patent array should be equal or a subset of documentable array. But it was failing when I realised that there is an enum field in Patent model to which I am passing the value 1 but it was converted to the enum equivalent value in the database and when I tried document->documentable->toArray() it came back with the enum value rather than 1 which got me thinking how can make the model factory return the actual enum value and not the index number.

Top of the head I just fetched the patent just after creating it via the factory like so:

$patent = Patent::find($patent->id);

And it works well but it seems inconsistent. Is there a way to refresh models. I know we can refresh relationships of models but is there a way to do for the models themselves?

Upvotes: 1

Views: 730

Answers (1)

Josh
Josh

Reputation: 3288

If you're strictly needing the change for API, you can do something cheeky with mutators like this.

https://laravel.com/docs/5.1/eloquent-serialization

Add this property. It tells Laravel that for special outputs only, it needs to append a non-database property.

protected $appends = ['documentable_type_name'];

Then you need some ways of knowing the language for the enum. You need an array, a @lang definition, etc. Here's a protected property solution that I am quite fond of in simple situations.

protected static $documentable_types = [ 'divorce', 'patent' ];

And then create this mutator on your Documentable model.

public function getDocumentableTypeName()
{
    if ($this->documentable_type)
    {
        return static::$documentable_types[ $this->documentable_type ];
    }

    return null;
}

This changes your JSON output to look like this:

{
    docuemntable_id        : 555,
    documentable_type      : 1,
    documentable_type_name : 'patent'
}

You can also hide the document_type field by adding this.

protected $hidden  = ['documentable_type'];

And Laravel magic takes care of the rest. Hope that helps.

Upvotes: 1

Related Questions