Why is my Laravel Eloquent accessor not showing up in the response? - laravel

I have a Model Review that has a unix timestamp as 1 of it's attributes (table columns).
I use 2 accessors inside this model:
public function getReviewDateAttribute($value)
{
return strftime('%A %e %B %Y', $value);
}
public function getReviewDateIsoAttribute()
{
return Carbon::createFromTimestamp($this->review_date)->toDateTimeString();
}
getReviewDateAttribute works as expected and shows up in the collection of models when I write a query.
However getReviewDateIsoAttribute does not. What could be the reason for this?
A subquestion: If I use the same attribute in both functions, how can I use the original format as input value?

You should be adding it to the $appends array. It isn't spinning through all available methods looking for getXXXXXAttribute. The other one is used because it is an accessor for an actual attribute, this one is not an actual attribute.
class YourModel ....
{
protected $appends = ['review_date_iso'];
...
}
Laravel 5.5 Docs - Eloquent - Serialization - Appending Values to JSON

This is probably because ReviewDateIso is not an actual column and therefore will not show up in the model collections...you can access it directly by calling the method directly
$model->getReviewDateIsoAttribute()
According to the docs accessors a ways of changing the value of a column before it is returned to the method that queried it.
If you want it to show up when you call the collection as Json append it to the output with
protected $appends = ['name_of_attribute'];

