Wrong values from database - php

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;

Related

How to obtain three level model data laravel

Updated
User model
class User extends Authenticatable
{
use HasFactory, Notifiable, HasApiTokens, HasRoles;
const MALE = 'male';
const FEMALE = 'female';
protected $guard_name = 'sanctum';
public function educationalBackgrounds()
{
return $this->hasMany("App\Models\Users\EducationalBackground", "user_id");
}
public function seminars()
{
return $this->hasMany("App\Models\Users\Seminar", "user_id");
}
}
I have child table EducationalBackground which is related to User table
class EducationalBackground extends Model
{
use HasFactory;
protected $table = 'users.educational_backgrounds';
protected $fillable = [
'user_id',
'studies_type',
'year',
'course',
];
public function user()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
public function educationalAwards()
{
return $this->hasMany("App\Models\Users\EducationalAward", "educational_background_id");
}
}
And a third table that i want to access the award field
class EducationalAward extends Model
{
use HasFactory;
protected $table = 'users.educational_awards';
protected $fillable = [
'educational_background_id',
'award',
'photo',
];
public function educationalBackground()
{
return $this->belongsTo('App\Models\Users\EducationalBackground', 'educational_background_id');
}
}
I have api get route here
Route::get('/educational-background/{id}', [UserProfileController::class, 'getEducationalBackground']);
Here is my api method it works fine. But i want to go deeper and access the data of third table.
public function getEducationalBackground($id)
{
$educationalBackground = EducationalBackground::with('user')->where('user_id', $id)->get();
return response()->json($educationalBackground, 200);
}
It looks like you're not really grasping the concept of relations yet. Also, I'd advise you to look into route model binding :) What you basically want to be doing is:
public function getEducationalBackground($id)
{
$user = User::find($id);
return $user->educationalBackgrounds()->with('educationalAwards')->get();
}
Also, when you're pretty sure that whenever you want to use backgrounds, you also want to use the awards, you can add the with(...) to the model definition like so:
class EducationalBackground extends Model
{
...
protected $with = ['educationalAwards'];
}
That way, you can simplify your controller method to:
public function getEducationalBackground($id)
{
$user = User::find($id);
return $user->educationalBackgrounds;
}

Laravel call to a member function addEagerConstraints() on boolean

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. :)

One to Many Relationship - Laravel & Mysql

In my application, Users can have many products. Now, i am trying to display the users phone number for a every displayed products.
In my products table, there is a column user_id for the respective users.
This is how my model looks like
User Model
public function products()
{
return $this->belongsTo('Models\Database\User','user_id');
}
Product Model
class Product extends BaseModel
{
protected $fillable = ['user_id','type', 'name', 'slug', 'sku', 'description',
'status', 'in_stock', 'track_stock', 'qty', 'is_taxable', 'page_title', 'page_description'];
// protected $guarded = ['id'];
public static function getCollection()
{
$model = new static;
$products = $model->all();
$productCollection = new ProductCollection();
$productCollection->setCollection($products);
return $productCollection;
}
public function users()
{
return $this->hasMany('\Models\Database\Product');
//->withTimestamps();
}
public function categories()
{
return $this->belongsToMany(Category::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
public function prices()
{
return $this->hasMany(ProductPrice::class);
}
public function orders()
{
return $this->hasMany(Order::class);
}
public function users()
{
return $this->hasMany('Models\Database\Product');
}
And in my view, this is how i try to get the respective user's phone number
<p>{{$product->users->phone}}</p>
But i get an error like
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'products.product_id' in 'where clause' (SQL: select * from products
where products.product_id = 1 and products.product_id is not
null)
You should do:
User Model
public function products()
{
return $this->hasMany('Models\Database\Product');
}
Product Model
public function user()
{
return $this->belongsTo('Models\Database\User');
}
In your blade:
{{ $product->user->phone }}
You have got your relationship models inverted,
change them:
In your User model:
public function products()
{
return $this->hasMany('Models\Database\Product');
}
In your Product model:
public function user()
{
return $this->belongsTo('Models\Database\User','user_id');
}
And then you could access the properties like:
<p>{{$product->user->phone}}</p>
Link to the Docs

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.

Laravel Eloquent: How to automatically fetch relations when serializing through toArray/toJson

I figures this works for automatically fetching user and replies when I am serializing my object to JSON, but is overriding toArray really the proper way of doing this?
<?php
class Post extends Eloquent
{
protected $table = 'posts';
protected $fillable = array('parent_post_id', 'user_id', 'subject', 'body');
public function user()
{
return $this->belongsTo('User');
}
public function replies()
{
return $this->hasMany('Post', 'parent_post_id', 'id');
}
public function toArray()
{
$this->load('user', 'replies');
return parent::toArray();
}
}
Instead of overriding toArray() to load user and replies, use $with.
Here's an example:
<?php
class Post extends Eloquent
{
protected $table = 'posts';
protected $fillable = array('parent_post_id', 'user_id', 'subject', 'body');
protected $with = array('user', 'replies');
public function user()
{
return $this->belongsTo('User');
}
public function replies()
{
return $this->hasMany('Post', 'parent_post_id', 'id');
}
}
Also, you should be using toArray() in your controllers, not your models, like so:
Post::find($id)->toArray();
Hope this helps!
I must submit a new answer since I'm a SO pleb. A more proper way to accomplish this for those finding this on Google like I did would be to avoid using protected $with if you don't have to and instead move that with() call to your retrieval.
<?php
class Post extends Eloquent
{
protected $table = 'posts';
protected $fillable = array('parent_post_id', 'user_id', 'subject', 'body');
public function user()
{
return $this->belongsTo('User');
}
public function replies()
{
return $this->hasMany('Post', 'parent_post_id', 'id');
}
}
And then you could modify the Post call to pre-load as needed:
Post::with('user','replies')->find($id)->toArray();
This way, you won't be including un-needed data every time you grab a record, if you don't need it.

Categories