how do i go getting this eloquent relationship right? - php

I have an user model and a student model which I have created relationship for, but when I try to
$student->user->fullname
I get this error
"trying to get property fullname of non-object"
here is my user model code:
<?php
namespace App;
use App\Assignment;
use App\Model\Quiz;
use App\Model\Course;
use App\Topic;
use App\Model\Guardian;
use App\Model\Student;
use App\Model\Teacher;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable, HasRoles, SoftDeletes;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'fullname',
'email',
'avatar',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function setPasswordAttribute($password)
{
$this->attributes['password'] = bcrypt($password);
}
public function guardian()
{
return $this->belongsTo(Guardian::class);
}
public function teacher()
{
return $this->belongsTo(Teacher::class);
}
public function student()
{
return $this->belongsTo(Student::class);
}
public function assignments()
{
return $this->hasMany(Assignment::class);
}
public function quizzes()
{
return $this->hasMany(Quiz::class);
}
public function courses()
{
return $this->hasMany(Course::class);
}
public function topics()
{
return $this->hasMany(Topic::class);
}
public function levels()
{
return $this->hasMany(Level::class);
}
}
and here is my student model code
<?php
namespace App\Model;
use App\User;
use App\Model\Course;
use App\Assignment;
use App\Level;
use App\Model\DoneQuiz;
use App\Model\Teacher;
use App\Model\Guardian;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
protected $fillable = ['user_id', 'level_id', 'guardian_id'];
public function user()
{
return $this->belongsTo(User::class);
}
public function courses()
{
return $this->hasMany(Course::class);
}
public function assignments()
{
return $this->hasMany(Assignment::class);
}
public function level()
{
return $this->hasOne(Level::class);
}
public function teachers()
{
return $this->hasMany(Teacher::class);
}
public function guardian()
{
return $this->hasOne(Guardian::class);
}
public function donequizzes()
{
return $this->hasMany(DoneQuiz::class);
}
}
and even when I try to use this relationship to get data like
'student_id' => auth()->user()->student()->id
I get this error
"BadMethodCallException Call to undefined method
Illuminate\Database\Eloquent\Relations\BelongsTo::id()"

when you use student() it returns a query builder
Either change it to simple student
'student_id' => auth()->user()->student->id
OR
'student_id' => auth()->user()->student()->first()->id

Related

In which model to put a function that returns all active / inactive venues of the user?

