Laravel Eloquent Join Using Another table - sql

Hi how to convert this SQL query to Laravel Eloquent?
I have three table: payments, devices and users.
Payments table does not store user_id. but table has device_id. And device table also has user_id.
I want to get user name which made payment.
select * from payments p
join devices d on p.device_id = d.devid
join users u on d.user_id = u.id

it's very easy
$users = \DB::table('payments')
->join('devices', 'devices.id', '=', 'payments.device_id')
->join('users', 'users.id', '=', 'devices.user_id')
->select('payments.*', 'users.name')
->get();
Another way is:
We have three models:
User (has many devices)
Device(belongs to user && has many payments)
Payment (belongs to device)
1) User.php
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
public function devices()
{
return $this->hasMany(Device::class);
}
2) Device
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Device extends Model
{
//
public function user()
{
return $this->belongsTo(User::class);
}
public function payments()
{
return $this->hasMany(Payment::class);
}
}
3)Payment
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Payment extends Model
{
//
public function device()
{
return $this->belongsTo(Device::class);
}
}
and your query should be:
Payament::with(['device','device.user'])->get();

Related

Delete unused groups in Laravel 8

I have a group model and I want to delete groups that don't have any member.
How can I get empty groups with eloquent or SQL query ?
class Group extends Model
{
use HasFactory;
protected $fillable = [
'group_name',
'description'
];
public function users(){
return $this->hasMany(User::class);
}
}
And this is the User model code:
class User extends Model implements AuthenticatableContract, AuthorizableContract
{
use SoftDeletes, Authenticatable, Authorizable, HasFactory, Notifiable;
public function getNameAttribute()
{
return $this->last_name.' '.$this->first_name;
}
public function group(){
return $this->belongsTo(Group::class);
}
}
You can use whereDoesntHave:
Group::whereDoesntHave('users')->delete();
You can make sure that you are deleting the correct groups by running this statement instead:
dump(Group::whereDoesntHave('users')->get());
I think whereDoesntHave work in you situation.
Group::query()->whereDoesntHave('users')->delete();

how to implement this sql in Laravel either using model or query builder?

