laravel eloquent merge 2 queries before executing them? - laravel

I have 2 queries like this:
$expiresAt = Carbon::now()->addMinutes(10);
$thumbnails = Cache::remember('entities-thumbnails-'.$entity_id, $expiresAt, function () use ($entity_id) {
return Images::where(['entity_id' => $entity_id, 'image_style' => 'thumbnail'])
->select('path AS thumbnail', 'width As thumbnailWidth', 'height As thumbnailHeight');
});
$largeImages = Cache::remember('entities-largeImages-'.$entity_id, $expiresAt, function () use ($entity_id) {
return Images::where(['entity_id' => $entity_id, 'image_style' => 'large'])
->select('path AS src')
->union($thumbnails)
->get();
});
What I want to do is not execute them seperately but as one query. Overall there will be 4 queries therefore instead of doing 4 I want to do one, is that possible? How does union work exactly?

Storing whole plain results in PHP variable then let PHP do such filtering would be better in my point of view. As an example
$images = Image::where('entity_id', $entity_id)->get();
$thumbnails = Cache::remember('entities-thumbnails-'.$entity_id, $expiresAt, function () use ($images) {
return $images->filter(function ($image) {
return $image->image_style === 'thumbnail';
});
});
$largeImages = Cache::remember('entities-largeImages-'.$entity_id, $expiresAt, function () use ($images) {
return $images->filter(function ($image) {
return $image->image_style === 'large';
});
});
You might call UNION is literally the same as JOIN. But, it does combining results set into one in an operation rather than relate them horizontally. Still, both need to be separated by PHP, as each row recorded are united into one collection.
I'm assuming you still need to make aliases for specified columns. Fortunately, Laravel is able to do that out of the box.
$thumbnails = Cache::remember('entities-thumbnails-'.$entity_id, $expiresAt, function () use ($images) {
return $images->filter(function ($image) {
if ($image->image_style === 'thumbnail') {
$image->setAttribute('thumbnail', $image->path);
$image->setAttribute('thumbnailWidth', $image->width);
$image->setAttribute('thumbnailHeight', $image->height);
return true;
}
return false;
});
});
$largeImages = Cache::remember('entities-largeImages-'.$entity_id, $expiresAt, function () use ($images) {
return $images->filter(function ($image) {
if ($image->image_style === 'large') {
$image->setAttribute('src', $image->path);
return true;
}
return false;
});
});

Related

Laravel 9.5.1 Undefined Variable on return view

Good day, I'm having a problem on passing data from controller to the blade.
This is the code from controller:
function dashboard(){
$adminData = ['LoggedAdminInfo'=>Admin::where('id','=',session('LoggedAdmin'))->first()];
$sensor_latest_data = array('list'=>DB::table('sensors')->latest('id')->first());
$sensor_data = Sensor::select('id', 'created_at')->get()->groupBy(function($data) {
return Carbon::parse($data->created_at)->format('M');
});
return view('admin.index', $adminData, $sensor_latest_data, ['chart_data'=>$sensor_data]);
}
The other data is working fine except for the last argument on return view.
I tried putting it inside the compact() function and it returned this:
return view('admin.index', $adminData, $sensor_latest_data, compact(['chart_data'=>$sensor_data]));
Compact function gets the variable name from string and map it to an array. For exmaple if you use compact('test'), it will search for test variable and map it and return it as ['test' => $test]
return view('admin.index', ['adminData' => $adminData, 'sensor_latest_data' => $sensor_latest_data, 'chart_data'=>$sensor_data]);
or just change your function to :
function dashboard(){
$adminData = ['LoggedAdminInfo'=>Admin::where('id','=',session('LoggedAdmin'))->first()];
$sensor_latest_data = array('list'=>DB::table('sensors')->latest('id')->first());
$chart_data = Sensor::select('id', 'created_at')->get()->groupBy(function($data) {
return Carbon::parse($data->created_at)->format('M');
});
return view('admin.index', compact('adminData', 'sensor_latest_data', 'chart_data'));
}
and here is simplified version:
function dashboard(){
$LoggedAdminInfo = Admin::where('id','=',session('LoggedAdmin'))->first();
$list = DB::table('sensors')->latest('id')->first();
$chart_data = Sensor::select('id', 'created_at')->get()->groupBy(function($data) {
return Carbon::parse($data->created_at)->format('M');
});
return view('admin.index', compact('LoggedAdminInfo', 'list', 'chart_data'));
}

Display content for user and for admin

