Laravel call to a member function addEagerConstraints() on boolean - php

I'm getting the following error whenever i go on to a users page, its supposed to show if the authenticated user is already following the user that the profile is on.
Could this be a problem with the relationship setup, it hasMany
Stack trace
local.ERROR: Call to a member function addEagerConstraints() on
boolean {"userId":1,"email":"fakeemail#aol.com","exception":"[object]
(Symfony\Component\Debug\Exception\FatalThrowableError(code: 0):
Call to a member function addEagerConstraints() on boolean at
/Applications/MAMP/htdocs/elipost/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:522)"}
[]
UserController.php
public function getProfile($user)
{
$users = User::with([
'posts.likes' => function($query) {
$query->whereNull('deleted_at');
$query->where('user_id', auth()->user()->id);
},
'follow',
'follow.follower'
])->with(['followers' => function($query) {
$query->with('follow.followedByMe');
$query->where('user_id', auth()->user()->id);
}])->where('name','=', $user)->get();
$user = $users->map(function(User $myuser){
return ['followedByMe' => $myuser->followers->count() == 0];
});
if (!$user) {
return redirect('404');
}
return view ('profile')->with('user', $user);
}
MyFollow(model)
<?php
class MyFollow extends Model
{
use SoftDeletes, CanFollow, CanBeFollowed;
protected $fillable = [
'user_id',
'followable_id'
];
public $timestamps = false;
protected $table = 'followables';
public function follower()
{
return $this->belongsTo('App\User', 'followable_id');
}
public function followedByMe()
{
return $this->follower->getKey() === auth()->id();
}
}
MyFollow
use Overtrue\LaravelFollow\Traits\CanFollow;
use Overtrue\LaravelFollow\Traits\CanBeFollowed;
class MyFollow extends Model
{
use SoftDeletes, CanFollow, CanBeFollowed;
protected $fillable = [
'user_id',
'followable_id'
];
public $timestamps = false;
protected $table = 'followables';
public function follower()
{
return $this->belongsTo('App\User', 'followable_id');
}
public function followedByMe()
{
return $this->follower->getKey() === auth()->id();
}
}
Post
class Post extends Authenticatable
{
protected $fillable = [
'title',
'body',
'user_id',
'created_at',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany('App\Comment');
}
public function likes()
{
return $this->hasMany('App\Like');
}
public function likedByMe()
{
foreach($this->likes as $like) {
if ($like->user_id == auth()->id()){
return true;
}
}
return false;
}
}
Likes
<?php
namespace App;
use App\Post;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Like extends Model
{
use SoftDeletes;
protected $fillable = [
'user_id',
'post_id'
];
}
User(model)
class User extends Authenticatable
{
use Notifiable,CanFollow, CanBeFollowed;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function posts()
{
return $this->hasMany(Post::class);
}
public function images()
{
return $this->hasMany(GalleryImage::class, 'user_id');
}
public function likes()
{
return $this->hasMany('App\Like');
}
public function follow()
{
return $this->hasMany('App\MyFollow');
}
public function comments()
{
return $this->hasMany('App\Comment');
}
}

As Jonas Staudenmeir stated, followedByMe isn't a relationship, it's a regular function and what it does is returning a boolean. I'm confused at why you've got a follow on your user model and trying to get information from the follow's follower? Just simplify, I see too much unneeded eager loading here.
Searching by indexed elements (id) > searching by name, any day of the week
Edit:
UserController
public function getProfile(Request $request, $id)
{
//$request->user() will get you the authenticated user
$user = User::with(['posts.likes','followers','follows','followers.follows'])
->findOrFail($request->user()->id);
//This returns the authenticated user's information posts, likes, followers, follows and who follows the followers
//If you wish to get someone else's information, you just switch
//the $request->user()->id to the $id if you're working with id's, if you're
//working with names, you need to replace findOrFail($id) with ->where('name',$name')->get() and this will give you
//a collection, not a single user as the findOrFail. You will need to add a ->first() to get the first user it finds in the collection it results of
//If you're planning on getting an attribute (is_following = true) to know if
//the authenticated user is following, you can use an accessor in the User model and write this after you've fetched the instance of the User
//$user->append('is_following');
return view ('profile')->with('user', $user);
}
User Model
//Accessor
//People who this user follows
public function getIsFollowingAttribute()
{
return MyFollow::where('followable_id',$this->attributes['id'])->where('user_id',Auth()->user()->id)->count() > 0 ? true : false;
}
//Relationships
//People who this user follows
public function follow()
{
return $this->hasMany('App\MyFollow','user_id','id');
}
//People who follows this user
public function followers()
{
return $this->hasMany('App\MyFollow','followable_id','id');
}
//Posts of this user
public function posts()
{
return $this->hasMany('App\Post','user_id','id');
}
//Likes of this user, not sure about this one tho, we're not using this for now but it could come in handy for you in the future
public function likes()
{
return $this->hasManyThrough('App\Likes','App\Post','user_id','user_id','id');
}
Post Model
//Who like this post
public function likes()
{
return $this->hasMany('App\Post','user_id','id');
}
MyFollow Model
//Relationships
//People who follow this user
public function followers()
{
return $this->hasMany('App\MyFollow','followable_id','user_id');
}
//Relationships
//People who this user follows
public function follow()
{
return $this->hasMany('App\MyFollow','user_id','followable_id');
}

With the help of #abr i found a simple fix, simple solution.
MyFollow.php(model)
public function followers()
{
return $this->hasMany('App\MyFollow','followable_id','user_id');
}
//Relationships
//People who this user follows
public function follow()
{
return $this->hasMany('App\MyFollow','user_id','followable_id');
}
User.php(model)
public function getIsFollowingAttribute()
{
return MyFollow::where('followable_id',$this->attributes['id'])->where('user_id',Auth()->user()->id)->count() > 0 ? true : false;
}
public function follow()
{
return $this->hasMany('App\MyFollow');
}
UserController.php
public function getProfile($user)
{
$users = User::with(['posts.likes' => function($query) {
$query->whereNull('deleted_at');
$query->where('user_id', auth()->user()->id);
}, 'followers','follow.followers'])
->with(['followers' => function($query) {
}])->where('name','=', $user)->get();
$user = $users->map(function(User $myuser){
$myuser['followedByMe'] = $myuser->getIsFollowingAttribute();
return $myuser;
});
if(!$user){
return redirect('404');
}
return view ('profile')->with('user', $user);
}
it works now. :)

