Laravel Relationships - access input from other table - php

I cant get this working. This should be easy, but I cant figure out how to access a users gamer tag from different table using relationships.
Here is my User.php Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'gamertag', 'slug', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
];
// A user has many messages (Chat)
public function chat () {
return $this->hasMany('App\Chat');
}
}
Here is my Chat.php Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Chat extends Model {
protected $table = "chat";
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'message', 'user_id'
];
// A Chat (or message) belong to a user
public function user() {
return $this->belongsTo('App\User');
}
}
And this is how I;m retrieving the messages:
class HomeController extends Controller {
public function index () {
$messages = Chat::orderBy('created_at', 'desc')->get();
return view('layouts.index', compact('messages'));
}
}
Why Im I having trouble getting the gamer tag to display?
#foreach($messages as $message)
<a class="author">{{ $message->user->gamertag }}</a>
#endforeach
/***** Edit***/
This works:
{{ dd($message->user->gamertag) }}
// This does NOT
{{ $message->user->gamertag }}

Try to use eager loading:
$messages = Chat::orderBy('created_at', 'desc')->with('user')->get();

I figured it out! Everything was working here, its just in my chat table, I had inserted a message with no identified user, so user_id = 0, and it was throwing that error off. Silly mistake.

Related

Laravel 8 belongsTo relationship not returning data on User model

I'm building a Laravel 8 API and want to automatically join user_settings onto a user whenever the User model is queried.
My thinking is that I can achieve this with the belongsTo relationship since user_settings "belongs" to a user.
However, when I attach this to my UserSetting model and query a user I'm not seeing any user settings attached to my User despite having data in the user_settings table.
Where am I going wrong?
Model: User
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class UserSetting extends Model
{
use HasFactory, SoftDeletes;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'user_settings';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_id',
'theme',
'refreshButtonPlacement',
'animationSpeed',
'fetchTimeout'
];
/**
* Get the user that owns the comment.
*/
public function user()
{
return $this->belongsTo(UserSetting::class);
}
}
Model: User
<?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 Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use HasFactory, Notifiable, SoftDeletes;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name',
'last_name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password'
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
'last_login_at' => 'datetime'
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
I also tried using a One To One relationship and defined a settings method on my User model but in Tinker when I ran User::findOrFail(1)->settings; I had nothing either.
Relationship setup:
class User extends Model
{
//some custom stuff
/**
* Get the phone associated with the user.
*/
public function user_setting()
{
return $this->hasOne(UserSetting::class);
}
}
class UserSetting extends Model
{
//some custom things
/**
* Get the user that owns the comment.
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
Afterwards you can use eager laoding by default, in your case you will have to add $with = ['user_setting'] to your User class.
You could also use the ->with() method, for that you will have to use either:
User::with('user_setting')->find(Auth::id());
//or
Auth::user()->with('organisation')->first()
Laravel doesn't load the relationship values in every call because of the obvious overhead. So you will either define the relationship to be loaded by default or you will have to work with the ->with() method for eager loading the relationship.
Add this method to your User model
And you can access the user settings through a dynamic attribute $user-> user_setting
on each User model instance
For more informations
https://laravel.com/docs/8.x/eloquent-relationships#one-to-one
public function user_setting(){
return $this->hasOne(UserSetting::class);
}

Userpermission pivot-function is only accessible via the Auth class

I have a simple Userpermission System consisting of 3 tables: users, permissions and the pivot table permission_user.
This is the User model:
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* 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',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function permissions()
{
return $this->belongsToMany('App\Permission');
}
}
and here is the Permission Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'description', 'level', 'parentpermission',
];
public function users()
{
return $this->belongsToMany('App\User');
}
}
Now when I try to get all the permissions of the currently logged in user with this:
$user_permissions = Auth::user()->permissions()->get();
it works without problems.
But when I try to get another Users Permissions like this:
$user_permissions = User::where('id', '=', $userid)->permissions()->get();
I get the following error:
Method Illuminate\Database\Eloquent\Collection::permissions does not exist.
How do I proceed?
I think you're missing first() here, since you can't get relations of a query builder object. Try this :
$user_permissions = User::where('id', '=', $userid)->first()->permissions()->get();
This first() will actually return User object, and then you can load its relations.
simply you can just add first() method to get just one record and get it's permissions, try this:
$user_permissions = User::where('id', '=', $userid)->first()->permissions;
There's no need to use get() method, this will get all the user permissions directely
Do this -
$user_permissions = User::find($userid)->permissions()->get();

Laravel - makeVisible doesn't make hidden attribute visible

I have the following code:
$model = new coretable;
log::info($model->all());
$model = $model->makeVisible('id_coretable');
log::info($model->all());
In my lumen log, I get the following result:
[2020-02-26 10:14:19] local.INFO: [{"Internal_key":"TESTKEY_1"},{"Internal_key":"TESTKEY_2"},{"Internal_key":"TESTKEY_3"},{"Internal_key":"TESTKEY_4"},{"Internal_key":"TESTKEY_5"}]
[2020-02-26 10:14:19] local.INFO: [{"Internal_key":"TESTKEY_1"},{"Internal_key":"TESTKEY_2"},{"Internal_key":"TESTKEY_3"},{"Internal_key":"TESTKEY_4"},{"Internal_key":"TESTKEY_5"}]
I would expect the "id_coretable" attribute to be present in the second output from log::info(), but it isnt.
Why is that?
Here is the model of coretable:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class CoreTable extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'coretable';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'Internal_key'
];
protected $hidden = [
'id_coretable',
'created_at',
'updated_at'
];
protected $primaryKey = 'id_coretable';
/**
* Many-To-Many relationship with User-Model.
*/
public function extensiontable_itc()
{
return $this->hasOne('App\extensiontable_itc', 'coretable_id');
}
public function extensiontable_sysops()
{
return $this->hasOne('App\extensiontable_sysops', 'coretable_id');
}
public function inaccessibletable()
{
return $this->hasOne('App\inaccessibletable', 'coretable_id');
}
}
I have no clue why makeVisible() doesnt have any effect on the effect.
The initial model you created does not have any influence on the models received from the all() function. This is a collection of new models with the initial $hidden array.
To change what values are shown, you will have to call makeVisible on the collection you receive:
$model = new coretable;
log::info($model->all());
log::info($model->all()->makeVisible('id_coretable'));
It is also recommended to call the query functions staticaly, this way you don't need to create an initial model:
log::info(coretable::all()->makeVisible('id_coretable'));

