The best way to operate output data models to build custom JSON? - laravel

I have some nested models with nested models.
best way to operate output data models to build custom JSON?
Now It is uncomfortable to iterate each model, add each others to separated array and after join by key.

Out of the box, you can add protected $hidden or protected $visible arrays as properties on the model class which will automatically hide or only make certain columns visible in JSON responses.
https://laravel.com/docs/5.4/eloquent-serialization#hiding-attributes-from-json
Additionally, you can use mutators to modify certain attributes when converting your models to JSON.
https://laravel.com/docs/5.4/eloquent-mutators#introduction
You can also add additional attributes not in your database to your JSON responses when converting a model to JSON.
https://laravel.com/docs/5.4/eloquent-serialization#appending-values-to-json
Example
class User extends Model {
protected $appends = ['is_admin'];
public function getIsAdminAttribute()
{
return $this->attributes['admin'] == 'yes';
}
}

Related

Laravel store data thru model

I dont know how else to label the title. Anyone have ideas go ahead and make a suggested edit.
I have a series of Models for the database in my application.
I can currently add a global scope to the model and have the model automatically add a "where" clause on my queries to the database on a key:value pair. This is working great.
class Customers extends Model
{
protected $table = 'customers';
protected static function boot() {
parent::boot();
static::addGlobalScope('companyRecordID', function (Builder $builder) {
$builder->where('companyRecordID', Auth::guard('user')->user()->companyRecordID);
});
}
}
I am having troubles trying to identify if this can be done; Id like to be able to store the "companyRecordID" from the Auth::guard('user')->user()->companyRecordID automatically when a database record is created. Similar to created_at and updated_at are created automatically without requiring code from the controller to define.
Can someone direct me to what I should be looking for. Ive spent a few hours trying to google key word pairs to find an answer with no avail.
If you are using Models to create the records you can listen for the creating event for the Model and then add any additional fields you may need. You can create a listener for the creating event on Customers:
Customers::creating(function ($customer) {
if (auth('user')->user()) {
$customer->companyRecordID = auth('user')->user()->companyRecordID;
}
});
You can throw that in a Service Provider's boot method or your Model's boot method. If you throw it in the Model's boot method you may want to adjust to using static:: instead of Customers::.
I believe you got your answer but,
On your model please use protected $fillable
protected $fillable = ['','',''];
protected $table = 'customers';
also, you can use Relationships to optimize your codes.

Join multiples fields from different tables with Laravel Model

i try return multiples fields from different tables in just one request, example
properties table
-id
-name
-address
rules table
-id
-checkin
-propertyId
i hope a response just like that
[
id=>123,
name=>Name,
address=>Main Street,
checkin:10:00
]
And i would like that this can be used by default in all futures request, all(), first(), get()
Note: I can't use relationship because I need to join two tables in just one
Simple solution set the default with on the property class to include the rule.
protected $with = ['rule'];
To fill you exact spec, add a checkin getter on the property model and use the append property to add it to the serialization.
protected $appends = ['checkin'];
public function getCheckinAttribute()
{
return $this->rule->checkin;
}
Extending the query builder
Laravel Eloquent Query Builder Default Where Condition
Applying logic for all your model queries
Or for the default scope
You could do it this was
https://laraveldaily.com/model-default-ordering-assigning-global-scope/

Laravel Eloquent Model Dynamic Stored Properties from and to a single serialized field

Using Eloquent L5.1
I'd like to not have to define a set of properties for a model. Instead having everything stored within the database as a serialized column.
In other words any property that is set to this model should before save be removed from the object and added to an array to be serialized and then saved in db to a "data" column.
In turn after retrieving the object from db the model should be hydrated with the de-serialized parameters from the data column.
I could override a good number of Illuminate\Database\Eloquent\Model methods to accomplish this and I'm willing to do so, was curious if anyone had an example of this.
An example of this might be for configuration objects that have virtually unlimited unknown values that have multiple itterations for different objects or for different users.
Put these accessors and mutators in your Model:
class YourModel extends Model
{
public function getDataAttribute($data)
{
return collect(json_decode($data,true));
}
public function setDataAttribute($data)
{
$data = (is_array($data) || is_object($data)) ? json_encode($data) : $data;
return $this->attributes['data'] = $data;
}
}
Now when you can pass data as json string, array or object
YourModel::create(['data'=>'{"working":"ok"}']);
YourModel::create(['data'=>['working'=>'ok']]);
It will work in all three cases.

Eloquent model method or attribute for calculation

I'm looking for a way to define a custom Eloquent method which only returns a calculation based on several columns in the according database table. I also tried setting it in the models attributes, but neither seem to work. Maybe I'm missing something, here's what I got so far:
<?php
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
public function difference() {
return $this->goals_f - $this->goals_a;
}
}
The error message I'm recieving is:
Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
Your error makes it sound to me like you are trying to call your method like a property" $team->difference. You would instead need to call it like: $team->difference(). If you want to get the difference as if it was a property, then you would need to define an accessor:
public function getDifferenceAttribute(){
return $this->goals_f - $this->goals_a;
}
Then you could call it like $team->difference.
You could also define a protected $appends property to your model so that the difference property is subsequently visible in it's JSON representation:
protected $appends = ['difference'];
More information: https://laravel.com/docs/5.2/eloquent-mutators#accessors-and-mutators

Adding data to an eloquent collection?

Im getting various data out of my database.
Product::with('users');
I also have toe execute a complex raw query to get back some information. This is returned as an array.
In my method I would like to get products with users and then add on the data from my raw query to this collection, but this data comes back as an array. Something like:
Product::with('users');
Product->extraData = $rawQuery;
How can I add the raw query output to my Product Collection?
By using Eloquent Facade like Product:: you will get an Eloquent Model object as a result or an Eloquent Collection object as a result, including results retrieved via the get method or accessed via a relationship.
Now, if i understand correctly, you need to add a single extraData property to Eloquent Collection model alongside with Collection items? Or you need to add extraData for each Product ?
If you need to add additional property to Eloquent Collection object, maybe it is a good idea to use a Custom Collection. Please read this section: http://laravel.com/docs/5.1/eloquent-collections#custom-collections .
<?php namespace App;
use App\CollectionWithExtraData;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function newCollection(array $models = [])
{
return new CollectionWithExtraData($models);
}
}
And maybe your CollectionWithExtraData can have let's say a
public function setExtraData() {
}
or
public $extraData = array();
If you need extraData for each Product Eloquent Model, just create a new attribute within your Eloquent Model, make it public and set your extra data when needed. Make use of setExtraData() method and $extraData property from above

Resources