Related

Wrong values from database

So, yesterday I asked this question : How to get reports only by id of user?
So, I need to get reports from table reports with user_id which is logged.
My model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Reports extends Model
{
protected $table = 'reports';
// public $timestamps = false;
protected $fillable = [
'user_id', 'username', 'user_id_posted', 'username_posted', 'news_id','opinion_id','event_id','career_solution_id', 'subject', 'why_reporting','why_reporting_message','additional_message','private'
];
public function career_solutionReport()
{
return $this->belongsTo('App\CareerSolution','career_solution_id','id');
}
public function eventReport()
{
return $this->belongsTo('App\Event','event_id','id');
}
public function newsReport()
{
return $this->belongsTo('App\News','news_id','id');
}
public function opinionReport()
{
return $this->belongsTo('App\Opinion','opinion_id','id');
}
public function user()
{
return $this->belongsTo('App\User','user_id','id');
}
}
I'm using this line :
$reports = \App\Reports::where('user_id', Sentinel::getUser()->id)->get();
but at dd($reports);
I'm getting a few wrong values:
so, here user_id should be only 548, which is my user_id. But also I'm getting reports from user_id 542, which isn't correctly.
I guess you have your relationship setup in your Sentinel model:
public function reports()
{
return $this->hasMany(Report::class, 'user_id', 'id');
}
Then you can do this instead:
$reports = Sentinel::getUser()->reports;

