Laravel child relationship from the same table alias issue - php

I have 2 tables structured as such:
videos table
id
comments table
id
commentable_id
commentable_type
text
And each has their own model.
Video has the following relationship to comment:
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
Here's where it get's a bit interesting though, because comments can have comments under them at 1 level, so a top level comment can contain any number of child replies but the children cannot have replies on them.
That is represented by the following relationship on the Comment model:
public function replies()
{
return $this->morphMany(__CLASS__, 'commentable');
}
The problem
I need to now sort these by a combined sum between the comment AND comment replies count.
I've tried adding a hasManyThrough relationship on the parent (Video) model but that ends up failing because the table isn't aliased (since there are technically comments through comments to get to replies).
How would I represent this relationship in laravel on the video model? What I've tried seems fruitless
SQL
I thought maybe writing out the SQL might help, but since Laravel doesn't seem to alias table names, it seems almost impossible to convert this into a provided laravel relationship
SELECT replies.*
FROM comments
RIGHT JOIN comments AS `replies`
ON `replies`.commentable_id = `comments`.id AND `replies`.commentable_type = 'comment'
WHERE `comments`.commentable_id = 'VIDEO ID'
AND `comments`.commentable_type = 'video';

Related

Linking a Model (ie. comment) to many other Models (ie. post, profile)

I am building a PHP application with Laravel where I have a Comment Model and many other models to which Comment can be attached to.
For example, a Profile can have many Comment but also a Post can have many Comment.
Should I split Comment in two models (ProfileComment and PostComment) or should I keep them together like this?
class Comment {
public function user()
{
return $this->hasOne('User');
}
public function profile()
{
return $this->belongsTo('Profile');
}
public function post()
{
return $this->belongsTo('Post');
}
}
If I keep them together, then on a database level how should I manage the comments table?
I was thinking about having the following columns:
integer: id - auto-incrementing id
integer: user_id - the user id
integer: foreign_id - profile/post id
varchar: type - which model? profile or post?
varchar: content - the actual comment
Is this the wrong approach?
if you want to use 1 table you will need to make Comment model morph.
if you don't want to use morph, make separated.
I think if you will use schema from your question, you will use morph.
I don't tkink where is need to make more tables, because all comments will have same structure (id, user_id (author), comment)
so in this case you will need just to make it morph (tagable).

two foreign keys, how to map with laravel eloquent

I have two tables in MySQL, where the first one is called users and the second one is called games. The table structure is as follows.
users
id (primary)
email
password
real_name
games
id (Primary)
user_one_id (foreign)
user_one_score
user_two_id (foreign)
user_two_score
My games table is holding two foreign relations to two users.
My question is how do I make the model relations for this table structure?? - According to the laravel documentation, I should make a function inside the model and bind it with its relations
for instance
public function users()
{
$this->belongsTo('game');
}
however I can't seem to find anything in the documentation telling me how to deal with two foreign keys. like in my table structure above.
I hope you can help me along the way here.
Thank you
A migration:
$table->integer('player1')->unsigned();
$table->foreign('player1')->references('id')->on('users')->onDelete('cascade');
$table->integer('player2')->unsigned();
$table->foreign('player2')->references('id')->on('users')->onDelete('cascade');
And a Model:
public function player1()
{
$this->belongsTo('Game', 'player1');
}
public function player2()
{
$this->belongsTo('Game', 'player2');
}
EDIT
changed 'game' to 'Game' as user deczo suggested.
Unfortunately the way you have this setup is not likely to work in the current context. You may have more luck with the belongsTo method, but again that only supports one relationship.
You could implement a user1() belongsTo, a user2() belongsTo and finally just declare a non eloquent function to return both (something like $users = array($this->user1(), $this->user2())

Laravel 4 Eloquent select

I have 3 tables
--- Posts (all the posts)
rows = id, title, content
--- Boards (all the boards)
rows = id, title
--- board_post (the link between boards and posts: many <-> many)
rows = board_id, post_id
2 Eloquent classes named board and post
now I would love to select all the posts from a board, based on board_post
I was thinking in the way of:
Posts::whereIn('id', $board->post_ids())
how would I be able to do this, that first off
that if I do Board::find(1)->post_ids I get all the post id's of that board
And then how wuld I be able to get all the post opbjects from that?
greetings Glenn
Why are you using a many-to-many relationship for Posts and Boards? It would most likely be a one-to-many relationship: A Board may have several posts, but a Post should only belong to one board (this would simplify your database structure to remove the board_post table).
You would then do:
Inside of Board class:
public function posts() {
return $this->hasMany('Post', 'board_id');
}
Then, Board::find(1)->posts would get you all of the posts for that board (use posts, not posts()).
To do it with your current database setup, use belongsToMany instead:
public function posts() {
return $this->belongsToMany('Post', 'board_post');
}
If you want to load a Board WITH all of it's posts (eager-loading) use this:
Board::with('posts')->find(1)
Otherwise, just to get the posts for a particular board, use:
Board::find(1)->posts
In Board model make sure you define belongsToMany relationship
public function posts()
{
return $this->belongsToMany('Post', 'board_post');
}
Now you should be able to do this:
Board::find({id})->posts
Forther reading material: http://laravel.com/docs/eloquent#relationships

Using pivot table with Eloquent and Laravel

Here is my problem. I have a table called news and table called categories, also I have a pivot table that connects these two called news_categories.
I am trying to fetch last 10 articles from certain category, but obviously pivot table doesn't have timestapms.
I was reading about hasMany(), belongToMany() but didn't find a good example of how it is done. Any help is appreciated
So far I have done this to News model:
public function categories(){
return $this->has_many_and_belongs_to("Categories")->withPivot('category_id', 'news_id');
}
But I have no idea how to select News based on pivot table value of category_id
You might want to read up on the Laravel 4 Eloquent Documentation a bit...
The relationship function is wrong and you don't need to specify the pivot items. The withTimestamps() function will automatically manage those on the pivot table for you.
public function categories()
{
return $this->belongsToMany('Category')->withTimestamps();
}

Cross reference table laravel 5

Lets say there are three tables:
categories
id
image_categories
image_id
category_id
images
id
My idea was that an image has multiple categories so I made a cross reference table to attach a category to an image. In my cross table (image_categories) i create a reference with image_id to the image table and category_id to the category table
Now I need to find all images that belong to a category so in my class Category I add.
public function images(){
return $this->hasManyThrough('App\Image', 'App\ImageCategory');
}
But I get an error that the column is not found.
Unknown column 'image_categories.id' in 'on clause' (SQL: select `images`.*,
`image_categories`.`subcategory_id` from `images` inner join `image_categories`
on `image_categories`.`id` = `images`.`image_category_id` where
`image_categories`.`subcategory_id` = 29)
if I look at the docs it says:
Has Many Through
The "has many through" relation provides a convenient short-cut for
accessing distant relations via an intermediate relation. For example,
a Country model might have many Post through a User model. The tables
for this relationship would look like this:
It sounds ideal for situations like this but what am I doing wrong?
If the category has multiple images and image has multiple categories, here you have a many to many relationship, the name of your pivot table will be category_image (Eloquent will join the two related model names in alphabetical order) and it should contain a both ids of the two tables as foreign key (you can add more argument to the table if you need it).
So just follow instruction in laravel docummentation Many To Many and it will work smoothly.
Note : If you Need to find all images that belong to a category so in your class Category define the images() function like bellow :
public function images(){
return $this->hasMany('App\Image');
}

Categories