I would like that normal users don't see the pictures with a status of 0 (not visible) only the visible ones (status 1) but that admins can see everything.
Is this kind of solution viable or is there something cleaner to do?
The gates/policies are not adapted for that, I don't see any other solution to my knowledge, that's why I come to you
Thanks in advance
public function show($name)
{
if(Auth::user()->isAdmin()) {
$model = cache()->remember('model_show'.$name, Config::get('cache.ttl'), function() use ($name) {
return Model::where('name', $name)->with('pictures')->first();
});
$pictures = $model->pictures()->latest()->paginate(18);
} else {
$model = cache()->remember('model_show'.$name, Config::get('cache.ttl'), function() use ($name) {
return Model::where('name', $name)->with('visible_pictures')->first();
});
$pictures = $model->visible_pictures()->latest()->paginate(18);
}
return view('model.model')->with(['model' => $model, 'pictures' => $pictures]);
}
You can clean it up by using when function in the query itself.
public function show($name)
{
$model = cache()->remember('model_show'.$name, Config::get('cache.ttl'), function() use ($name) {
return Model::where('name', $name)->when( Auth::user()->isAdmin() , function ($q)
{
return $q->with('pictures');
}, function ($q)
{
return $q->with('visible_pictures');
})->first();
});
$pictures = $model->pictures()->latest()->paginate(18);
return view('model.model')->with(['model' => $model, 'pictures' => $pictures]);
}
or we could also use arrow functions
public function show($name)
{
$model = cache()->remember('model_show'.$name, Config::get('cache.ttl'), function() use ($name) {
return Model::where('name', $name)->when( Auth::user()->isAdmin() ,
fn($q) => $q->with('pictures') ,
fn($q) => $q->with('visible_pictures')
)->first();
});
$pictures = $model->pictures()->latest()->paginate(18);
return view('model.model')->with(['model' => $model, 'pictures' => $pictures]);
}

Where should I define my logic that will be used in a blade template?

In this question I got a nice answer with some code. I now wonder what is the intended laravel way of implementing this.
The code is:
function getRoutesByGroup(array $group = [])
{
$list = \Route::getRoutes()->getRoutes();
if (empty($group)) {
return $list;
}
$routes = [];
foreach ($list as $route) {
$action = $route->getAction();
foreach ($group as $key => $value) {
if (empty($action[$key])) {
continue;
}
$actionValues = Arr::wrap($action[$key]);
$values = Arr::wrap($value);
foreach ($values as $single) {
foreach ($actionValues as $actionValue) {
if (Str::is($single, $actionValue)) {
$routes[] = $route;
} elseif($actionValue == $single) {
$routes[] = $route;
}
}
}
}
}
return $routes;
}
Route::group(['as' => 'main'], function () {
Route::get('/', function () {
return view('pages.start');
})->name('Home');
Route::get('/foobar', function () {
return view('pages.foobar');
})->name('Home');
Route::get('/business', function () {
return view('pages.business');
})->name('Business');
});
getRoutesByGroup(['as' => 'main']); // where to load this?
I want to use this in two blade templates to render a menu. My first thought was to put this in a Trait and use that Trait within the AppServiceProvider.php, but this seems to only have 5 internal ignite routes available so I guess its too early in the bootstrapping process.
What is the correct way in this scenario? Do I make a Facade, another Service Container, do I load this via inject in a template, do I make a global var?
I ended up making a new service provider and used view composer.
Still, if there is a better and more MVCish way I'm glad for any input.

laravel & vuejs: Builder could not be converted to string

this is my search function in users controller
public function search()
{
if( $search = \Request::get('q') ){
$users = User::where( function($query) use ($search){
$query->where('name','LIKE',"%$search%");
});
}
return $users;
}
this is the vuejs code .Fire is new instance of vuejs that i created in app.js
Fire.$on('searching',() => {
let query = this.$parent.search; // query parent(app.js) for 'search'
axios.get('api/findUser?q='+query)
.then((data) => {
this.users = data.data;
})
});
You've constructed a query, but you haven't actually run it until you call ->get() on it.
return $users->get();

How to get routes list by specific groups in laravel 5?

Hello I am trying to do it like this but it's getting all the routes, I only want the routes from a specific group(s).
This is my code:
<?php
$routes = Routes::getRoutes();
#foreach($routes as $route)
{{ $route->getPath() }}
#endforeach`
Thanks in advance!
Let's create some routes without any groups
Route::get('/', function () {
return view('welcome');
});
Route::get('/load', 'defaultController#load');
Now we'll create some routes with groups
Route::group(['as' => 'admin'], function () {
Route::get('users', function () {
return "users route";
});
Route::get('ravi', function () {
return "ravi route";
});
Now we are going to create a route in this group which will look for the admin group and print all routes that exist in this group.
Route::get('kumar', function () {
$name = 'admin';
$routeCollection = Route::getRoutes(); // RouteCollection object
$routes = $routeCollection->getRoutes(); // array of route objects
Now in our route object, we will look for our named route by filtering the array.
$grouped_routes = array_filter($routes, function($route) use ($name) {
$action = $route->getAction(); // getting route action
if (isset($action['as'])) {
// for the first level groups, $action['as']
// will be a string
// for nested groups, $action['as'] will be an array
if (is_array($action['as'])) {
return in_array($name, $action['as']);
} else {
return $action['as'] == $name;
}
}
return false;
});
// Here we will print the array containing the route objects in the 'admin' group
dd($grouped_routes);
});
});
Now you can copy and paste this in your route folder and you will be able to see the output by hitting your_project_public_folder_url/kumar
I took help from this answer Answer of patricus

Resources