I'm using Laravel 5.4. I have the methods I created in the User model. When I want to create an object from the User model and invoke my own methods, I can not get to the methods I added.
The User Model is derived from the Authenticable class at 5.4, which was derived earlier from the Model class. I think the problem is about it. What I really want to do is to set up the belong_to, has_many structure to relate the user model to the other models.
But with the User model I do not do that. What do you recommend ?
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',
];
public function getMakale()
{
return $this->hasMany(Makale::class, 'user_id', 'id');
}
}
$author = User::first();
return method_exists($author,'getMakale');
//eventually turns false
I believe you are potentially setting an accessor rather than a relationship. In this case I would think you want to name that function something like:
public function haberler()
{
return $this->hasMany(Makale::class, 'user_id', 'id');
}
or public function makales(). Prefixing your function name with get or set will have unintended consequences in Laravel.
Related
When using jenssegers/laravel-mongodb, the belongsTo relationship properly always returns null, despite, when dumping, the value appearing. How can I get the belongsTo relationship?
I have two models, a post and a user. Where the post has a belongs to relationship with user. When I use $post->user, I always get null. Despite the fact that when dumping ($post) it clearly shows the user id!
User (Using the boiler plate laravel auth, except with MongoDB auth user)
use Jenssegers\Mongodb\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
protected $collection = 'users';
/**
* 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',
];
}
Post:
use Jenssegers\Mongodb\Eloquent\Model;
class Post extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
];
public function user()
{
return $this->belongsTo(User::class);
}
}
Based on the Jessenger's readme doc, this is fairly standard and nothing special.
Post::all()->first() related values dump
#attributes
"_id" => MongoDB\BSON\ObjectId {#1601 ▶}
"user" => "602f054f6294a33233745fab"
I saved the user using this, just getting the logged in user's ID.
$post->user = auth()->user()->getAuthIdentifier();
However, getting $post->user always returns null
$post = Post::all();
dd($post->user) // null
$post->user() works and returns the relationship, with the related value being the actual user.
Other posts suggested setting the foreign and local key
Post Class
public function user()
{
return $this->belongsTo(User::class, 'user_id', '_id');
}
This doesn't work either.
Initially I saved the user as an ObjectId, but that doesn't work either.
My current idea is to just scrap the belongsTo functions entirely and just set the related IDs manually. The issue is that now I'll need to manually query for the user instead of the package doing so for me, or using Post::with('user') to autoload it.
How can I get the belongsTo relationship ID value?
PHP: 8.0.2
Laravel Framework: 8.28.1
Jessengers/MongoDB: 3.8.2
I have found a bizarre work around, add user_id to the fillable field and fill that out
use Jenssegers\Mongodb\Eloquent\Model;
class Post extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
'user_id'
];
public function user()
{
return $this->belongsTo(User::class);
}
}
EG
Controller
$post->user_id = $userID;
Then querying for the user works fine
$post = Post::all();
dd($post->user); // Gets the user, no longer null
dd($post->user_id); // This is the user id field you filled out before. Returns the user id
Why this works is beyond the realm of understanding for my puny mortal mind. Interestingly there's no need to set $post->user.
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'));
For a unit test in laravel 5.1 I am trying to test a cascading delete function of the Client model, which, with the recursive flag set, should also delete all users associated with the client.
I want to use a mock user adn test only wether the delete function on the user is called, so I wont have to use the database, and to apply the same principle to other tests in the future.
at the moment the test fails because I cannot find a way to make the client model retreive the associated user without firing a query.
I think I need to mock the hasMany relation defining function of the client, but i have not found a way.
the client model:
class Client extends Model
{
protected $table = 'clients';
protected $fillable = [];
public function casDelete($recursive = false){
if($recursive) {
$users = $this->users()->get();
foreach($users as $user) {
$user->casDelete($recursive);
}
}
$this->delete();
}
public function users(){
return $this->hasMany('App\User');
}
}
the user model:
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable, 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', 'client_id'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
public function casDelete($recursive = false){
$this->delete();
}
public function client(){
return $this->belongsTo('App\Client');
}
}
the test:
class ClientModelTest extends TestCase
{
use DatabaseTransactions;
function testCasDelete(){
$client = factory(Client::class)->create();
$user = factory(User::class)->make(['client_id' => $client->id]);
$observer = $this->getMock('user');
$observer->expects($this->once())->method('casDelete');
$client->casDelete(true);
}
}
When you are using DatabaseTransactions, this mean you want to persist the data in the database. And when you are using create() from the factory still you are using the database, so either you should not use the database at all or if you want you to use the database then you can simply solve the problem. but what I can suggest is this solution, which I'm not using the database init.
$user = \Mockery::mock();
$user->shouldReceive('casDelete')->andReturnNull();
$queryMock = \Mockery::mock();
$queryMock->shouldReceive('get')->andReturn([$user]);
$clientMock = \Mockery::mock(Client::class)->makePartial();
$clientMock->shouldReceive('users')->andreturn($queryMock);
$clientMock->casDelete(true);
This way you can be sure that you have called casDelete on each user model.
this is a very simple test case, you can extend it in the way you like base on what you want to achieve.
I am novice in laravel, therefor my question may be odd to someone. Well, my question is how can I write a entity in Laravel Model class which will not be created any field in database after my migration. For example
class JobseekerModel extends Model
{
use SoftDeletes;
protected $table='dbl_jobseekers';
protected $primaryKey='id';
protected $fillable=[
'FirstName',
'MiddleName',
'LastName',
'Dob',
'Education',
'DesireField',
'Skill',
'SpecialSkill',
'Experience',
'Location',
'HomeAddress',
'Salary',
'Comenteries',
'Resume'
];
protected $dates = ['deleted_at'];
}
This is my Model, now I want to add another property named 'PagedListSize' in my Model, however I don't like to create it as a database column. So how do I do this?
For example I am acquainted to use NotMapped property in .Net Framework, which is written like
[NotMapped]
public int PagedListSize {set; get;}
So, how do I able to do this. Is there any way to do this in laravel? i am working on Laravel 5.4
You can create custom Mutators to have that kind of custom properties wihout mapping them to database fields in Laravel.
class Tag extends Model
{
public function getFullNameAttribute()
{
return $this->first_name.' '.$this->last_name;
}
public function setFullNameAttribute($value)
{
list($this->first_name, $this->last_name) = explode(' ', $value);
}
}
and then you can use it like this after you initialize the model:
$tag->full_name = "Christos Lytras";
echo $tag->first_name; // prints "Christos"
echo $tag->last_name; // prints "Lytras"
Here is a tinker screenshot:
The best way to do this in Laravel indeed is through custom Mutators. In addition, mutators can be configured to be displayed in the json or array output dump of the model. e.g. for PagedListSize we could have:
public functionGetPagedListSizeAttribute()
{
return #some evaluation;
}
protected $appends = array('pagedListSize');
This way, pagedListSize will not only be available directly as a field but also be available whenever the model is serialized as Json or Array.
You can add protected properties to Laravel Model, it's fine as long as they do not collide with field-names. Besides, with Laravel, migration are deciding of DB structures, not models, so you do not take the risk to create fields automatically (actually, default models works with no properties out of the box).
EDIT : Example from the default package User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
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',
];
/**
* You can add some properties here
* will require getter and/or setters
* does not need to be fillable
*/
protected $someLogicalProperty;
}
The actual db structure is defined in the migration (2014_10_12_000000_create_users_table.php) :
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
As you can see, timestamps and token are not even listed in the user model. All the fillable when defined will be setable as public property on the user object ($user->name = 'Bob';, but you can also pass it as argument to the create()/save() inherited methods). Entities are not directly accessed in Laravel, but there are here and can be further specified if needed.
I have a two table named users and profile . In profile table there is a column named userID.Now i want to this userID column takes value from users table's id.I have done database relationships part.But can not retrieve data with view.I have searched but i have not found any satisfying answer according my issue.
By the way i am new in Laravel.I have tried so far
User Model:
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $table ="users";
protected $fillable = [
'userName', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function userProfile(){
return $this->hasOne('App\Profile');
}
}
Profile Model:
class Profile extends Model
{
//
protected $table = "profiles";
public $fillable = ["firstName","lastName","middleName","DOB","gender","featuredProfile","email","phone","summary","profilePic"];
public function user(){
return $this->belongsTo('App\User');
}
}
And i am trying to retrieve userID with {{$profile->userID}}.I really don't know where is the problem and how to do this?
you will need to tell laravel to get the relationship model like this
$profile = Profile::find(1);
$userID = $profile->user->id;
edit:
from the docs
model is automatically assumed to have a user_id foreign key.
which in your case is userId so change your hasOne and belongsTo methods to tell laravel the name of foreign_key you are using
public function profile()
{
return $this->hasOne('App\Profile', 'userId');
}
public function user()
{
return $this->belongsTo('App\User', 'userId');
}
Please add userID to the fillable array of profiles.
Please check below sample code to do the same.
public $fillable = ["firstName","lastName","middleName","DOB","gender","featuredProfile","email","phone","summary","profilePic","userID"];