User Model:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function venues()
{
return $this->hasMany(Venue::class);
}
public function profile()
{
return $this->hasOne(Profile::class);
}
}
Venue Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Venue extends Model
{
use HasFactory;
protected $fillable = ['user_id', 'city_id', 'category_id', 'title', 'address', 'phone', 'email', 'website', 'facebook', 'instagram', 'content_bg', 'content_en', 'cover_image', 'lat', 'lng'];
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function category()
{
return $this->belongsTo(Category::class, 'category_id');
}
public function city()
{
return $this->belongsTo(City::class, 'city_id');
}
public function features()
{
return $this->belongsToMany(Feature::class, 'venue_feature');
}
public function images()
{
return $this->hasMany(VenueImage::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
}
Everything is fine, but now I want to have two methods where to call active / inactive venues of the user and I'm not sure where to place them in User Model or in Venue Model, generally which is better?
If I put them in Venue model (getUserActiveVenues and getUserInactiveVenues) and pass authenticated user to these methods, or to put them in User model (getActiveVenues and getInactiveVenues).
add relations to the user model
public function venues()
{
return $this->hasMany(Venue::class);
}
public function activeVenues()
{
return $this->hasMany(Venue::class)->where('active',true);
}
public function inActiveVenues()
{
return $this->hasMany(Venue::class)->where('active',false);
}
then you can eager load the relevant type of venue. I had to guess at what you mean be 'active'

Is there a way to make this query without raw part, between realtion models?

User Model:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function venues()
{
return $this->hasMany(Venue::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
public function profile()
{
return $this->hasOne(Profile::class);
}
public function approvedVenues()
{
return $this->hasMany(Venue::class)->where('is_approved', '=', 1);
}
public function unapprovedVenues()
{
return $this->hasMany(Venue::class)->where('is_approved', false);
}
public function ownVenuesReviews()
{
return $this->reviews()->whereIn('user_id', function($query) {
$query->select('id')
->from('venues')
->whereRaw('venues.user_id = users.id');
})->get();
}
}
Venue Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Venue extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'city_id',
'category_id',
'title',
'address',
'phone',
'email',
'website',
'facebook',
'instagram',
'content_bg',
'content_en',
'cover_image',
'lat',
'lng'
];
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function category()
{
return $this->belongsTo(Category::class, 'category_id');
}
public function city()
{
return $this->belongsTo(City::class, 'city_id');
}
public function features()
{
return $this->belongsToMany(Feature::class, 'venue_feature');
}
public function images()
{
return $this->hasMany(VenueImage::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
}
Review Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Review extends Model
{
use HasFactory;
protected $fillable = ['rating', 'content', 'venue_id', 'user_id'];
public function venue()
{
return $this->belongsTo(Venue::class);
}
public function images()
{
return $this->hasMany(ReviewImage::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
So Users have many Venues, Venues have many reviews.
I want to get reviews on own Venues for example (If I own venues with id 100, 101 - I want to get all reviews for these two venues)
Raw query is this:
SELECT * FROM `reviews` WHERE reviews.venue_id IN (SELECT venues.id FROM venues WHERE venues.user_id = 1)
What I tried in Laravel in User model (doesn't work), I'm also curious if there is a way, without raw part:
public function ownVenuesReviews()
{
return $this->reviews()->whereIn('user_id', function($query) {
$query->select('id')
->from('venues')
->whereRaw('venues.user_id = users.id');
})->get();
}
A HasManyThrough relationship should work, if I'm understanding your model relationships properly:
public function ownVenueReviews(): HasManyThrough
{
return $this->hasManyThrough(Review::class, Venue::class);
}
The raw part is only needed because you have to include the foreign key in the select portion of the sub query. Even though you may not want the user_id in the query result it must still be selected for Laravel to be able to make the relationship match work.
public function ownVenuesReviews()
{
return $this->reviews()->whereIn('user_id', function($query) {
$query->select('id', 'user_id')
->from('venues');
})->get();
}
I did it like this, but I'm not quite sure, that this is the best way, I'm open to suggestions:
public function ownVenuesReviews()
{
return Review::whereIn('venue_id', function($query) {
$query->select('id')
->from('venues')
->where('user_id', $this->id);
})->get();
}

Undefined property: Illuminate\Database\Query\Builder::$sessionId

This is my PlayerController, Player & Session Model and Resource.
I want to use the input (sessionId from SessionsTable) to fetch user from the room with the same id (userSession) and return an array in this format: [{userId:1, userName: stacki, userVote:8},{...},...]
I already asked [here][1] to achieve this and now im stuck with this error.
What do I have to change in order to solve this issue? Simply adding ->first() does not solve my issue, I need more than one record.
namespace App\Http\Controllers;
use App\Player;
use Illuminate\Http\Request;
use App\Http\Resources\Players as PlayerResource;
class PlayerController extends Controller
{
public function index(Request $request)
{
$room = $request->input('sessionId');
$currentPlayers = Player::where('userSession', $room)->get();
return PlayerResource::collection($currentPlayers);
}
public function create()
{ }
public function update()
{ }
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Player extends Model
{
protected $fillable = [];
public $sortable = [
'userId',
'userName',
'userVote'
];
public function sessions()
{
return $this->hasMany('App\Session');
}
public function players(){
return $this->belongsToMany('App\Session');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Session extends Model
{
protected $fillable = [];
public function user(){
return $this->belongsToMany('App\Player');
}
public function creator()
{
return $this->hasOne('App\Player', 'userId');
}
}
class Players extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'userId' => $this->sessionId,
'userName' => $this->userName,
'userVote' => $this->userVote
];
}
}
`
[1]: https://stackoverflow.com/questions/58062014/display-db-entries-in-json-array-in-controller-laravel-php
Your Player class might extends the Illuminate\Http\Resources\Json\JsonResource instead of ResourceCollection.
This should solve your problem.
use Illuminate\Http\Resources\Json\JsonResource;
class Players extends JsonResource
{
/**
* Transform the resource collection into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'userId' => $this->sessionId,
'userName' => $this->userName,
'userVote' => $this->userVote
];
}
}
Hope it helps.

where is the attribute in the laravel code comes from?

<?php
namespace App\Models;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
public static function boot()
{
parent::boot();
static::creating(function ($user) {
$user->activation_token = str_random(30);
});
}
public function gravatar($size = '100')
{
$hash = md5(strtolower(trim($this->attributes['email'])));
return "http://www.gravatar.com/avatar/$hash?s=$size";
}
public function statuses()
{
return $this->hasMany(Status::class);
}
public function feed()
{
return $this->statuses()->orderBy('created_at', 'desc');
}
public function followers()
{
return $this->belongsToMany(User::Class, 'followers', 'user_id', 'follower_id');
}
public function followings()
{
return $this->belongsToMany(User::Class, 'followers', 'follower_id', 'user_id');
}
public function follow($user_ids)
{
if (!is_array($user_ids)) {
$user_ids = compact('user_ids');
}
$this->followings()->sync($user_ids, false);
}
public function unfollow($user_ids)
{
if (!is_array($user_ids)) {
$user_ids = compact('user_ids');
}
$this->followings()->detach($user_ids);
}
public function isFollowing($user_id)
{
var_dump($this->followings);die();
return $this->followings->contains($user_id);
}
}
This is a code come from laravel models.
There is a method named $this->followings() .But I don't see any $this->followings attribute assigned in the code.
where is the $this->followings comes from?
thanks
Suggested reading about Laravel model relationships
in particular:
Once the relationship is defined, we may retrieve the related record using Eloquent's dynamic properties. Dynamic properties allow you to access relationship methods as if they were properties defined on the model

Trying to get the username using MODELS but getting this error: Trying to get property of non-object

ERROR: ErrorException in 814a6fb85b2cceb262c3a8191c08e42742940fc7.php line 223: Trying to get property of non-object (View: /var/www/html/m/TS/resources/views/d/show-details.blade.php)
Actually I am trying to get the username who has stored the result in the database i.e. TN has got user_id as a foreign key in the table so I need to get the username from that user_id using models but I am getting this problemTrying to get property of non-objectwhen I try to get theusername` associated with the id. I dont know where I am doing it wrong.
THE ERROR I AM GETTING IS HERE value="{{$tn->users->username}}" WHICH SHOWS IN THE CACHED FILE.
I have given my code below too to look.
Thank you in advance
Controller
public function details($id) {
$d= $this->detail->showDetails($id);
$tn= TN::find($id);
// calling functions from Model
$n = $d->tN;
$o = $d->tO;
return view('details.show-details', compact('d','o', 'n', 'tn'));
}
View
foreach($n as $n)
<input style="font-size:10px;font-weight: bold; color:black; background:#59d864;" value="{{$tn->users->username}}" readonly>
Models
User Model
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\TN;
use App\TO;
use App\UserType;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function tN() {
return $this->hasMany(TN::class);
}
public function tO() {
return $this->hasMany(TO::class);
}
public function userType() {
return $this->belongsTo(UserType::class);
}
}
TO Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\D;
use App\TT;
use App\User;
class TO extends Model
{
protected $fillable = ['o', 'date'];
public function d() {
return $this->belongsTo(D::class);
}
public function tOType() {
return $this->belongsTo(TOType::class);
}
public function users() {
return $this->belongsTo(User::class);
}
}
TN Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Debtor;
use App\TracingType;
use App\User;
class TN extends Model
{
protected $fillable = ['r', 'date'];
public function d() {
return $this->belongsTo(D::class);
}
public function tType() {
return $this->belongsTo(TType::class);
}
public function users() {
return $this->belongsTo(User::class);
}
}
Hello I have sorted this problem but forgot to post it in here the problem was here
public function users() {
return $this->belongsTo(User::class);
}
This should be public function user() rather than users. Because it belongsTo to User class, it should be singular not plural and for hasMany we use plurals. Thank you for your help though ... :)

Categories