Laravel authorize() assigns unexpected object to response - php

I have three Eloquent models for a recipe management application where User has many cookbook, cookbook has many recipes and so on (see below).
To authorize I'm using this policy:
public function view(User $user, Recipes $recipe) {
return $user->id === $recipe->cookbook->user_id;
}
Here is the controller:
public function show($id) {
$recipe = Recipes::find($id);
$this->authorize('view', $recipe);
return $recipe;
}
Testing this works fine, however I'm getting extra information in my response.
The response somehow gets assigned an extra object cookbook. After print testing the problem seems to lie on the line $recipe->cookbook->user_id; where if removed the result came to be as expected.
Am I overlooking something?
Models for Reference
User
class User extends Authenticatable
{
use HasFactory, Notifiable, HasApiTokens;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function cookbooks() {
return $this->hasMany('App\Models\Cookbook');
}
public function recipes() {
return $this->hasManyThrough('App\Models\Recipes', 'App\Models\Cookbook');
}
}
Cookbook
class Cookbook extends Model
{
use HasFactory;
protected $guarded = ['user_id'];
protected $fillable = [
'cookbook_name',
];
protected $casts = [
'cookbook_shared_user' => 'string'
];
public function user() {
return $this->belongsTo('App\Models\User');
}
public function recipes() {
return $this->hasMany('App\Models\Recipes');
}
}
Recipe
class Recipes extends Model
{
use HasFactory;
protected $guarded = ['cookbook_id'];
protected $fillable = [
'recipe_name',
'recipe_description',
'recipe_video_url',
'recipe_image_url'
];
public function cookbook() {
return $this->belongsTo('App\Models\Cookbook');
}
}

You're loading the relationship in your policy, exactly where you said:
$recipe->cookbook
Now in your controller, you can change your return to:
return $recipe->setAppends([]);
That will remove your appends like cookbook.
If you want more control you can use API Resources (Laravel way).

Related

Relations in Laravel eloquent

I am beginner in Laravel. I use in my project Laravel 5.8.
I have this code:
Dish.php
class Dish extends Model
{
protected $quarded = ['id'];
protected $fillable = ['company_id', 'name', 'description', 'enable'];
public $timestamps = false;
public function components()
{
return $this->hasManyThrough('App\DishValues', 'App\Dish', 'id', 'dishes_id');
}
}
DishValues
class DishValues extends Model
{
protected $quarded = ['id'];
protected $fillable = ['dishes_id', 'food_ingredient_id', 'quantity'];
public $timestamps = false;
public function ingredient()
{
return $this->belongsTo('App\FoodIngredient', 'food_ingredient_id');
}
}
FoodIngredient.php
class FoodIngredient extends Model
{
use scopeActiveTrait;
public function scopeVisibleDemo($query)
{
return $query->where('available_in_demo', 1);
}
protected $quarded = ['id'];
protected $fillable = ['company_id', 'name', 'garbage', 'energy_value', 'protein', 'fat', 'available_carbohydrates', 'roughage', 'description', 'url_address', 'allergen', 'available_in_demo', 'enable'];
public $timestamps = false;
}
I get my data:
Dish::with('components')->paginate(25);
How can I get in this code values from FoodIngredient?
This is not working:
Dish::with('components, ingredient')->paginate(25);
or
Dish::with('components')->with('ingredient')->paginate(25);
Given you have multiple relationships, you use :with() with an array of values, not a comma separated string.
This example comes from the docs on "Eager Loading Multiple Relationships" and I've re-named the models based on your example
App\Dish::with(['components', 'ingredient'])->get();
There is also a good blog post that explores the eager/lazy loading of related models in this way.

laravel belongsTo on User Model not working

Following are my relations in laravel , I am unable to access company using User's Object, but i am getting null when i try to access it, please see my code below to get the picture
following are my models
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Zizaco\Entrust\Traits\EntrustUserTrait;
use Session;
use Illuminate\Support\Facades\DB;
class User extends Authenticatable
{
use Notifiable;
use EntrustUserTrait;
protected $table = 'tbl_users';
protected $primaryKey = 'id';
protected $guarded = ['id'];
const API = 'api';
const WEB = 'web';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'last_login', 'Address', 'Age', 'DateOfBirth', 'created_by', 'deleted_by'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'is_admin' => 'boolean',
];
public function isAdmin()
{
return $this->is_admin;
}
static function GetUserNamebyID($id)
{
$name = User::select("name")->where(["id" => $id])->pluck('name');
if (isset($name[0])) {
return $name[0];
} else {
return '';
}
}
public function loginlogout()
{
$this->hasMany("App\Models\LoginLogoutLogs", 'userID');
}
public function company()
{
$this->hasMany("App\Models\Company", "company_id");
}
}
And following is my companies Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use DB;
use App\Models\CarePlanData;
use Session;
class Company extends Model
{
protected $table = 'companies';
protected $primaryKey = 'id';
protected $guarded = ['id'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'phone_no', 'address', 'password', 'description', 'city', 'company_logo', 'country', 'email'
];
static public function fetchAllActiveCompanies()
{
return DB::table("companies")->where(['is_active' => 1])->pluck('name', 'id');
}
// change company to hasmany
public function users()
{
return $this->hasmany('App\Models\User');
}
}
and this is how i am trying to access the Company , but i am getting null.
public function fetchCompany(){
$User = User::find($user->id);
dd($User->company());
}
First of all if a user belongs to 1 company then it should be:
public function company()
{
$this->belongsTo("App\Models\Company", "company_id");
}
then fetchCompany() should be
public function fetchCompany(){
$User = User::with('company')->find($user->id);
dd($User->company);
}
You need to use with to load the relations. You pass the name of the function which defines the relation in your User model to with like this with('function_name').
Your actual question is:
You have belongTo Relation between User and Company but when you trying to access the Company via user object, you get null
In your User.php Model put the following function but if you already have then leave it:
public function company()
{
$this->belongsTo("App\Models\Company", "company_id");
}
Then
Replace this function:
public function fetchCompany(){
$User = User::find($user->id);
dd($User->company());
}
To is one:
public function fetchCompany(){
$User = User::find($user->id);
if($User){
dd($User->company()->get());
}
}
or to this one:
public function fetchCompany(){
$User = User::find($user->id);
if($User){
dd($User->company);
}
}
actually if your company_id field is on user model, then your relation should be
public function company()
{
$this->belongsTo("App\Models\Company", "company_id");
}
unless a user can have many companies ?

