Reputation: 13781
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
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