How to get images that are liked by a certain user? - php

I'm trying to create a variable that contains the last 7 images that have been liked by a user with certain id so I can pass that variable to my view. I believe I have to use whereHas() but so far nothing I've tried work so it's probable I might be doing it wrong.
The tables I have are:
Table: Votes
Columns: id, user_id, image_id, vote
Table: Users
Columns: id, username, password
Table: Images
Columns: id, name, user_id, path
In the votes table, if the vote value is 1, it is a like and of it is 0, it is a dislike.
I have models for the 3 tables like this:
Image
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Image extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
public function votes(){
return $this->hasMany('App\Vote');
}
}
User:
<?php
namespace App;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements Authenticatable
{
use \Illuminate\Auth\Authenticatable;
public function images(){
return $this->hasMany('App\Image');
}
public function votes(){
return $this->hasMany('App\Vote');
}
}
Vote:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Vote extends Model
{
public function images(){
return $this->belongsTo('App\Images');
}
}
I was able to figure something close to what I have in mind:
$likedImages = Image::where('parent_id', NULL)->whereHas('votes', function($q) use ($vote) {
return $q->where('vote', $vote);
})->orderBy('created_at', 'desc')->limit(7)->get();
Unfortunately, this gets liked images by everyone and not just the specific user.

Normally whereHas() will do the trick, if you want the images that has been voted you do something like
Image::whereHas('votes',function($votes) {
//if you want to get only votes with 1 you do
$votes->where('vote',1);
})
//if you want to get the latest 7 images you order them and take 7
->orderBy('id','DESC')
->take(7)
->get();
That will get you all the images that has a votes row, If that fails, maybe your relationships are not set properly.

You need to use the Vote model, and fetch the recent 7 votes where the like value is 1 and LEFT JOIN the images table.
I am not an ORM specialist but...
An untested example:
$votes = Vote::where([
["user_id", "=", $userId],
["vote", "=", 1]])->leftJoin("images", "user_id", "=", "images.user_id")->latest()->take(7);
Again, this is untested, but I gave you the idea.

Related

Is it possible to grouping by from and to user id in Laravel 8

I am having One-to-One chat simple table, where message store as from user id and to user id. here is schema.
I am retrieving conversation between two user by matching either from_user_id match with login user or to_user_id as
->where(function($q) use($user_id) {
$q->where('from_user_id', $user_id)
->orWhere('to_user_id', $user_id);
})
Now i want a unique conversation between login user and other users. i have tried as
->groupBy('from_user_id', 'to_user_id')
but it return both record id : 1 and 6 because it stored as 65 - 66 and 66 - 65.
So any way that i can group by with unique conversasion and get only one record for the same. or i need to change schema of table as conversation and conversation_message.
Please guide me.
Thanks.
I would recommend adding a Conversation model. You basically want a unique identifier for each user-to-user relationship (and all messages therein), and a Conversation model will be the most succinct way to accomplish that.
That being said, there are clever ways of doing what you want to do without an extra model. Since you know the logged in user's ID, you can pass a callback to the Collection's groupBy method that groups by the ID that isn't the logged-in user. For example:
->where(function($query) {
$query->where('from_user_id', $user_id)
->orWhere('to_user_id', $user_id)
})
// So the messages appear in order.
->orderByDesc('created_at')
->get()
->groupBy(function($item) use ($user_id) {
// If the message was sent by the user, it groups on the recipient's ID.
// If the message was received by the user, it groups on the sender's ID.
return $item->from_user_id == $user_id ? $item->to_user_id : $item->from_user_id;
});
This example doesn't account for a user sending messages to themselves (which may be possible in your system), so it may need fine-tuned.
Recently, I coded a chat system for my company. I tried many schemas but finally found the best one. I can share it with you.
This schema may consist of several tables and will force you to send more requests. But in this structure you will be able to handle all tasks easily. Here you are model and controller structure:
ChatMessage:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ChatMessage extends Model
{
use HasFactory;
public $table = "chat_messages";
protected $fillable = ['chat_id', 'user_id','content'];
public function chat()
{
return $this->belongsTo(ChatUser::class, 'chat_id', 'id');
}
public function user()
{
return $this->belongsTo(User::class);
}
}
ChatUser:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ChatUser extends Model
{
use HasFactory;
public $table = "chat_users";
protected $fillable = ['user_id_from', 'user_id_to','last_activity'];
protected $dates = ['last_activity'];
public function user_from()
{
return $this->belongsTo(User::class, 'user_id_from', 'id');
}
public function user_to()
{
return $this->belongsTo(User::class, 'user_id_to', 'id');
}
public function messages()
{
return $this->hasMany(ChatMessage::class, 'chat_id', 'id')->latest('id')->take(15);
}
}
ChatController:
public function index()
{
$chats = ChatUser::has('messages')
->where('user_id_from', $this->user->id)
->orWhere(function ($query) {
$query->where('user_id_to' , $this->user->id);
})
->with(['user_to','user_from'])
->orderBy('last_activity', 'DESC')
->get();
return $this->successResponse(new ChatCollection($chats));
}
If you have any questions don't hesitate to ask.