I want to select my balance "column" From user table laravel

I'm a beginner in laravel framework,I am in the course of developing an API,and I want to select from users table balance of user when I get her Id in api So I do what I found in documentations in my contoller and i use postman to test my work but always I get a error
this is my controller:
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
class MyBalanceController extends Controller
{
public function index(Request $request)
{
# code...
// $Ads = ads::all();
// return $this->sendResponse($Ads->toArray(), 'Ads read succesfully');
// This is the name of the column you wish to search
$input = $request->all();
$validator = Validator::make($input, [
'user_id'=> 'required'
] );
$Cards = User::where('user_id','=', $request->user_id)->pluck('balance')->toArray();
//$user = Auth::user();
// $Cards = DB::select('select balance from users where id = :id', ['id' => 1]);
return response()->json(['Cards'=>$Cards]);
}
}
this is my modal :
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password','username','lastname','tel','adress','balance'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
At first you can go to your .env file and set APP_DEBUG to true so you can see your exceptions when developing your app.
Regarding your problem try
$balance = User::findOrFail($request->user_id)->balance;
return response()->json($balance);
If no user was found with that id then a 404 HTTP error will be thrown

Laravel eloquent relationship not giving me what i want

im trying to figure out eloquent and having a hard time understand it, even tho ive tried to read up on it.
I have two tables: fs_festivals, and fs_bands.
fs_festivals: id, name
fs_bands: id, festival_id, name
So, one festival can have many bands, and one band belongs to a festival.
Band-model (Band.php)
class Band extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $fillable = array(
'festival_id','name','note','bandak', 'bandakinfo','created_by','updated_by'
);
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'fs_bands';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
public function festival() {
return $this->belongsTo('Festival');
}
}
Festival-model (Festival.php):
class Festival extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $fillable = array(
'name','year','info','slug', 'image','created_by','updated_by'
);
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'fs_festivals';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
public function bands() {
return $this->hasMany('Band');
}
}
In my controller:
public function festivalHome() {
$bands = Band::all();
return View::make('fis.festivalhome')->with('bands',$bands);
}
And in my view:
Bands:
#foreach($bands as $band)
{{ $band->name }}
#endforeach
This lists all bands in the fs_bands table. I only want to list those who are set with the festival_id of the current festival im working on (say festival_id='2'). How should i go about this?
Ive tried this (seeing what others have done),
#foreach($festival->$bands as $band)
But it gives me an error of
Undefined variable: festival
What am I doing wrong? Also I wonder, should I do something else instead of $bands = Band:all(); to list them by festival_id? That would be an option but something tells me that this should be done automatically with eloquent.
Controller:
public function festivalHome($id) {
//$bands = Band::all();
$festival = Festival::with('bands')->whereId($id)->first(); //it will load festival with all his bands
return View::make('fis.festivalhome')->with('festival',$festival);
// or you can filter bands
$bands = Band::whereHas('festival', function($query) use ($id){
$query->whereId($id);
})->get(); //there will be only bands which will be on the festival
}
And in your view:
#foreach($festival->bands as $band)
{{ $band->name }}
#endforeach
//or
#foreach($bands as $band)
{{ $band->name }}
#endforeach

Categories