Relation isn't showed in query with Laravel

I have in model Report following
public function reportedItem()
{
return $this->belongsTo('App\Item', 'item_id', 'id');
}
In Item model
public function report()
{
return $this->hasMany('App\Report', 'item_id','id');
}
In controller
public function details( $item_id )
{
$flags = Item::find($item_id)->report->unique('user_id');
return view('flags.details', compact('flags'));
}
Why when I do {{ dd(collect($flags)) }} in my view.blade I don't see anything from items table even when I query it Item::find($item_id)?
dd output
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Report extends Model
{
protected $table = 'reports';
protected $primaryKey = 'report_id';
protected $fillable = [
'item_id', 'report_body', 'user_id', 'report_reason'
];
public function reportedItem()
{
return $this->belongsTo('App\Item', 'item_id', 'id');
}
public function user()
{
return $this->hasOne('App\User', 'id', 'user_id');
}
}
One way is to use something like this in your controller
public function details( $item_id )
{
$flags = Report::with('reportedItem')->where('item_id', '$item_id')->get();
try this
$flags = Item::find($item_id)->with('report')->get()
The below should work
$flags = Item::with('reportedItem')->find($item_id);
Then when you dd($flags) this look for the "relations" tab and inside that you'll see the info.

Sort by selectRaw relationship in Laravel (calculated count, sum ...)

I have a Question model which have morphMany Answer. Answer have also morphMany Answer and Rating
I added relationship to calculate and load Answer count and Answer rating sum :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use App\Facades\AuthManager;
class Answer extends Model {
protected $with = [
'user',
'cards',
'answers.user',
'answersCountRelation',
'ratingSumRelation'
];
protected $fillable = [
'text',
'user_id'
];
public function answerable() {
return $this->morphTo();
}
public function user() {
return $this->belongsTo(User::class);
}
public function answers() {
return $this->morphMany(Answer::class, 'answerable');
}
public function reports() {
return $this->morphMany(Report::class, 'reportable');
}
public function cards() {
return $this->hasMany(Card::class);
}
public function ratings() {
return $this->hasMany(Rating::class);
}
public function hasReported(User $user) {
return ($user != null && $this->reports()->where([
'user_id' => $user->id
])->first() != null);
}
public function hasRated(User $user) {
return ($user != null && $this->ratings()->where([
'user_id' => $user->id
])->first() != null);
}
public function answersCountRelation() {
return $this->answers()->selectRaw('answerable_id, count(*) as count')->groupBy('answerable_id');
}
public function getAnswersCountAttribute() {
return ($this->answersCountRelation->first() ? $this->answersCountRelation->first()->count : 0);
}
public function ratingSumRelation() {
return $this->ratings()->selectRaw('answer_id, SUM(power) as sum')->groupBy('answer_id');
}
public function getRatingSumAttribute() {
return ($this->ratingSumRelation->first() ? $this->ratingSumRelation->first()->sum : 0);
}
}
Now I wonder how can I load Question with Answer already sorted by answer count, rating, created_at etc
Is it possible to do it using the already eager loaded answersCountRelation or ratingSumRelation ?
Or do I have to do another request in Question->with(['answers' => function ($q) ...
Thx !

Complete Newbie at Laravel, wondering if I'm using models correctly

So I've got three models, "Incomplete", "User", and "Collaboration". They are related with foreign keys as such:
Collaboration->incomplete_id
incomplete_id->Incomplete
Incomplete->user_id
user_id->User
If I want to get the email of a user for a Collaboration model I have the following code
User::find(Incomplete::find($collab->incomplete_id)->user_id)->email);
I feel like this is wrong as I'm not joining any tables but I don't want to break out of mvc and call straight up SQL from the controller. Basically I'm curious how I could do this correctly.
Collaboration Model
class Collaboration extends Eloquent{
//Set the database to connect to as form d
protected $connection = 'formd';
//Set the table for the model to incomplets
protected $table = 'collaborations';
//Set the fillable columns
protected $fillable = array('incompid', 'link', 'shareFlag');
private $rules = array(
'link'=>'required|unique:collaborations|size:56',
'incompid'=>'required|integer'
);
private $errors;
public function validate($data)
{
// make a new validator object
$v = Validator::make($data, $this->rules);
// check for failure
if ($v->fails())
{
// set errors and return false
$this->errors = $v->errors();
return false;
}
// validation pass
return true;
}
public function errors()
{
return $this->errors;
}
public function getId(){
return $this->getKey();
}
public function incomplete(){
return $this->hasOne('Incomplete');
}
}
Incomplete Model
class Incomplete extends Eloquent{
//Set the database to connect to as form d
protected $connection = 'formd';
//Set the table for the model to incomplets
protected $table = 'incompletes';
//Set the fillable columns
protected $fillable = array('name', 'data', 'userid');
private $rules = array(
'name' => 'required|min:3',
'data' => 'required'
);
private $errors;
public function validate($data)
{
// make a new validator object
$v = Validator::make($data, $this->rules);
// check for failure
if ($v->fails())
{
// set errors and return false
$this->errors = $v->errors();
return false;
}
// validation pass
return true;
}
public function errors()
{
return $this->errors;
}
public function getId(){
return $this->getKey();
}
public function getData(){
return $this->data;
}
public function getName(){
return $this->name;
}
public function user(){
return $this->hasOne('User');
}
}
You can use Eloquents relations:
http://laravel.com/docs/eloquent#relationships
class Collaboration extends Eloquent {
public function incomplete()
{
return $this->hasOne('Incomplete', 'incomplete_id', 'id');
}
}
You can then get the data from the incomplete record by doing:
$collab->incomplete->user_id
In this case, use a relation on your models:
class Collaboration extends Eloquent {
public function incomplete()
{
return $this->belongsTo('Incomplete', 'incomplete_id');
}}
And
class Incomplete extends Eloquent {
public function user()
{
return $this->belongsTo('User', 'user_id');
}}
Then, do this:
Collaboration::find($id)->incomplete()->user()->email;
first of all you'll have to update parts of your model class
Class Collaboration extends Eloquent{
protected function incomplete(){
return $this->belongsTo('Incomplete');
}
}
Class Incomplete extends Eloquent{
protected function collaboration(){
return $this->hasOne('Collaboration');
}
protected function user(){
return $this->belongsTo('User');
}
}
Class User extends Eloquent(){
protected function incomplete(){
return $this->hasOne('Incomplete');
}
}
Then inorder to get what your want, here is the query
Collaboration::find($id)->incomplete()->user()->email;

Laravel model object chaining

For some reason, I cannot chain model objects. I'm trying to eager load 'Location' for an 'Order' and would prefer the logic to be contained in the models themselves. But past one chain, it does not work.
class Order extends Eloquent {
protected $table = 'orders';
public function customer() {
return $this->belongsTo('Customer');
public function location() {
return $this->customer()->location(); // this does not work
}
}
class Customer extends Eloquent {
protected $table = 'customers';
public function user() {
return $this->belongsTo('User');
}
public function orders() {
return $this->hasMany('Order');
}
public function location() {
return $this->user()->location();
// return $this->user(); // WORKS!!
}
}
class User extends Eloquent {
protected $table = 'users';
public function locations() {
return $this->hasMany('Location');
}
public function location() {
return $this->locations()->first();
}
}
I eventually want to do this:
class ChefController extends BaseController {
public function get_orders() {
$chef = $this->get_user_chef(); // this already works
return $chef->orders()->with('location')->get(); // does not work
}
}
Try to reference relation (user table) by adding user_id as second argument, like this:
public function user() {
return $this->belongsTo('User',"user_id");
}
Maybe you called that id field different, but you know what I mean.

Categories