Laravel Relationship's

I have a little difficulty in Laravel Relationships. I made all the relationships between CourseModel, CourseTimeModel and CourseInstructorModel. But the problem is that i want to get instructor_name from instructor table. Is it possible that i can get the instructor_name from instructor table using relationship?
CourseModel.php
class CourseModel extends Model {
protected $table = 'course';
protected $fillable = [
'course_name',
'fee',
'duration',
'description',
'created_at',
'updated_at',
];
public function courseInstructor() {
return $this->hasMany('App\CourseInstructorModel');
}
public function courseTime() {
return $this->hasMany('App\CourseTimeModel');
}
public function getCourses() {
$courses = $this->with(['courseTime', 'courseInstructor'])->paginate(10);
return $courses;
}
}
CourseInstructorModel.php
class CourseInstructorModel extends Model
{
protected $table = 'course_instructor';
protected $fillable = [
'course_id',
'instructor_id',
'created_at',
'updated_at',
];
public function course()
{
return $this->belongsTo('App\CourseModel');
}
}
CourseTimeModel.php
class CourseTimeModel extends Model
{
protected $table = 'course_time';
protected $fillable = [
'course_time',
'course_id',
'created_at',
'updated_at',
];
public function course()
{
return $this->belongsTo('App\CourseModel');
}
}
I solved my problem using Many to Many Relationship between CourseModel and InstructorModel.
Here is my code that i write in CourseModel.php
public function instructor() {
return $this->belongsToMany('App\Instructor');
}
You can get instructor_name in this way :
$courseModel = CourseModel::find(1);
$instructor_name = $courseModel->courseInstructor->instructor_name;

Laravel 5 Call to undefined method Illuminate\Database\Eloquent\Collection::tags();

I have two Models that use a many to many relationship.
class Tag extends Model
{
protected $table= 'tags';
protected $primaryKey = 'id';
protected $fillable = [
'name'
];
public function members()
{
return $this->belongsToMany('App\Data','data_tag','tag_id','data_id')
->withTimestamps();
}
}
and a Data Model..
class Data extends Model
{
protected $table= 'dbaccess';
protected $primaryKey = 'id';
protected $fillable = [
'username','password','email','added_at','user_id'
];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany('App\Tag','data_tag','data_id','tag_id')
->withTimestamps();
}
}
where the data_tag is linking a table.
when I call the function
$mani = App\Data::find(2);
and then
$mani->tags()->attach(3);
I get the following error.
[Symfony\Component\Debug\Exception\FatalErrorException]
Call to undefined method Illuminate\Database\Eloquent\Collection::tags()
Can anyone help me with this ?
dd($mani) reply this
It seems you are getting a collection instead of a model
Try to get the first element of the collection with:
$mani = App\Data::find(2)->first();

Laravel ORM relationship method 'BelongsToMany' throwing error

Summary
I am receiving the following error when trying to call the relationship:
Object of class Illuminate\Database\Eloquent\Relations\BelongsToMany
could not be converted to string
My setup is very basic, and consists of two models, User and Role.
User Model [User.php]
<?php
use Illuminate\Auth\UserInterface;
class User extends Eloquent implements UserInterface {
protected $table = 'users';
protected $hidden = array('password');
protected $fillable = array('id', 'username', 'password');
public function getAuthIdentifier() {
return $this->getKey();
}
public function getAuthPassword() {
return $this->password;
}
}
Role Model [Role.php]
<?php
class Role extends Eloquent {
protected $table = "roles";
protected $fillable = array(
'id',
'code',
'name'
);
public function foo() {
return $this->belongsToMany('User', 'map_role_user', 'role_id', 'user_id');
}
}
And finally I'm calling the method foo in the routes file, example:
Route::get('role', function() {
return Role::find(1)->foo();
});
From
https://laravel.com/docs/5.3/eloquent-relationships or https://laravel.com/docs/4.2/eloquent#relationships
If a collection is cast to a string, it will be returned as JSON:
<?php
$roles = (string) User::find(1)->roles;
If you dont want to add further constraints to the query then you have to use dynamic properties concept. So,
$user = App\User::find(1);
foreach ($user->posts as $post) {
//
}
If you want to add more constraints then do this
App\User::find(1)->posts()->where('title', 'LIKE', '%Best%')->get()

Categories