Let say i have the following;
User Model;
class User extends Authenticatable
{
public function posts()
{
return $this->hasMany('App\Models\Socials\Post');
}
}
Post Model;
class Post extends Model
{
public function comments()
{
return $this->morphMany('App\Models\Socials\Comment', 'commentable');
}
Comment model;
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
When i used $user = User::find($id); and $user->posts(), it returns all the post of the user, but if i used this method $user->posts()->comments() It return this message Method Illuminate\Database\Query\Builder::comments does not exist.
The question is how can i get all the comments of the user on the said post?
Change:
$user->posts()->comments();
to:
$user->posts->pluck('comments')->collapse();
The method itself returns an instance of Eloquent's query builder allowing you to add to or edit the query if you want. However, if you don't want to edit the query you can access the relationships as properties and Laravel will handle to execution of the query.
Essentially, $user->posts is actually turning into $user->posts()->get() in the background.
Credit to #JonasStaudenmeir.
Related
Everything what I was searching tells me about Auth::user() or auth()->user() but it gives access to result of query to DB - to all fields of record.
Here are details.
Laravel 8.x
There is eloquent model called User. I created also another elo model Example. There is relation in database one-to-one so table examples has foreign key user_id. In User model I created
public function example() { return $this->hasOne(); }
and in Example:
public function user() { $this->belongsTo(); }
Now I have ExampleController with public function __contruct() - if current user doesnt have related example yet I want to run view to create it.
Tell me please what is a correct way to do that - to access current user model method?
You could use an inline middleware
use App\Models\Example;
use Illuminate\Support\Facades\Auth;
class ExampleController extends Controller
{
/**
* Instantiate a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware(function ($request, $next) {
if ( Example::where('user_id', Auth::id())->doesntExist() ) {
return redirect('user-has-no-example');
}
return $next($request);
});
}
}
I have a pivot table post_profile that contains the hearts (likes) of each post.
Post.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
public function profilesHearted()
{
return $this->belongsToMany(Profile::class);
}
}
Profile.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
protected $guarded = [];
public function profileImage()
{
$imagePath = ($this->image) ? $this->image : 'profile/czyhBQu2YWX6gvBivZrnEs2ORoBwr3d9mzkwxk8k.png';
return $imagePath;
}
public function followers()
{
return $this->belongsToMany(User::class);
}
public function heartedPosts()
{
return $this->belongsToMany(Post::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
The main view which shows all posts of followed users is working along with the heart button but underneath I want to show liked by <x> and 30 others, where x is first follower of the user if any of the user's follower hearted the post. I tried many ways to get x but I am a bit lost.
This is PostsController.php index function which leads to the view:
public function index()
{
$users = auth()->user()->following()->pluck('profiles.user_id');
$posts = Post::whereIn('user_id', $users)->with('user')->latest()->paginate(5);
return view('posts.index', compact('posts', 'users' ));
}
What I tried to do but deleted eventually after failing is get each post in foreach loop and check if each $post->heartedProfiles(contains($users)), but this doesn't work this way. So another way I tried is in my view ie, index.blade.php
#foreach($users as $userid)
User::select('id')->where('profile_id', $userid)->first()
->profile->profilesHearted->find($post->id)
#endforeach
Which doesn't work because User class cannot be used directly in view without passing.
I'm sure there is a simple and cleaner way to do this in Laravel. This is my first time using Laravel and ORM programming so really felt lost. Took the FreeCodeCamp Instagram clone tutorial and understood the basics. All I need is to give me some idea to get started.
When dealing with many to many you need to use the pivot functions, so you would do like so
Post::profilesHearted()->wherePivotIn('profile_id', $users)->first()
Not checked the code but hopefully it will give you the idea.
I have two tables users and user_details. I have linked users table as
public function userDetails()
{
return $this->hasOne('App\Repositories\Models\UserDetails', 'id', 'user_id');
}
and linked user_details table as
public function user()
{
return $this->belongsTo('App\Repository\Models\User');
}
While from UserController for accessing users data with details, if I try to access the data
return $this->user->with('userDetails')->get();
I get this type of error
FatalErrorException in HasRelationships.php line 488: Call to undefined method
App\Repositories\Models\UserDetails::getConnectionName()
Is there anything wrong?
Make sure UserDetails class extends Model class:
use Illuminate\Database\Eloquent\Model;
class UserDetails extends Model
You can also clean up your code like this. Having neat code will make your code more valuable and it will be easier for other developers to understand or you to remember when you get back to your code later on.
use Illuminate\Database\Eloquent\Model;
use App\Repository\Models\User;
use App\Repository\Models\UserDetails;
public function user()
{
return $this->belongsTo('User');
}
public function userDetails()
{
return $this->hasOne('UserDetails', 'id', 'user_id');
}
I am busy with Laravel From Scratch: Updating Records and Eager Loading. I have followed the tut but I am getting this error when trying to add user data in CardsController. I am assuming that I've missed a step in the card user relationship somewhere but I've watched the video 3 times and my database queries for User, Card & Note matches the video exactly.
Is there another step I need to perform after creating the Users table via the migration perhaps?
Error
BadMethodCallException in Builder.php line 2345:
Call to undefined method Illuminate\Database\Query\Builder::user()
CardsController code
<?php
namespace App\Http\Controllers;
use App\Card;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class CardsController extends Controller
{
public function index()
{
$cards = Card::all();
return view('cards.index', compact('cards'));
}
public function show(Card $card)
{
$card = Card::with('notes.user')->get();
return $card;
return view('cards.show', compact('card'));
}
}
Your note model is lacking the relationship definition for it's associated user, it looks like.
You should just be able to add the relationship in the Notes model like this:
public function user()
{
return $this->belongsTo(User::class);
}
That video does have some problems, so I also encountered the same problem.
You should just be able to add the relationship in the Note model like this:
public function user()
{
//return $this->belongsTo(User::class);
return $this->belongsTo('App\User');
}
and in the User model like this:
public function notes()
{
return $this->hasMany(Note::class);
//return $this->belongsTo('App\Note');
}
bless you !
TLDR: When the SoftDeletes trait is included in my parent model, I no longer get soft deleted instances of the parent model as a dynamic property of the child. How can this be done?
I have defined a couple of basic models, like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Builder;
class User extends Model
{
use SoftDeletes;
public function posts()
{
return $this->hasMany("App\Post");
}
}
class Post extends Model
{
public function user()
{
return $this->belongsTo("App\User");
}
public function scopePending(Builder $query)
{
return $query->whereNull("pending");
}
}
In my controller, I want to list pending posts, so I do this:
<?php
namespace App\Controllers;
use App\Post;
class PostController extends Controller
{
public function index()
{
$posts = Post::pending()->get();
return view("post.index", ["pending"=>$posts]);
}
}
And finally, in my view:
#foreach($pending as $post)
{{ $post->title }}<br/>
{{ $post->user->name }}<br/>
#endforeach
This results in an exception being thrown, "Trying to get property of non-object" with the line number corresponding to where I try to output $post->user->name for users which have been soft deleted.
How can I have these dynamic properties include soft deleted items?
Apparently the related user model has been soft-deleted, that's why the related user is not loaded.
Define the relation like in the code below and you'll be always able to fetch a user regardless if they have been soft-deleted or not:
public function user()
{
return $this->belongsTo("App\User")->withTrashed();
}
Unfortunately if you do so
public function user()
{
return $this->belongsTo("App\User")->withTrashed();
}
you will no longer available to use dynamic access to user relation, because dynamic access expects that relation method returns BelongsTo instance, which returns by belongsTo method of Eloquent class. But withTrashed returns Builder instance.
EDIT
I was wrong, thanks #patricius for being guided on the right path (in comments).