Reputation: 610
I'm converting a page to Laravel. I used to have a PHP script (GET) that handled select queries from any table. All I had to do was sent the table parameter, and it would return the result.
The idea was to have a controller like this:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use DB;
class Projects extends Controller
{
/**
* Get projects based on the table
*
* @return Response
*/
public function index($table)
{
$result = DB::select("SELECT projectid FROM `" . $table . "` WHERE isClass=1 LIMIT 10");
return view('pages.allviews', ['results' => $result]);
}
}
The problem is that page will execute this query three times. Happens that, the controller will create the View right after executing, and the only solution would be to repeat the query three times in the controller.
I want to avoid doing that, I want to separate the controller from what the page needs, and be able to execute it the times the page needs. Generalizing is the key.
Is there a way to do this, and keep this abstraction without having to create a new controller?
Upvotes: 0
Views: 780
Reputation: 146191
There are many ways to do this but the most important thing is here that, you should extract your query logic from the controller to a separate class so you can re-use the object. Basically, a repository class would be good for this but it would be possible to create a query object as well. Anyways, let's keep it simple. So, as I mentioned that, you have many options and depending on your project, you may decide the strategy.
In your case, you may simply use the DB::table()
method and cache it for a while so for the next subsequent calls, the cached result will be returned. See the examle now:
$limit = 10;
$table = 'users';
$select = ['id', 'name'];
$result = \Cache::remember($table, 60, function() use ($table, $select, $limit) {
return \DB::table($table)->limit($limit)->get($select);
});
Then to access the cached query, you may use this:
if(\Cache::has('users')) {
$users = \Cache::get('users');
}
So, while this may solve your problem but I suggest you to create a separate class and keep that query logic (with caching) in that class, for example:
namespace Some\Namespace;
use DB, Cache;
class CachedQuery {
public function getResult($table, $select = '*', $limit = 10, $timeout = 60)
{
return Cache::remember($table, $timeout, function() use ($table, $select, $limit) {
return DB::table($table)->limit($limit)->get($select);
});
}
}
Then use it like:
use Some\Namespace\CachedQuery;
class SomeController extends Controller {
public function index(CachedQuery $cachedQuery, $table)
{
// The $table parameter is required, rest are optional
$result = $cachedQuery->getResult($table, ['projectid']);
}
}
Also, you can use IoC/Service Container object to store data temporarily. Also, it's possible to create an interface and bind the interface to a class to get it from Service Container but I kept it as simple as I can. Hope you got the idea. Also, check the Cache component.
Upvotes: 1