My sql code is :
SELECT b.item_id as breakfast,l.item_id as lunch, d.item_id as dinner
FROM breakfast_menus as b,lunch_menus as l,dinner_menus as d
where (b.day_id=3 and l.day_id=3 and d.day_id=3)
my models are:
breakfast_id model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class breakfast_item extends Model
{
protected $fillable = [
'id', 'item'
];
}
breakfast_menu model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class breakfast_menu extends Model
{
protected $fillable = [
'day_id', 'item_id'
];
public function item()
{
return $this->belongsTo('App\breakfast_item', 'item_id');
}
public function day()
{
return $this->belongsTo('App\day', 'day_id');
}
}
day model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class day extends Model
{
protected $fillable = [
'day',
];
public function breakfast_menu()
{
return $this->hasOne('App\breakfast_menu', 'day_id');
}
}
and like this the rest models of lunch_items and lunch_menu,dinner_items and dinner_menu is declared. If required the models and relations can be changed. My main necessary is to show the data as a weekly view of breakfast ,lunch and dinner in a table
in your day Model, you have to define two relations:
public function lunch_menu()
{
return $this->hasOne('App\lunch_menu', 'day_id');
}
public function dinner_menu()
{
return $this->hasOne('App\dinner_menu', 'day_id');
}
then you load breakfast_menu,lunch_menu,dinner_menus for the day model where id for day =3
$value=day::find(3)->with(['breakfast_menu.item','lunch_menu.item',
'dinner_menus.item'])->get();
$value->breakfast_menu now is an object with an attribute called item witch has the 'id,item' field, you must check it out using debugger ....
for the literally converting you sql to ORM:
$values=Day:: addSelect([
'breakfast'=>breakfast_menu::select('breakfast_menus.item_id')
->where('breakfast_menus.item_id',3),
'lunch'=>lunch_menu::select('lunch_menus.item_id')
->where('lunch_menus.item_id',3),
'dinner'=>dinner_menu::select('dinner_menus.item_id')
->where('dinner_menus.item_id',3)
->get();
please note your original query doesn't get the items, but the item_id s

Laravel Convert Mysql query to Eloquent

I'm new to Laravel and I can write simple eloquent queries but have no idea how to convert this query to eloquent. Can anyone give any idea, is it possible to convert this to eloquent or I have to write raw query?
"Select categories.id, categories.name, Sum(likes.liked) as liked
FROM categories, likes
WHERE likes.material_id IN (SELECT category_material.material_id
FROM category_material
WHERE category_material.category_id = categories.id)
GROUP BY categories.id";
Here my Models
class Material extends Model
{
public function categories(){
return $this->belongsToMany(Category::class,'category_material');
}
public function likes(){
return $this->hasMany(Like::class);
}
////////////////////////////////////////////////////////////
class Like extends Model
{
protected $table = 'likes';
public function user(){
return $this->belongsTo(User::class);
}
public function material(){
return $this->belongsTo(Material::class);
}
//////////////////////////////////////////////////////
class Category extends Model
{
public function materials(){
return $this->belongsToMany(Material::class,'category_material');
}
You can define a likes relationship in your Category model like so:
public function likes()
{
return $this->belongsToMany(Like::class, 'category_material', 'category_id', 'material_id', 'id', 'material_id');
}
Then to achieve what you're after with Eloquent you can use a mixture of has() and withCount, however, we're going to modify the withCount call to return a sum() instead:
$catrgories = Category::has('likes')->withCount([
'likes as liked' => function ($query) {
$query->select(DB::raw('SUM(likes.liked)'));
},
])->get();
If you're wanting to return categories that don't have any likes you can remove the has() method, and introduce the COALESCE() function to your raw query:
$catrgories = Category::withCount([
'likes as liked' => function ($query) {
$query->select(DB::raw('COALESCE(SUM(likes.liked), 0)'));
},
])->get();
Alternatively, you could simply load the necessary relationships and then use that fact that Eloquent returns collection to get the value after you've retrieved the results from the database:
$categories = Category::with('materials.likes')->get()->map(function ($item) {
$item->setAttribute('liked', $item->materials->map(function ($item) {
return $item->likes->map->sum('liked')->sum();
})->first());
$item->unsetRelation('materials');
return $item;
});
This would mean that you don't have to add the custom relationship.

Search by Max of Value in Eloquent Database Laravel

How convert this Raw SQL to Eloquent Database in my API Controller?
What i'm tried is i wanna get data from Two Tables from My API Controller.
First: Formc_image Table which is general information about data
Second: Formc_image_detail which is detail and path of data
They are related by ID.
This is my API Controller FormCController.php
SELECT *
FROM formc_image_detail
WHERE id_tps=$id_tps AND jenis_pemilihan=$election_id
AND versi = (SELECT MAX(versi) FROM formc_image WHERE id_tps=id_tps AND jenis_pemilihan=$election_id)
ORDER BY no_lembar ASC
This is my Model FormCImageDetail
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class FormCImageDetail extends Model
{
protected $table = 'formc_image_detail';
public function formc_image(){
return $this->belongsTo('App\Models\FormCImage');
}
}
This is my FormCImage Models
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class FormCImage extends Model
{
protected $table = 'formc_image';
}
I was make this code in My API Controller:
return response(FormCImageDetail::with('formc_image')
->where('jenis_pemilihan', $electionId)
->where('id_tps', $tpsId)
->orderBy('no_lembar', 'ASC')->paginate(100)->jsonSerialize(), Response::HTTP_OK);
But it still error.
This is my Migration:
Schema::create('formc_image', function (Blueprint $table) {
$table->integer('id_tps');
$table->smallint('versi');
$table->string('jenis_pemilihan');
$table->timestamps();
}
Schema::create('formc_image_detail', function (Blueprint $table) {
$table->integer('id_tps');
$table->smallint('versi');
$table->integer('no_lembar');
$table->string('jenis_pemilihan');
$table->char('url_image', 100);
$table->timestamps();
}
Use this:
return FormCImageDetail::with('formc_image')
->where('jenis_pemilihan', $electionId)
->where('id_tps', $tpsId)
->where('versi', function($query) use($election_id) {
$query->select(DB::raw('max(versi)'))
->from('formc_image')
->whereColumn('id_tps', 'formc_image_detail.id_tps')
->where('jenis_pemilihan', $election_id);
})
->orderBy('no_lembar')
->paginate(100);

How to create a row for user in another related table when the user is created in laravel?

I need to create a row in a related table. This is a hasOne and belongsTo relationships.
A user hasOne profile
A profile belongsTo user
I want to create a profile row once the user has been created.
public function store(UserRequest $request)
{
$user= new User();
User::create($request->all());
Profile::create([
'user_id' => $user->user_id,
]);
return redirect()->route('users.index')
}
you can use events(observer) in laravel for doing your work when User created in any where of your project.
https://laravel.com/docs/5.3/eloquent#observers
Use Model Observers.
You can declare an observer to created event, and create the profile there.
public function creating($model)
{
// Create your related profile.
// Note that profile relationship must be defined at your model class
$model->profile()->create();
return true;
}
This observer may be created either on a Model Observer Class, or declared on model boot.
Try like this:
public function store(UserRequest $request)
{
$user = User::create($request->all());
$user->profile()->create([]);
return redirect()->route('users.index')
}
You have to have hasOne relation method in user's class:
public function profile()
{
return $this->hasOne(Profile::class);
}
This for update is not working; Is there a solution
public function update(Request $request, $id)
{
$input = $request->all();
$employee = Employee::findorfail($id);
$update = $employee->update($input);
$employee->personaldetail()->update(['employee_id' => $employee->employees_id,]);
return redirect()->route('employees.index')->with('message','Employee has been updated');
}