Multiple relationships on same table with two column Laravel - php

If the bookstore does not have any books in stock, this bookstore can purchase books from the other bookstore it is contracted with.
book_transfers table is as follows.
ID | sender_bookstore_id | delivery_bookstore_id
1 | 2 | 3
2 | 1 | 2
3 | 3 | 1
books table
ID | store_name
1 | London Garden Book Store
2 | Englaland Cafe Book
3 | Domesday Book Store
Two-column sender_bookstore_id and delivery_bookstore_id belong to the same table. The name of this table books.
My Controller code is below:
$data = BookTransfer::join('books', 'books.id', '=', 'book_transfers.sender_bookstore_id')
->select(
'book_transfers.*',
'book_transfers.sender_bookstore_id as sender_id',
'book_transfers.delivery_bookstore_id as delivery_id',
'books.store_name as sender_store_name'
)
->groupBy('book_transfers.id')
->get();
return $data;
I can only get sender_store_name here. I need to add extra code for delivery_store_name in the above controller But I don't know how to get delivery_store_name.
Best Regards,

Using relation would be much more simpler.
// BookTransfer Model
public function sender(){
return $this->belongsTo(Book::class, 'sender_bookstore_id');
}
public function delivery(){
return $this->belongsTo(Book::class, 'delivery_bookstore_id ');
}
Your controller would look like this
$data = BookTransfer::with(['sender', 'delivery'])->get();

If you want to get the datas by join, you can join the same books table again, and alias it another name:
BookTransfer::join('books AS sender_books', 'sender_books.id', '=', 'book_transfers.sender_bookstore_id')
->join('books AS delivery_books', 'deliery_books.id', '=', 'book_transfers.delivery_bookstore_id')
->select(
'book_transfers.*',
'book_transfers.sender_bookstore_id AS sender_id',
'book_transfers.delivery_bookstore_id AS delivery_id',
'sender_books.store_name AS sender_store_name',
'delivery_books.store_name AS delivery_store_name'
)

Related

Multiple category id wise show product in laravel 9

I am trying to building ecoommerce system using laravel 9. Everything goes fine but Suddenly I got one issue. I want to show product based on category id but my product table category id store multiple. Bellow I am showing my table structure:
Product Table:
|---ID---|---Name---|---Cat_id---|---Status--|
| 1 | T-shirts | 1,2, | active |
| 2 | Pants | 4,3, | active |
| 3 | Sweaters | 5,2, | active |
Category Table
|---ID---|---Name---|
| 1 | General |
| 2 | News |
| 3 | Festival |
| 4 | Category |
Controller
public function category($slug)
{
//
$cat = Category::where('slug', $slug)->first();
$products = Product::whereIn('cat_id', [$cat->id])->where('status', 'active')->orderby('id', 'asc')->paginate('12');
return view('frontend/Catproducts', compact('products', 'cat'));
}
Now I want when I am click on "NEWS" category I want to see two product. How can I fix it
As #aynber said in the comments, best solution is to normalize the database, so you have a setup like this:
Categories table:
id
name
Products table:
id
name
status
Product_categories table:
id
product_id
category_id
With a belongsToMany relationship from Product to Category(and back), your query should look something like:
$categoryIdArray = [2];
Product
::whereHas('category', function($query) use($categoryIdArray) {
$query->whereIn('id', $categoryIdArray);
})
->get();
It is still possible with your current setup though, while a little hacky:
$cat = Category
::where('slug', $slug)
->first();
$catId = $cat->id;
$products = Product
::where(function($where) {
$where->where('cat_id', 'like', "$catId,%")//Look for first cat in col, don't forget trailing comma
->orWhere('cat_id', 'like', "%,$catId,%")//Look for appended cat between commas
})
->where('status', 'active')
->orderby('id', 'asc')
->paginate('12');
This will work on small scale, but because we are using like, mysql needs to check ALL records, and cannot optimize the query. That's the reason why normalization is important :)

Getting result from array of Ids in Laravel

I've a following attendance table:
id | grade_id | subject_id | date | students
1 | 2 | 6 | 2020-05-05 | [3,6,8,11,17,21,20,19]
I want to fetch all rows with name of all students from array of Ids.
What I've tried is:
$result[] = Attendance::where('date', '=', $day)
->with('grades', 'subjects')
->join('students', function($join) {
$join->on('students.id', '=', 'attendances.id')
->where('students.id', '=', 'attendances.students');
})->get();
But couldn't get result. Please help me!
It is not a proper table structure.Will be better if you make another table like
id | attendance_id | student_id
1 | 1 | 3
1 | 1 | 6
And make its relation in model with attendance and student table.This way table will be normalized and will be easy to handle relationship.

Codeigniter using Join or where to validate a row of result

