Calling the function morphTo returns null - php

right now i am stuck in this not really knowing what to do (maybe is really easy, but i don't see how to do it).
I have this model of users:
<?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;
protected $table = 'tcn_user';
// Time for the relations
public function user(){
return $this->morphTo(__FUNCTION__, 'type_user', 'id_user');
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username','permision', 'first_name', 'surname', 'us_password', 'email'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'us_password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
Being the problem (I suppose) in the function user(). I call it but it returns null when doing it, the variables for the childs are there, so I really don't know what is wrong. But for doubts I have here the code for one of them so you can see it.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Teacher extends Model
{
protected $table = 'teacher';
//In first place let's do the relations of the model
public function user(){
return $this->morphOne(User::class, 'user', 'id_user');
}
public function schedule(){
return $this->hasMany(ServiceSchedule::class, 'id_teacher');
}
public function session(){
return $this->hasMany(DaySession::class, 'id_teacher');
}
}
Being the important one the function user().
If you need for information please let me know, is my first time asking here, so i really don't know if I am doing it well.
PD: Okey, sorry for the things i have forgotten to add.
This being to code about how i am calling the Teacher:
public function detail($id){
$user = User::find($id);
if(is_object($user)){
$data = array(
'code' => 200,
'status' => 'success',
'user' => $user,
'subuser' => $user->user
);
}else{
$data = array(
'code' => 404,
'status' => 'error',
'message' => 'El usuario no existe'
);
}
return response()->json($data);
}
And the relation it have, well, we have User, the parent "class" with the information all the users need to have, and after that we have the "childs" like Teacher, Student, Parent, all of then with different information.
And responding to Rwd, no, i don't have a camp in the database with the name user, is more, the table user is named tcn_user (Because user is a keyword in mysql)

Related

MorphToMany relation doesn't work properly in my test

In my laravel project I use morphToMany relation to connect costs to the orders and products of the orders.
I have this migration:
Schema::create('costables', function (Blueprint $table) {
$table->unsignedBigInteger('cost_id');
$table->morphs('costable');
$table->foreign('cost_id')
->references('id')->on('costs')
->onUpdate('cascade')
->onDelete('cascade');
});
This is the Order model, with costs() method in it:
namespace Domain\Webshop\Models;
use Domain\Customer\Models\Address;
use Domain\Customer\Models\Member;
use Domain\Product\Models\Cost;
use Domain\Webshop\Database\Factories\OrderFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
class Order extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'member_id',
'shipping_address_id',
'billing_address_id',
'status',
];
public static $rules = [
'member_id' => 'required|integer',
'shipping_address_id' => 'sometimes|integer',
'billing_address_id' => 'nullable|integer',
'status' => 'required|integer',
];
protected $casts = [
'member_id' => 'integer',
'shipping_address_id' => 'integer',
'billing_address_id' => 'integer',
];
protected $hidden = ['created_at', 'updated_at', 'deleted_at'];
/**
* Create a new factory instance for the model.
*
* #return \Illuminate\Database\Eloquent\Factories\Factory
*/
protected static function newFactory(): OrderFactory
{
return OrderFactory::new();
}
public function member(): BelongsTo
{
return $this->belongsTo(Member::class, 'member_id');
}
public function shippingAddress(): BelongsTo
{
return $this->belongsTo(Address::class, 'shipping_address_id');
}
public function costs(): MorphToMany
{
return $this->morphToMany(Cost::class, 'costable');
}
}
And this is my phpunit test, for testing costs on the Order and OrderProduct models. The $this->model is the actual model, I use this as a trait:
/** #test */
public function shouldHasCosts()
{
$item = $this->model::factory()
->hasCosts(1)
->create();
$this->assertInstanceOf(
Cost::class,
$item->first()->costs()->first(),
"It should be defined a relation called costs on $this->model"
);
}
My problem is, the test success in the Order model case, but fails at the OrderProduct. What have I forgotten, or whats wrong in my code?
I found the problem myself: in the test's setup there was a factory create for the OrderProduct, so in that case there was two rows in the database, and the shouldHasCosts() test is examine the first(), so it was wrong. I deleted the unnecessary create, and it has solved the problem.

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 class not being found in a model

