Laravel Mutator to add predefined values into database - laravel

I'm new into Laravel and I'm trying to store the user's company id on a column of the products table each time a user creates a new product. The company's id it's retrieved from the user's session. I'm trying it with Laravel's Mutator:
public function setFirstNameAttribute($value) {
$this->attributes['company_id'] = session()->get('company.id');
}
But each time I create a new Product the company id stored it's null. Seems like the function it's never executing. Is there any other resource to perform actions like this?

You must use model events - this will be executed on model creation before saving. Or you can use another events depends on you logic - see docs.
class YourModel extends Model
{
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::creating(function (YourModel $model) {
$model->company_id = session()->get('company.id');
});
}
}
Mutators only works when you change mutating field directly:
$model->first_name = 'new_name'
And with your code - you will lost "new_name".

I noticed that the function name is incorrect, since the accessors use "studly" cased name of the column you wish to access, it may be as simple as to change
public function setFirstNameAttribute($value)
to
public function setCompanyIdAttribute($value)

Related

Clarification with eager loading/mutators/accessors for laravel

I'm making a laravel app for work and I need to load all users with their attached role without any nesting of the roles. I used this tutorial for roles: https://medium.com/#ezp127/laravel-5-4-native-user-authentication-role-authorization-3dbae4049c8a . If I use public $with = ['roles']; on my User model it returns the entire role object within the user object and I need it to just return role:'role_name';
/**
* set up eloquent between roles/user
*
* #return \Illuminate\Database\Eloquent\Relations\belongsToMany
*/
public function roles()
{
return $this->belongsToMany(Role::class);
}
Above is in my User model and below is in my Role model to define the relationships.
/**
* provides a many-to-many relationship to User model
*
* #return User::class
*/
public function users()
{
return $this->belongsToMany(User::class);
}
I thought that by adding this to the User model:
protected $appends = ['role_name'];
public function getRoleNameAttribute()
{
return $this->attribute['name'];
}
it would return everything but all it does is create a role_name: 'user_name'; On the model. So I guess I realize I'm accessing just the Users table and not the Roles table in the DB, but again not really sure what to do. Any help would be greatly appreciated.
If for the purpose of convenience you need to access the role name directly from the model you should refer to the actual relationship data:
protected $appends = ['role_name'];
public function getRoleNameAttribute()
{
return $this->roles->pluck('name');
}
This should append the array of role names to your user model. It will be an array because roles seem to have a many-to-many relationship with the User model.
The issue is you're returning $this->attributes['name'] in the getRoleNameAttribute. You want the role names, so instead you'd do something like this:
If you want an array with the names:
return $this->roles()->pluck('name')
If you want the names as a string:
return array_implode(", ", $this->roles()->pluck('name')->toArray());

How can I access the instantiated user within the user model itself (without creating another relationship)?

I want to create a custom method by accessing the instantiated users id, like:
public function ware(){
return File::where('owner', $this->user->id);
}
same could be a accessor or scope. and then being able to call
$user = User::find(5);
$user->ware()->all()...
You would define relationships using PK/FK as outlined in the Laravel documentation here and then could access them via relationship like:
Make sure your file table has a column for user_id which would allow the relationship to function as outlined above.
Add to User Model:
/**
* Get the files for the user.
*/
public function files()
{
return $this->hasMany('App\File');
}
Add to File Model:
/**
* Get the user for the file.
*/
public function user()
{
return $this->hasOne('App\User');
}
You could then access it like User::find(5)->files (to get user files) or File::find(5)->user to return the file user.

Laravel middleware return data for user_id

Is it possible to create a middleware in laravel 5.2x to return data in controller only for specific user_id instead typing everywhere stuff like
->where('access_gallery','=',true)
For example I have a gallery on my webpage where users can upload photos crop them etc.
I check by middleware if their payment_datetime < current datatime, if true next step.
In next step i want to return/edit/delete/crop/..., only photos for specific user, to do that normally i would have to create a query with #up code, because we I dont want user_1 to edit user_2 page.
It's a little annoying to copy it everywhere, and also if i create an Admin account to access everything i have to create next query for every each function to return all data for them.
If it's not possible to create function like that in middleware, is it possible in controller?
I think what you're looking for is a scope - or even a global scope.
https://laravel.com/docs/5.2/eloquent#global-scopes
Create a Scopes directory under App. Create a file like so:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class UserGallery implements Scope
{
/**
* Query if user has gallery
*
* #return void
*/
public function apply(Builder $builder, Model $model)
{
return $builder->where('access_gallery','=',true);
}
}
Then in your model (that you want this scope applied too), add a boot function to the beginning of your model class:
use App\Scopes\UserGallery;
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::addGlobalScope(new UserGallery);
}
You could even put the scope in a trait class...in my opinion, would look cleaner and easier to inject into your models.
PS: Limit the amount of logic you put in a middleware class. Consider middleware as a door to get into your main set of logic. That door is either open or locked for the user to access.

How to use a protected property in an Eloquent model without Laravel trying to save it to the database

In one of my models, I have an attribute named "slug". When the slug is changed, I need to record the original slug before updating it to the new one, so my model has a protected property "originalSlug". Before saving the model, I do something like this in my model:
protected $originalSlug;
public function customSave($newSlug){
$this->originalSlug = $this->slug;
$this->slug = $newSlug;
return $this->save();
}
Then I have an event that does other tasks using that originalSlug after a successful save.
The problem is Laravel is trying to save the originalSlug to the database though it isn't actually an attribute and doesn't have a database column. So it fails with the "Column not found" error.
What could I do to get Laravel to ignore that originalSlug property, or is there a better way I should be doing this?
If you want Eloquent to ignore a property, it needs to be accessible to set, otherwise __set will be called and Eloquent will treat it as an attribute.
You can alternatively use mutator for this.
So here's what you need:
public $originalSlug;
public function customSave($newSlug){
$this->originalSlug = $this->slug;
$this->slug = $newSlug;
return $this->save();
}
or:
protected $originalSlug;
public function customSave($newSlug){
$this->originalSlug = $this->slug;
$this->slug = $newSlug;
return $this->save();
}
public function setOriginalSlugAttribute($value)
{
$this->originalSlug = $value;
}
Then Eloquent will not set an originalSlug attribute , so it won't be saved to the db.
You can do that with events, like suggested in the comments, and I would suggest this way too.

Adding attributes to a model

I have four columns in my users database and a config variable. In my view I need to show the sum of those columns divided by the variable - simple enough to calculate but ideally I'd like the result of that to be stored as an attribute on the model.
Basically to avoid doing this:
$user = Auth::user();
$user->setPercent();
dd($user->percent);
What I'd like to do is have that percent attribute set automatically but I'm not sure where to do that. I've tried overriding the model constructor but that the data for the user hasn't been retrieved at that point.
Thanks
To create you just have to add a method like this to your user model:
class User extends BaseModel implements UserInterface, RemindableInterface {
public function getPercentAttribute($value)
{
/// do your magic
return $yourMagicValue
}
}
To use it the way you said you need:
$user->percent
And if you want to have this attribute when the object is created do:
public function __construct($attributes = array())
{
if (!isset($this->percent))
$this->percent = $this->setPercent();
parent::__construct($attributes);
}
This works for me

Resources