I tried queries in tinker and with dd method. So I got confused since I cant view my new accessor in the attribute list.
I thought I missed something. Then later I noticed appended attributes are shown separately when we dd the query result than the usual attribute JSON.
I lost time thinking my accessor is not working. Its just I`m not checking in the right way or right place. So I``m attaching the following image, if anyone gets stuck on accessors like me, this might help them.

In fact it depends on what you are trying to achieve. If you are going to display anything in Blade for example, you can use whenever you want $object->review_date_iso to get this attribute value.
However if you are returning Json responses (for example API), you need to tell Eloquent model to append extra fields to your model when transforming to JSON format.
You probably have review_date attribute in your model (this is the column in database I suppose) but you don't have review_date_iso in your table in database, so in your model you need to use:
protected $appends = ['review_date_iso'];
but you don't have to include here review_date because it's already in your table in database and your accessor will be automatically fired.

Related

How to use relationship data outside of relationship field in Laravel Nova?

I am trying to figure out how to do something seemingly simple with Laravel Nova, but I can't figure this out.
What I want to do is reference relationship data in a text field. I see in Nova, and understand how to reference a relationship via the HasOne, HasMany ... facades. But what I want to do is get relationship data like this:
Text::make('State', $this->state->name)
This doesn't work, and something I noticed when trying to debug is that each function in a Nova resource seems to run multiple times. Here is the logging I added:
public function fields(Request $request) {
logger($this->state->name)
}
When I do this, there are 3 logging instances, the first 2 containing the state name, and the third not. I think that may have something to do with it not working, but don't know what might be causing this.
Thank you in advance for help!
There's a simple way to get relationship data into a Nova Text field, just use a closure:
Text::make('State', function() {
return $this->state->name;
})
As for the multiple calls to the fields function, the answer has to do with the question: Do you have another Resource in your Nova folder that is related to the Resource we are discussing? If so, that is why -- it needs to call fields to display it properly. You can examine the following query string parameters to get more insight: viaResource, viaResourceId, and viaRelationship.

Laravel - Model binding not working when I use accessors

I want to populate my select box from the Laravel IoC Container.
App\Http\Utilities\BillingHelper.php
views/billing/create.blade.php
views/billing/edit.blade.php
Create the table:
Now, instead of the value, i want to display some flags and currency symbols.
Should i use mutators?
Problem
If i use mutators, when i open the edit page, i see always the first value selected, from the BillingHelper, instead of the choosen one.
Any help? Thanks.
I know it should be a comment, but I have no reputation.
What if, on you edit page, you replace null on Form::select with $client->language and $client->currency.
I know that you area binding the values with Form::Model. But worth a try.
When you use mutators the matching won't occur anymore. You'll have to use a matching static array according to the values you'll return. (the flags)
You can make it work if you make a mutator for saving the data also and simplify again to the ['it', 'en', 'lv'], otherwise your saved data will differ and the initial mutator won't work the second time. You can still make a one-time-only test.
This is why:
Your form binding is using $bill->language to retrieve the actual stored data, and compare it with the values in your $bill::lang static array. If no match found, than the first value will be always selected.
Can you provide the the currency and language fields definition in the migration for the bill?
Also retrive your values from your bills DB and paste them here for language and currency. They must be in the defined static sets.
Laravel has a way of skipping the accessor/mutator by using
$model->getOriginal('data_field').
The "getOriginal()" gets the model's original attribute values.

Proper Use of Accessors in Laravel

I am new to Laravel and am building a simple CRUD app to learn more about the framework. I am curious about the proper use of accessors.
I thought accessors would be great for formatting a model's properties for display in a view, much like a filter in Angular. Currently I have a few accessors set to convert char(1) fields to full values in the view, like "c" to cash or "f" to financed. Is this the intended (or an acceptable) use of accessors? If so, what is a good way to prevent accessors from formatting properties that are binded to a form, for instance, in the edit route.
For example, I am storing a monetary amount in the db as a decimal but formatting it with characters ($150,00) for display in the show route. How can I prevent the accessor from altering the value when populating the edit form? (Validation will fail as the input is limited to numeric values).
http://laravel.com/docs/4.2/eloquent#accessors-and-mutators
http://laravel.com/docs/4.2/html#form-model-binding
Everything depends on your needs. The key is that you don't need to create accessors to actual columns/properties. For example let's assuyme in DB you have price field.
Using the following code:
$model = Model::find(1);
echo $model->price;
You can display row price just to display data from database.
But you can also create accessor for unexisting property:
public function getCurPriceAttribute($value)
{
return '$ '.($this->price * 1.08); // for example adding VAT tax + displaying currency
}
now you can use:
$model = Model::find(1);
echo $model->price;
echo $model->cur_price;
Now if you want to put data into form you will use $model->price to allow user to change it without currency and in other places where you want to display product value with currency you will use $model->cur_price

Laravel 4 - Unable to override getDateFormat()

Can anyone tell me why I get an error saying Trailing Data, whenever I Override this method in my model and alter it in any way?
protected function getDateFormat() {
return 'Y-m-d H:i:s';
}
Any change to the above code breaks my page.
I am following the official documentation here: http://laravel.com/docs/eloquent#timestamps
getDateFormat is purely meant for how date/time fields are stored in the database. You're not meant to modify it for display purposes.
EDIT: Here are some suggestions for custom formatting of your datetime fields if you don't want to call format() everywhere.
Make a presenter class
Add accessor methods like getDateYearAttribute and getDateMonthAttribute
Use Carbon's setToStringFormat method as documented here
Add a HTML macro for formatting dates
Add a blade extension for the same thing
This may not be the same but I would get this error when working with timestamps and carbon but using strtotime() on the data i was passing resolved my issue, may help you.

Accessing model from controller?

I want to get data from my database and then in my model I wish to do some php stuff to the data before passing it to my view.
Normally I would do this to get all of my data:
->with('content', Content::all());
But I have set up a function in my model called test:
public function test(){
//get and modify data here
}
How can I access this using:
->with
from my controller?
Is this the one you are looking for?
Model:
public static function foo($bar) {
return static::where('foo', '=', 'bar');
}
Controller:
->with('content', Foo::foo("test"));
What you are trying to do isn't really explained correctly but I'll try to answer anyway.
From what I understand, you want to do some data transformation in the model before it is used. But your comment in the test() function say that you want to GET and modify data.
In laravel, functions for getting and modifying data are separated:
For getting data, you can define a query scope ( http://four.laravel.com/docs/eloquent#query-scopes ). A query scope is usually a shortand for adding some parameters to an existing query.
For modifying data before it is read from the model, or before assinging it to the model, Eloquent provide a system called mutators (http://four.laravel.com/docs/eloquent#accessors-and-mutators ). A mutator is a method called when reading or assiging value to a field. It is usualy to convert php type to a database type (for example array to json on save, then json to array on read). A mutator can be used to populate some extra value or do some extra checks to the value.
I hope I've helped you a bit. If you don't find it is a correct answer, please clarify your question so I can help you a little more.

Resources