I have a website built in Laravel 5.2 that supports multiple languages. Most of the website contents are coming from MySQL database. I cache most of my queries. Example:
$categories = Cache::remember('Categories', 1440, function()
{
return $this->category->getAllOrderByRank();
});
The problem is when I visit the English version of the website the query results get saved. Then when I change the language to Deutsch, The query is still cached and showing the English data from database. Do you guys have any suggestions of how I can handle this?
Thank you
I'd include the locale in the cache name:
$locale = App::getLocale();
$categories = Cache::remember('Categories.' . $locale, 1440, function()
{
return $this->category->getAllOrderByRank();
});
That way if you're set to en you'll pull Categories.en query, if you're set to de you'll get Categories.de, etc.
I'm wondering, though, where are you doing the translations? This probably shouldn't be affected by a cached query.
Related
I am using laravel 8 and currently my url is looking as
http://127.0.0.1:8000/?country_id_to=1
and I want to set URL as
http://127.0.0.1:8000/uk/en/pakistan
In each route. Ihave no idea to do it.
To add on #Douwe de Haan comment - and be more precise have a look at this page: https://laravel.com/docs/8.x/routing#route-parameters
For your example you could do
Route::get('/{localization}/{language}/{country}', function ($localization, $language, $country) {
// your code
});
Where
http://127.0.0.1:8000/uk/en/pakistan
Would now result in
$localization = "uk";
$language = "en";
$country = "pakistan";
This will obviously also work with a controller.
If you want to reference an entity not by its ID but by a custom field you can do that as well
https://laravel.com/docs/8.x/routing#customizing-the-default-key-name
I am using Laravel Scout with Algolia for populating a datatable and have this intermittent issue where a record in the table after delete will still be visible. It happens when Algolia's index doesn't update quickly enough and the application fetches the data from Algolia prior to it showing as deleted. After refreshing the page and/or updating another record it shows the correct data. Below is my setup - does anyone have any ideas on how to better set this up so any live update will always have the correct data?
public function deleteSelected()
{
$truckings = Trucking::query()->whereKey($this->selected);
$truckings->each(fn ($trucking) => $trucking->delete());
event(new TruckingCreated);
$this->showDeleteModal = false;
$this->notify('You\'ve deleted ' . collect($this->selected)->count() . ' trucking slips.');
$this->getRowsQueryProperty();
$this->selected = [];
}
As you can see I am calling $this->getRowsQueryProperty(); method after deleting records to force it to update - but there are still instances where this will happen.
Below is that method for reference which fetches the data.
public function getRowsQueryProperty()
{
$query = Trucking::search($this->filters['search'],
function (SearchIndex $algolia, string $query, array $options) {
$options['filters'] = $this->algoliaFilters();
return $algolia->search($query, $options);
});
return $this->applySorting($query);
}
Thank you for any help or advice.
It is because you're missing the get call from your query. Using each without get first chunks the results and runs a mass delete query, bypassing model events, thus not deleting indexes.
$truckings = Trucking::query()->whereKey($this->selected)->get();
$truckings->each(fn ($trucking) => $trucking->delete());
I have made a ServiceProvider to load data on several views. Like this:
View::composer(['components.navigation.main.search','search.*','page-parts.cats','page-parts.categories_menu','page-parts.categories_more','page-parts.cats_top','components.modals.off-category'],function ($view) {
$view->with([
'toplevel_categories' => Category::topLevel()->orderBy('name')->get(),
]);
});
But on several html pages he needs to load multiple of these views and I don't want to load the topLevel categories each time to avoid overload and less runtime.
Can I store the loaded data (toplevel_categories) in a session or what is the most efficient way to handle this problem?
You could simply cache the variable and use it in the callback like:
$topLevelCategories = Category::topLevel()->orderBy('name')->get();
View::composer([], function($view) use ($topLevelCategories) {
$view->with([
'toplevel_categories' => $topLevelCategories
}
You could even use the cache mechanic from laravel itself to save an additional query, like caching it for 30 minutes (assuming the database hasnt changed in the meantime):
// Save the categories in the cache or retrieve them from it.
$topLevelCategories = Cache::remember('topLevelCategories', 30, function() {
return Category::topLevel()->orderBy('name')->get();
});
Note that for Laravel 5.8 the second parameter is in SECONDS, for 5.7 and below it is in MINUTES.
Since your service provider is only loaded once per request/lifecycle this should do the trick.
I've created an API using Laravel and I'm trying to find out how to cache Eloquent models. Lets take this example as one of the API endpoints /posts to get all the posts. Also within the method there are various filter options such as category and search and also gives the option to expand the user.
public function index()
{
$posts = Post::active()->ordered();
if (Input::get('category')) $posts = $posts->category(Input::get('category'));
if (Input::get('search')) $posts = $posts->search(Input::get('search'));
if ($this->isExpand('user')) $posts = $posts->with('user');
$posts = $posts->paginate($this->limit);
return $this->respondWithCollection($this->postTransformer->transformCollection($posts->all()), $posts);
}
I have been reading up and found in Laravel 4 you could cache a model like this
return Post::remember($minutes);
But I see this has been removed for Laravel 5.1 and now you have to cache using the Cache facade, but is only retrievable by a single key string.
$posts = Cache::remember('posts', $minutes, function()
{
return Post::paginate($this->limit);
});
As you can see, my controller method contains different options, so for the cache to be effective I would have to create a unique key for each option like posts_cagetory_5, posts_search_search_term, posts_category_5_search_search_term_page_5 and this will clearly get ridiculous.
So either I'm not coming across the right way to do this or the Laravel cache appears to have gone backwards. What's the best solution for caching this API call?
As the search is arbitrary, using a key based on the search options appears to be the only option here. I certainly don't see it as "ridiculous" to add a cache to for expensive DB search queries. I may be wrong as I came by this post looking for a solution to your exact problem. My code:
$itemId = 1;
$platform = Input::get('platform'); // (android|ios|web)
$cacheKey = 'item:' . $itemId . ':' . $platform;
$item = Item::find(1);
if( Cache::has($cacheKey) ) {
$result = Cache::get($cacheKey);
} else {
$result = $this->response->collection( $item, new ItemTransformer( $platform ) );
Cache::tags('items')->put($cacheKey, $result, 60); // Or whatever time or caching and tagged to be able to clear the lot in one go...
}
return $result;
I realise that my example has less complexity but it seems to cover all the bases for me. I then use an observer to clear the cache on update.
I am new to laravel and I am trying to get a pagination function into my result pages, so I have the following function to generate results from query and I would like to have a pagination on the results page, but I don't seem to get it work correctly
public function showResults()
{
$selectedquery = Input::get('Annonces');
$what = Input::get('what');
$where = Input::get('where');
$results = DB::table('annonces')->where($selectedquery,'LIKE', '%'.$what.'%')
->where('Lieu','LIKE', '%'.$where.'%')
->get();
return View::make('results',array('results' => $results));
}
Any Help?
Well, for one, you're missing the call to ->paginate(n). Right now, your closure is ->get(), which returns all results for your annonces table. This is good, but doesn't work for pagination. Change the function like so:
$results = DB::table('annonces')->where($selectedquery,'LIKE', '%'.$what.'%')
->where('Lieu','LIKE', '%'.$where.'%')
->paginate(10);
This will return all results grouped into 10 results per page. Feel free to change that as you see fit.
Lastly, somewhere on your view where you display the results, you will need to use this code to display a page-viewer:
<?php echo $results->links(); ?>
<!-- OR -->
{{ $results->links(); }}
Also, be sure to check out the docs on Laravel's pagination. You'll find it's pretty comprehensive!
Laravel Pagination
Hope that helps!