Retrieve data from database filtered by pivot table Laravel

I've got table structure like this:
users:
id
name
managers:
id
user_id
user_manager:
manager_id
user_id
vacations:
user_id
date_from...
My task is to fetch all data from vacations table where user (vacations.user_id) belongs to given manager id (managers.user_id) and that assigment is in pivot table user_manager. User can have many managers, manager can have many users. I've been trying to do this, but I've got stuck. My workaround was this:
DB::table("vacations")
->leftJoin("users", function ($join) {
$join->on("vacations.user_id", "=", "users.id");
})
->leftJoin("user_manager", function ($join) {
$join->on("user_manager.user_id", "=", "users.id");
})
->where("user_manager.manager_id", "=", $id)
->get();
But I want to know a way to make this with eloquent model and all of it's fancy stuff.
Manager model:
class Manager extends Model
{
use HasFactory;
protected $table = 'managers';
protected $fillable = ['user_id'];
public function users()
{
return $this->belongsToMany(User::class, 'employee_manager')->withTimestamps();
}
}
User model:
class User extends Model
{
use HasFactory, Notifiable;
public function managers()
{
return $this->belongsToMany(Manager::class, 'employee_manager')->withTimestamps();
}
}
You are trying to get all Vacation records which created by a User which belongs to a specific Manager
It means you need to get all Vacations where user_id in that Manager
's users()
You can achieve this with a basic way like this;
$vacationsThatConcernTheManager = Vacation::whereIn('user_id', $manager->users()->pluck('id'))->get();
And if you want use directly something like $manager->vacations() you can use hasManyThrough as described in documentation.
Add this relation to your Manager model;
public function vacations()
{
return $this->hasManyThrough(Vacation::class, User::class);
}

Get model data based on pivot table column

# TABLES:
# kids: name, birthday, active
# chores: name, start_age, number_of_kids_required
# chore_kid: chore_id, kid_id, chore_date
Kid.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Kid extends Model
{
public function chores(){
return $this->belongsToMany('App\Chore')
->withPivot('chore_date')
->withTimestamps();
}
}
Chore.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Kid;
class Chore extends Model
public function kids(){
return $this->belongsToMany('App\Kid')
->withPivot('chore_date')
->withTimestamps();
}
}
With belongs to many I can grab the chores with assigned kids and the pivot table having the requested chore date:
$chore->kids()->wherePivot('chore_date', $date);
How can I get all the chores with the same chore_date without limiting it to the kids that are assigned to a specific chore.
How do I do this? This is my guess at this but it doesn't work:
Chore::wherePivot('chore_date', $date);
I have tried other combinations, but can't seem to find the right syntax.
controller
$chore = Chore::whereHas('kids', function ($query) use ($date){
$query->where('chore_date','=', $date );
})->get();
with that you'll get chore with specific date. hope that help.

one to many relationships in laravel

Each industry has many projects
each project belongs to only one industry
industries table has columns as below:
id, industry_name, industry_code, created_at, updated_at
projects table has columns as below:
id, industry_id (foreign key), user_id, project_name, project_start_date, project_end_date, created_at, updated_at
I want to show project name and industry name in my index.blade.php (view)
I have created Project & Industry models. How do I show the result in my view?
Industry.php model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Industry extends Model
{
public function project()
{
return $this->hasMany('App\Models\Project');
}
}
Project.php model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
public function industry()
{
return $this->belongsTo('App\Models\Industry');
}
}
like this ...
$Industry = App\Industry ::find(1);
echo $Industry ->Project ->project_name;
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many
do try renaming your method "project" to "projects" in Industry.php since it is a "hasMany" relationship. this would prevent you from making errors.
in your controller, say PagesController.php
public function index() {
// find an industry with id of 1
$Industry = App\Industry ::find(1);
return view('some_view',compact('industry'));
}
therefore in your view, since an industry has many projects you can access them and loop over them by $Industry->projects. However you should consider eager loading them in order to prevent the n + 1 problem. there edit your query to $Industry = App\Industry ::with('projects')->find(1);
read more on eager loading https://laravel.com/docs/5.5/eloquent-relationships#eager-loading
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many
If specifically you want only project_name and industry_name then
try this -
$result = App\Industry::with(array('projects'=> function($query){
$query->addSelect(['project_name']);
}))
->where('industry.id',$id)
->get([industry_name]);
else for all records try this -
$result = App\Industry::with('projects')
->where('industry.id',$id)
->get();
Hope this will help you.

Laravel: How do I create the relationship and which one do I use?

I have the database structure that have a classes table, a users table and users_classes table that matches the other two, because a user can belong to multiple classes. I have a problem now. I have code like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class Classes extends Model
{
protected $table = 'classes';
public function students()
{
}
}
And I want to be able to access the students of the class by typing $class = Classes::find(1) and then $class->students to access the students. How do I define the relationship without using the query builder? I want to use eloquent. Im a noobie in Laravel pls dont downvote.
You use a belongsToMany relation.
If your users_classes table has the fields user_id and class_id you can do the following:
public function students()
{
return $this->belongsToMany(Student::class, 'users_classes', 'class_id', 'user_id');
}

Categories