I am using laravel 5.1 for a CMS development. I have a simple structure of posts, users and users can like posts.
Posts and Users have many-to many relationship and use a pivot table for relationship.
Posts Model has
public function likedby()
{
return $this->belongsToMany('App\Models\User','user_like_post')
->withTimestamps();
}
User Model has
public function likes(){
return $this->belongsToMany('App\Models\Post','user_like_post')
->withTimestamps();
}
I want to list the latest activity of the users. For e.g.
Username1 likes Post2
Username5 likes Post9
Username30 likes Post25
I know I have to write an sql query like this -
mysql > select users.name, posts.heading from user_like_post as ulp
> join users on ulp.user_id=users.id
> join posts on ulp.post_id=posts.id
> order by ulp.created_at desc limit 10;
The above query works fine but is there a way to do it using laravel eloquent?
If you want pure eloquent solution, then you need additional model for the pivot table:
class PostUser extends Model {
protected $table = 'user_like_post';
public function post()
{
return $this->belongsTo(Post::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
// then something like this
$activity = PostUser::latest()->take(10)->get();
#foreach ($activity as $action)
{{ $action->user->name }} likes {{ $action->post->title }}
#endforeach
Other than that you would need joins in order to sort the results by pivot table.
Related
I'm trying to remake this query:
return DB::select(DB::raw("SELECT COUNT(orders.id), name FROM orders JOIN users ON orders.manager_id = users.id GROUP BY users.id"));
I have Order model which has links to another tables using belongsTo() method, there are several of them:
public function user()
{
return $this->belongsTo(User::class);
}
public function post()
{
return $this->belongsTo(Post::class);
}
public function manager()
{
return $this->belongsTo(User::class, 'manager_id');
}
When I use simple queries like Order::all() it works fine but I've tried to call this:
return Order::groupBy('users.id')
->selectRaw('COUNT(orders.id), name')
->get();
Of course, Laravel don't know should I use either user name or manager name as it's two relations with users table in Order. How should I write the query above properly?
return Order::groupBy('users.id')
->select(DB::raw('COUNT(orders) AS TOTAL_ORDERS'))
->addSelect('name')
->get();
You can count with DB:raw i think it will work for u.
I'm trying to retrieve related models of the same type on from a pivot table.
I have 2 models, App\Models\User and App\Models\Group and a pivot model App\Pivots\GroupUser
My tables are have the following structure
users
id
groups
id
group_user
id
user_id
group_id
I have currently defined relationships as
In app/Models/User.php
public function groups()
{
return $this->belongsToMany(Group::class)->using(GroupUser::class);
}
In app/Models/Group.php
public function users()
{
return $this->belongsToMany(User::class)->using(GroupUser::class);
}
In app/Pivots/GroupUser.php
public function user()
{
return $this->belongsTo(User::class);
}
public function group()
{
return $this->belongsTo(Group::class);
}
I'm trying to define a relationship in my User class to access all other users that are related by being in the same group. Calling it friends. So far I've tried this:
app/Models/User.php
public function friends()
{
return $this->hasManyThrough(
User::class,
GroupUser::class,
'user_id',
'id'
);
}
But it just ends up returning a collection with only the user I called the relationship from. (same as running collect($this);
I have a solution that does work but is not ideal.
app/Models/User.php
public function friends()
{
$friends = collect();
foreach($this->groups as $group) {
foreach($group->users as $user) {
if($friends->where('id', $user->id)->count() === 0) {
$friends->push($user);
}
}
}
return $friends;
}
Is there a way I can accomplish this using hasManyThrough or some other Eloquent function?
Thanks.
You can't do that using hasManyThrough because there is no foreign key on the users table to relate it to the id of the group_user table. You could try going from the user to their groups to their friends using the existing belongsToMany relations:
app/Models/User.php:
// create a custom attribute accessor
public function getFriendsAttribute()
{
$friends = $this->groups() // query to groups
->with(['users' => function($query) { // eager-load users from groups
$query->where('users.id', '!=', $this->id); // filter out current user, specify users.id to prevent ambiguity
}])->get()
->pluck('users')->flatten(); // massage the collection to get just the users
return $friends;
}
Then when you call $user->friends you will get the collection of users who are in the same groups as the current user.
I have 3 tables users, companies and pivot table with user_id, company_id.
I can't get users, which belongs to my company inside User model.
Tried like
belongsToMany('App\User','companies_users','company_id','user_id' );
but I get relation with wrong users.
Since you are having a belongsToMany relationship between the User and Company, the User belongs to more than one Company. To get users of the companies of a particular User will not be straight forward. If you are sure that is exactly what you want, then do this:
//inside the User model
public function companies()
{
return $this->belongsToMany('Company');
}
//inside the User model
public function companiesusers()
{
$users= new Illuminate\Database\Eloquent\Collection;
foreach($this->companies as $company)
{
$users = $users->merge($company->users->get());
}
return $users->unique();
}
//inside the Company model
public function users()
{
return $this->belongsToMany('User');
}
Then you can get a user's companiesusers like so:
User::first()->companiesusers();
I want to build query like this in laravel 5.3
SELECT p.post_text, p.bbcode_uid, u.username, t.forum_id, t.topic_title, t.topic_time, t.topic_id, t.topic_poster
FROM phpbb_topics t, phpbb_posts p, phpbb_users u
WHERE t.forum_id = 9
AND p.post_id = t.topic_first_post_id
AND u.user_id = t.topic_poster
ORDER BY t.topic_time
DESC LIMIT 10
Consider for example there are two tables one is users and the other is posts
while creating migration add user_id foreign key to your posts table as
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
create User and Post model, and in your User model define relationship to Post as
public function post(){
return $this->hasMany(Post::class);
}
and in your Post model define a relationship to User model as
public function user(){
return $this->belongsTo(User::class);
}
now you can get the user from Post model
$post = Post::findOrFail(1);
return $post->user;
I have a posts and a users table.
In the posts table, i have a posts_author which is the ID of the user from the users table.
Is there an easy way to display the email address of the user, which is in the users table?
Cheers,
As long as you've set your relationships up it should just be a simple query.
http://laravel.com/docs/eloquent#relationships
Look at the one to many relationships.
(1 User, Multiple posts)
Remember to set the inverse of the relationship up also
If your model has the right relationships then should be as simple as $post->author->email().
You must tweak the author relationship because Eloquent assumes the key will be named author_id.
// Post
public function author() {
return $this->belongsTo('Author', 'posts_author');
}
// Author
public function posts() {
return $this->hasMany('Post');
}
Remember to use eager loading in case you are retrieving emails from more than one post object, or you will end up with n+1 queries.
Providing that you've configured the relationships properly, it should be pretty easy.
Post Model:
class Post extends Eloquent
{
protected $table = 'posts';
public function author()
{
return $this->belongsTo('User', 'posts_author');
}
}
Then User Model:
class User extends Eloquent
{
protected $table = 'users';
public function posts()
{
return $this->hasMany('Post', 'posts_author');
}
}
Then when loading the post you can do the following.
$post = Post::with('author')->find($id);
This will tell Eloquent to join on the users table and load the user data at the same time. Now you can just access all of the user information like this:
$post->author->username;
$post->author->email;
$post->author->id;
// etc etc
Obviously this is just a skeleton, but the assumption is that you have the rest setup.