I am trying to get my project to use authorization roles to restrict users to certain featuers and I am following along with a tutorial. When I make a call to a class in my user.php file I am getting an error that the class App\Role can't be found. I am not sure if it is a namespace issue but I can't get to the bottom of it. I believe it is the roles function that is giving me this issue.
<?php
namespace EliteWorker;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'address', 'phone', '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 roles() {
return $this->belongsToMany('App\Role');
}
public function hasAnyRoles($roles){
return null !== $this->roles()->whereIn('name', $roles)->first();
}
public function hasAnyRole($role){
return null !== $this->roles()->where('name', $role)->first();
}
}
You changed the namespace to EliteWorker so if the Model class RoleĀ is generated with Artisan, it'll also have that namespace
public function roles()
{
return $this->belongsToMany('EliteWorker\Role');
}
Note that you can also get the model base name by calling the class static property
public function roles()
{
return $this->belongsToMany(Role::class);
}
No need to import it if it's in the same namespace
Also note that the artisan command app:name has been removed in Laravel 6 to encourage developers to use the generic App namespace

(E_ERROR) Too few arguments to function Symfony\Component\HttpKernel\Profiler\Profile::__construct(), 0 passed

I wanted to relate a profile model to the existing user model using the relationship belongs to and hasOne and I am getting that error.
here is my Profile.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
public function user(){
return $this->belongsTo(User::class);
}
}
User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Symfony\Component\HttpKernel\Profiler\Profile;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'username', '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 profile()
{
return $this->hasOne(Profile::class);
}
}
In my terminals i can get the user through the profile but cannot get the profile using user. here is the error
$user->profile
TypeError: Too few arguments to function Symfony/Component/HttpKernel/Profiler/Profile::__construct(), 0 passed in /Users/macair13/freeCodeGram/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php on line 720 and exactly 1 expected.
To fix the issue, replace the use Symfony\Component\HttpKernel\Profiler\Profile; line on top of your User.php file with use App\Profile; instead.
This is happening as you've mistakenly included the wrong class on top of your User.php file. When Laravel is trying to load the relationship, it attempts to construct a Symfony\Component\HttpKernel\Profiler\Profile object instead of constructing your intended model.
Use like below in your user model
public function profile()
{
return $this->hasOne('App\Profile', 'foreign_key');
}
I am not sure why you have used Symfony\Component\HttpKernel\Profiler\Profile in your user model. When your relationship is building it is using that Profile and not your Profile Model. You have to use the Profile Model namespace while defining the relationship.

Laravel/Ardent - on save(), error: Relationship method must return an object of type Illuminate

I'm having some trouble getting my Laravel relationships to work out. In my application, there is a one-to-many relationship between users and ideas. (A user may have multiple ideas.) I'm using Ardent.
Here's my User model:
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
use LaravelBook\Ardent\Ardent;
class User extends Ardent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
protected $fillable = array('first_name', 'last_name', 'email', 'password');
public $validation_errors;
public $autoPurgeRedundantAttributes = true;
public $autoHashPasswordAttributes = true;
public $autoHydrateEntityFromInput = true;
public static $passwordAttributes = array('password');
public static $rules = array(
'first_name' => 'required|between:1,16',
'last_name' => 'required|between:1,16',
'email' => 'required|email|unique:users',
'password' => 'required|between:6,100'
);
public function ideas()
{
return $this->hasMany('Idea');
}
}
And here's my Idea model:
use LaravelBook\Ardent\Ardent;
class Idea extends Ardent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'ideas';
protected $fillable = array('title');
public $validation_errors;
public $autoPurgeRedundantAttributes = true;
public $autoHydrateEntityFromInput = true;
public static $rules = array(
'title' => 'required'
);
public function user()
{
return $this->belongsTo('User');
}
}
Finally, here's my controller code:
class IdeasController extends BaseController {
public function postInsert()
{
$idea = new Idea;
$idea->user()->associate(Auth::user());
if($idea->save())
{
return Response::json(array(
'success' => true,
'idea_id' => $idea->id,
'title' => $idea->title),
200
);
}
else
{
return Response::json(array(
'success' => false,
'errors' => json_encode($idea->errors)),
400
);
}
}
}
$idea->save() throws the error:
{
"error": {
"type": "LogicException",
"message": "Relationship method must return an object of type Illuminate\\Database\\Eloquent\\Relations\\Relation",
"file": "\/var\/www\/3os\/vendor\/laravel\/framework\/src\/Illuminate\/Database\/Eloquent\/Model.php",
"line": 2498
}
}
At first, I was trying to set the user_id in the Idea like so:
$idea->user_id = Auth::id();
I then changed it to:
$idea->user()->associate(Auth::user());
But the results were the same.
Any suggestions would be much appreciated.
You cannot use associate in that direction, since it can only be used on a belongsTo relationship. In your case, an idea belongs to a user and not the other way around.
I suspect there is an error when saving, as you create an idea without the required title, and you then try to get the errors by calling $idea->errors, while it should be $idea->errors().
associate will work on belognsTo relationship , in your cause what you have to use is Attaching A Related Model. See more about Attaching A Related Mode in documentation.

Categories