nilportugues / laravel5-jsonapi

Laravel 5 JSON API Transformer Package
http://nilportugues.com
MIT License
310 stars 70 forks source link

Hydrated Model Relations Get Re-Fetched #40

Closed apburton84 closed 8 years ago

apburton84 commented 8 years ago

If a model has had it's relations hydrated prior to a being passed to ListResource::get(), will the same relations be re-fetched, i.e. does laravel5-jsonapi know that there is data already present in the relation or does it just fetch them regardless ?

$results = Listing::searchByQuery(false, false, false, $limit, false, false);
$results = Listing::hydrate($results->toArray());

foreach ($results as $r) {
     $r->setRelation('listingType', (new listingType())->fill(
         $r['listing_type']
     ));
 }

$total = function () use ($model_class) {
        return (new $model_class())->count();
};

 $url = $request->url();

 $results = function () use ($results) {
     return $results;
 };

 $api_request = RequestFactory::create();

 $page_size = $this->page_size;
 $page      = $api_request->getPage();

 if (!$page->size()) {
      $page->setSize($page_size);
 }

 $fields    = $api_request->getFields();
 $sorting   = $api_request->getSort();
 $included  = $api_request->getIncludedRelationships();
 $filters   = $api_request->getFilters();

 $resource = new ListResource($this->serializer, $page, $fields, $sorting, $included, $filters);

 return $resource->get($total, $results, $url, Listing::class);

As the relations have been hydrated I would not expect to see any relational queries in

print_r(\DB::getQueryLog());

However I do.

Any help would be greatly appreciated :-)

nilportugues commented 8 years ago

The serializer does no cache for the persistence layer. It does cache the serialization process, so an object is not processed twice.

Maybe you should add Laravel's Cache:: to some closure method/s provided by this package to provide some cache layer.

You could also pass in an array by reference and use this array as a cache.

I'm planning on providing a basic cache mechanism in the next major release (https://github.com/nilportugues/laravel5-jsonapi/issues/19). So if you find anything worth noting I'll certainly listen :+1:

apburton84 commented 8 years ago

Thanks for your response

Maybe you should add Laravel's Cache:: to some closure method/s provided by this package to provide some cache layer.

and apologises for my ignorance, but how would I do the above ?

nilportugues commented 8 years ago

https://laravel.com/docs/5.2/cache#cache-usage

Cache::get('key') and Cache::add('key', 'value', $minutes)... is what you're looking for.

apburton84 commented 8 years ago

Thank you for that, could you point me to the right file within laravel5-jsonapi that caches the process ?

apburton84 commented 8 years ago

Bump!

nilportugues commented 8 years ago

@apburton84 https://github.com/nilportugues/laravel5-jsonapi/blob/f7c56c99c66e7229a2a730e3e4cdf7fc5612c389/src/NilPortugues/Laravel5/JsonApi/Controller/JsonApiTrait.php

It does not cache, but the "*Callable" methods are the one you could overwrite to add cache.

apburton84 commented 8 years ago

Thank you @nilportugues

apburton84 commented 8 years ago

Unfortunately none of those methods get call in the process ? I overrode them in my model which uses the JsonApiTrait and replaced their content with exit;

The use case for this scenario is, if you have hydrated models relations, because this data is elsewhere i.e. in elastic search not in Mysql DB.

listing->listingType 

listing is fine, the DB is not hit but for listingType it is, even though $listing[0]->listingType returns a populated entity before being passed to $resource->get();