As I understand, mutators change your attribute on save function (create or update). Can I make mutator just for atrribute display to users, but leave default values on save function ?
In Eloquent Model when you do this:
public function getSomeNameAttribute($value)
{
return ucfirst($value);
}
That ^ will mutate the value for showing it later in views and it won't affect what is stored in DB table.
And also if you use a setter setSomeNameAttribute($value) you can pull the actual value from db table with:
$model->getOriginal('attribute_name'); // Laravel V. ^5.*
or
$model->getRawOriginal('attribute_name'); // Laravel V. ^8.*
Related
I have a model User with fileds like - colorhair_id, nationality_id, etc. Of course I have a relationship to other model. Problem is that I want to return nationality from User i must do that:
User::find(1)->colorhair->name
In next time I need to use
User::find(1)->nationality->name
It works but it's not look professional and it's dirty. How can I change query or something else to return object with repleace field like nationality_id to nationality with name of that. Any idea?
You can use Laravel Mutators. Put below two functions into the User model
public function getHairColorNameAttribute(){
return $this->colorhair->name
}
public function getNationalityNameAttribute(){
return $this->nationality->name
}
Then when you simply access it.
User::find(1)->hair_color_name;
The next time
User::find(1)->nationality_name;
If you want to get these values by default use $append in the model. Put the following line to the top of the User model
protected $appends = ['hair_color_name','nationality_name'];
Note: In laravel 9 mutators little bit different from the above method.
Bonus Point :
if you access values in the same scopes don't use find() method in each statement.
$user = User::find(1);
then
$user->hair_color_name;
$user->nationality_name;
How can i define create method with variables and model in laravel? Like this:
public function createMethodName($variable, $variable2)
{
\App\ModelName::create([...]);
}
You have to just insert the passed variables in the array like:
// include model at the top of your file:
use \App\Models\ModelName;
public function createMethodName($variable1, $variable2)
{
$my_stuff = ModelName::create([
‘something’ => $variable1,
‘something_else’ => $variable2,
]);
}
Also, do not forget to make some of your Model fields fillable (fields which are included in the array) in your Model, if you want to save values to the table with using create(). Check the Reference about this:
https://laravel.com/docs/8.x/eloquent#mass-assignment
Short update:
Maybe I misunderstood your question a bit since according to your new comments under your question it is getting clearer that you maybe first would like to create a Table with Schema::create() method (which is a totally different part of the fun). Reference:
https://laravel.com/docs/8.x/migrations#creating-tables
Then after you created your Table, you can create a Model using artisan like:
php artisan make:model ModelName
Reference:
https://laravel.com/docs/8.x/eloquent#defining-models
and then you can use ModelName::create() method in your Controller as I gave it above to saving your data into your Table. So you should study these steps a bit more if it is the case.
I have a flight class and this flight has a custom view field like so:
This represents a belongs to many relationship which stores website_id / flight_id and pricing as pivot data in a pivot table.
The custom view uses JS to send this data back to the controller in this format:
{"1":{"price_adult":"434","price_child":"545"},"2":{"price_adult":"323","price_child":"324"},"3":{"price_adult":"434","price_child":"43"}}
Trying to send this data with the request doesn't create the relations fields, and because I do not have a flight ID at the point of creating this within the controller I can not loop this JSON to make the relations manually.
Can anyone point out what the best course of action is or if there is support for this? I took a look at the docs but they are woefully short and patchy in terms of being much help.
EDIT:
I should have said I can probably make this work using a custom name attribute on the model for the relation, then add a set mutator to loop this data and update the prices relation but I don't want to go down this route if there is support for this I am missing out of the box in backpack.
EDIT2:
Someone asked about the relation:
$this->belongsToMany(Website::class, 'website_pricing')->withPivot('price_adult', 'price_child');
This is working fine its not a problem with the relation working its how can I get backpack to store the data as a relation when the flight has no ID yet, or how can I pass the data I posted above in such a way that the backpack crud controller can handle it?
You may need to create a flight first, if no flight id is being provided. Can you explain the database relational structure more?
Basically thought I should post what I did because no one could provide an answer to this.
So basically you have to copy the store / update functions from the parent, changing a few lines.
$this->crud->hasAccessOrFail('create');
// fallback to global request instance
if (is_null($request)) {
$request = \Request::instance();
}
// replace empty values with NULL, so that it will work with MySQL strict mode on
foreach ($request->input() as $key => $value) {
if (empty($value) && $value !== '0') {
$request->request->set($key, null);
}
}
// insert item in the db
$item = $this->crud->create($request->except(['save_action', '_token', '_method']));
$this->data['entry'] = $this->crud->entry = $item;
// show a success message
\Alert::success(trans('backpack::crud.insert_success'))->flash();
// save the redirect choice for next time
parent::setSaveAction();
return parent::performSaveAction($item->getKey());
Basically any line which references a function in the parent class using $this->method needs to be changed to parent::
This line is what I used to submit the relations JSON string passed to the controller as relations $item->prices()->sync(json_decode($request->input('prices'), true));
This is done after the line containing $item = $this->crud->create as the item id that just got stored will be available at that point.
I have a table content. So when I retrive anything from that table using laravel eloquent, I need to set a global where clause Content::where('is_playlist', 1)->get();, so that every time I retrieve data from that table, I should automatically filtered with that particular where clause.
You can create a scope function in the model to filter that out e.g:
public function scopePlaylist($query)
{
return $query->where('is_playlist', 1);
}
This means you can easily call, Content::playlist()->get() and you'll have only playlist content.
I hope this is useful?
If I use firstOrCreate then the default values are given for the model that I set up in the database. But when I use firstOrNew the values are not given and are instead given out as NULL. Is there any way to fix this aside from using firstOrCreate?
This is because firstOrNew will just create a new instance of your model when it doesn't get a result from the database. Therefore it does not get the default values from the database.
So I guess you have at least two options here. The first one would be the one you already mentioned using firstOrCreate (this is not something I would recommend because this could lead to incorrect state in your database). Another option would be to add 'Accessorson your model with which will return either the value retrieved from the database or when it'snull` it will return the default value you define.
public function getMyFieldAttribute($myField)
{
if ($myField === null) {
return 'my-default-value';
}
return $myField;
}
More info on accessors can be found in the documentation: https://laravel.com/docs/5.2/eloquent-mutators#accessors-and-mutators