User table:
User_id(Pk,AI) | First_name | Last_name
1 | John | Doe
2 | Peter | Griffin
3 | Donald | Duck
Item table:
Item_id(PK,AI) | Owner(FK - user_id) | Item_name
1 | 1 | Shoes
2 | 2 | Pants
3 | 3 | Shirt
Item_review table:
Item_review_id(PK,AI) | Item(FK - item_id) | Reviewer(FK - user_id) | Rating |
Content
1 | 1 | 2 | 4 | Great
With the Tables above, There are three things i want to check before inserting a row into the review table.
Check if reviewer is not the item owner(cannot review own item or biased review)
Form validation(if reviewer inputted anything into the rating and content)
Check if review exists(no duplicate review or only one review per user)
That's my procedure, I've done the other two except the first one as i am unsure and confused on how to do this.
I could simply use a get where query like:
public function check_biased_review($user_id, $item_id){
$this->db->select('*');
$this->db->from('item');
$this->db->where('item_id', $item_id);
$this->db->where('owner', $user_id);
$query = $this->db->get();
if($query->num_rows() > 0){
return TRUE;}
else{
return FALSE;}
}
I actually solved this by writing the code above, i had this misconception that i would have to query so many rows if there are many reviews to find the matching rows that i forgot about the where clause in the first place which will do it in the db instead of doing it in the model function with an foreach loop and an if statement. I guess you have to code first instead of having assumptions and never doing it to check or you could waste time like i did.
But my first solution was to use a join query. $item_id and $user_id is passed from the controller to the model.
How would i go about joining the tables to get the same result?
I just try to give you an join query example below.
$this->db->select('*');
$this->db->from('Item_review');
$this->db->join('User','Item_review.user_id = User.User_id');
$this->db->join('Item','Item_review.item_id= Item.Item_id');
$this->db->where('item_id', $item_id);
$this->db->where('owner', $user_id);
$query = $this->db->get();

Laravel (5.3) Eloquent - Relationship issue

I have the following 3 tables which are normalised:
`Table: TheMovies`
id | MovieName
---------------------
1 | Zootopia
2 | Moana
3 | Toy Story
`Table: TheGenres`
id | GenreName
---------------------
21 | Action
22 | Animation
23 | Adventure
`Table: mMoviesGenres`
movieID | genreID
---------------------
1 | 21
1 | 23
2 | 22
2 | 21
3 | 23
3 | 21
As you can see in the 3rd table a movie has multiple genres, and a genre has multiple movies.
I've created TheMovies and TheGenres models in laravel.
I made sure that the relationship is made inside the models using the following code:
class TheMovies extends Model
{
public function TheGenres() {
return $this->belongsToMany('App\TheGenres', 'mMoviesGenres', 'seriesID', 'genreID');
}
}
class TheGenres extends Model
{
public function TheGenres() {
return $this->belongsToMany('App\TheMovies', 'mMoviesGenres', 'genreID', 'seriesID');
}
}
I've tested everything, and I succeeded displaying a list of genres for a particular movie, and I also succeeded displaying a list of movies for a particular genre.
The actual problem is that I want to display related movies for a particular movie based on genre.
Let's take TheMovies.id = 1 which is similar with TheMovies.id = 3, they are both Action and Adventure as you can see in the third table.
I've found out the query which is needed based on the following post:
SQL Query based on other table.
SELECT m2.movieId
FROM mMoviesGenres m1
INNER JOIN mMoviesGenres m2
ON m1.genreID = m2.genreID
WHERE m1.movieId = 1 AND
m2.movieId <> 1
GROUP BY m2.movieId
HAVING COUNT(*) >= 2
But I don't know how to transform this query in Eloquent style, and yes I can make a raw query in Eloquent, but I want to make use of the relationship created.
Please give me some advice.
You can try as:
// returns array of genre_ids associate with the TheMovies.id => 1
$genre_ids = TheGenres::whereHas('TheMovies', function($q) {
$q->where('id', 1);
})->pluck('id')->toArray();
Then use those $genre_ids to fetch the related movies as:
TheMovies::whereHas('TheGenres', function($q) use($genre_ids) {
$q->whereIn('id', $genre_ids);
})->get();
Update
Assuming you have:
$genre_ids = [21, 23];
then your query can be as:
TheMovies::whereHas('TheGenres', function($q) use($genre_ids) {
$q->whereIn('genreID', $genre_ids)
->groupBy('movieID')
->havingRaw('COUNT(DISTINCT genreID) = 2');
})->get();
Note - I have not tested it but you can give it a try.

Joining Tables in Laravel 4.2 Eloquent

I'm not so good at making queries using Laravel Eloquent. I've two tables
stories table
------------------------------------------------------------------
id | title | body | author_id |...
------------------------------------------------------------------
1 | Story 1 | Once a.. | 2
2 | Story 2 | There is | 4
3 | Something | You are. | 2
activities table
------------------------------------------------------------------
id | story_id | liker_id |...
------------------------------------------------------------------
1 | 2 | 2
Here author_id & liker_id are actually user_id. I want to get the Stories authored and liked by a specific user to display these stories in his profile.
I want to use the Eloquent ORM. I tried something like this using query builder
$stories = DB::table('stories')
->join('activities', function($join)
{
$join->on('stories.author_id', '=', 'activities.liker_id')
})
->where('stories.author_id', $author_id)
->get();
return $stories;
I can get story_id for a specific liker_id by join but couldn't get the details from stories table using story_id in a Single query.
Here is simple method with query builder to get Stories authored and liked by a specific user
$author_id = 1;
$stories = DB::table('stories')
->join('activities', 'stories.author_id', '=', DB::raw('activities.liker_id AND stories.id = activities.story_id'))
->Where('stories.author_id', $author_id)
->get();
//select * from `stories` inner join `activities` on `stories`.`author_id` = activities.liker_id AND stories.id = activities.story_id where `stories`.`author_id` = 1"
with Eloquent you can do as following create 2 model file
1. Story model (Story.php)
2. Activity Model (Activity.php)
Story.php
class Story extends Eloquent {
public function activities()
{
return $this->hasMany('Activity');
}
}
Activity.php
class Activity extends Eloquent {
public function story()
{
return $this->belongsTo('Story');
}
}
than you can write function within Story to get data as your need
$stories = Story::with('activities')
->where(DB::raw('stories.id = activities.story_id'))
->Where('stories.author_id', $author_id)
->get();
// haven't tested with eloquent but it should work

Categories