custom serialization data on laravel - php

this is my first post. I have a problem with my Laravel application.
I need to modify the serialization of the data for my endpoint to get the data of a specific bike.
The endpoint return this:
{"bike":{"id":32,
"unlock_code":2342,
"rack": {"id":3,
"available_stands":10,
"latitude":"46.754",
"longitude":"8.5732",
"available_bikes":10
},
"bike_state":{"description":"Available"}
}
}
but i want to have this:
{"bike":{"id":32,
"unlock_code":2342,
"rack":{"id":3,
"available_stands":10,
"latitude":"46.754",
"longitude":"8.5732",
"available_bikes":10
},
"bike_state":{"Available"}
}
}
the field name ('description') must be hidden. It's the first time i use laravel and i don't know if it's possible to do this.
This is the model
class BikeState extends Model
{
protected $hidden = ['id'];
public function bikes()
{
return $this->hasMany('App\Bike');
}
}
this is the repository with the method to retrieve the data:
class BikeRepository
{
public function findBikeById($id)
{
return Bike::with('rack','bikeState')->findOrFail($id);
}
}
and this is the controller
class BikeController extends Controller
{
private $bikeRepository;
public function __construct(BikeRepository $bikeRepository)
{
$this->bikeRepository = $bikeRepository;
}
public function getBike($id)
{
return response() ->json(['bike' => $this -> bikeRepository ->
findBikeByid($id)], 200);
}
}
Thank you

Create an accessor on your Bike model like this:
public function getBikeStateAttribute($value)
{
return json_encode($this->attributes['description']);
}
Then add accessor to Bike model's array like this:
protected $appends = ['bike_state'];

Related

Laravel - Model Eloquent without relationships

i trying to load all rows from a model without the relationship.
The attributes $with it not event set on my Event model but when i do
$events = Event::all();
all my relationship are loaded, and i can see all the query with the dbquerylog.
i don't understand why theses relationship are loaded,
Please help me !
Thanks you.
I'm using Laravel 8.
here's an example.
class Event extends Model {
public function items() {
return $this->hasMany(Item::class);
}
public function items2() {
return $this->hasMany(Item2::class);
}
public function items3() {
return $this->hasMany(Item3::class);
}
public function items4() {
return $this->hasOne(Item4::class);
}
}
$events = Event::all();
If you have a single instance of a model object, you can do:
$obj->withoutRelations();
As laravel documentations says you can use without: https://laravel.com/docs/8.x/eloquent-relationships
Model
protected $with = ['item1','item2','item3','item4'];
Controller
$events = Event::without(['item1','item2','item3','item4'])->get();
I met this problem one day, and it turned out that I was using relation in scope method. Because of this relation values were added to response.
Check out this example:
class Event extends Model {
public function items() {
return $this->hasMany(Item::class);
}
[...]
public function scopeItemsGreen() {
return $this->items->every(function ($item) {
return $item->color == 'green';
});
}

How to get a single element with a model with relations Laravel

I have three models Driver Worker and Group. The models are like this:
class Group extends Model
{
.....
public function driver()
{
return $this->belongsTo('App\Driver');
}
public function worker()
{
return $this->belongsTo('App\Worker');
}
}
Drivers
class Driver extends Model
{
public function groups()
{
return $this->hasMany('App\Group');
}
}
Worker
class Workerextends Model
{
public function groups()
{
return $this->hasMany('App\Group');
}
}
But how can I get a single element with the relationships that I have defined in my models. I have this in my controller but I only get the first element of the table. I need to get the element with the id and also the relations.
public function show(Group $group)
{
return $group->with(['worker','driver'])->first();
}
try this
public function show(Group $group,$id){
$group = $group->where('id',$id)->with(['worker','driver'])->first();
return $group
}
in your Route
Route::get('/group/show/{id}', 'GroupController#show')->name('group.show');

How to apply relationship with two id's in laravel

So I have a model called data_storage and another model entity_states
I have to fetch the record from data_storage with entity_states where entity_state has data_storage_id and state_id.
How can I use eloquent to achieve this ?.
Or Ill have to use Query builder and use innerJoin?
Update1
My Actual Query
$this->values['new_leads'] = $data_storages->with('actions','states','sla')->where('wf_id',$wfid)->get();
My data_storage modal
class data_storages extends Model
{
//
protected $fillable = ['layout_id','member_id','company_id','team_id','data','status','wf_id'];
function actions()
{
return $this->hasMany('App\Models\ActionDataMaps', 'data_id', 'id' );
}
function states()
{
return $this->hasOne('App\Models\workflow_states','id','status');
}
function sla()
{
//Here I have to get those row from entity_states model where , data_storage_id and state_id
}
}
Thanks
Here's the more reasonable way to do it:
class DataStorage extends Model {
public states() {
return $this->belongsToMany(State::class,"entity_states");
}
}
class State extends Model {
public storages() {
return $this->belongsToMany(DataStorage::class,"entity_states");
}
}
Then you can eager-load related models via e.g.:
$storage = DataStorage::with("states")->first();
$storage->states->first()->column_in_related_state;
Or via the state:
$state = State::with("storages")->first();
$state->storages->first()->column_in_related_storage;
If there are additional columns in the pivot table entity_states then you can refer to them in the relationship as e.g.:
public states() {
return $this->belongsToMany(State::class)->withPivot("pivot_column");
}
In your model data_storage you can define a property / method entity_states to get them:
class data_storage extends Model
{
public function entity_states()
{
return $this->hasMany('App\entity_states','data_storage_id')->where('state_id ','=',$this->table());
}
}
Then you can access them in an instance by
$entityStatesOfDataStorage = $yourDataStorageInstance->entity_states;
See this link:
https://laravel.com/docs/5.3/eloquent-relationships
for Query Builder you may use this:
DB::table('data_storage')
->join('entity_states','data_storage.data_storage_id','=','entity_states.state_id')
->get();
For your reference Laravel Query Builder

Laravel Paginate with Dynamic Method

I am building a REST API on Laravel. I currently have a Model ( Project ) which has 2 Dynamic Methods ( liveindexes and totalindexes ).
I want the API (/projects) to return the values of both those methods as well.
Project Controller
public function index()
{
return Project::paginate();
}
Project Model
class Project extends Model
{
protected $table = 'projects';
protected $fillable = [
'target'
];
public function indexes()
{
return $this->hasMany('App\indexes','project_id','id');
}
public function totalindexes()
{
return $this->indexes()->count();
}
public function liveindexes()
{
return $this->indexes()->whereNotNull('anchor')->count();
}
}
To include these items with your Project model, add them to your model's attributes, attributes are appended when to model is transformed into an array, or it's JSON form.
Add this to your code:
protected $appends = ['live_indexes', 'total_indexes'];
public function getLiveIndexesAttribute() {
return $this->attributes['live_indexes'] = $this->liveIndexes();
}
public function getTotalIndexes() {
return $this->attributes['total_indexes'] = $this->totalindexes();
}

Delete hasManyThrough relationship rows using Laravel's Eloquent

I have three models, Advertiser, PtcAd, and PtcCampaign. When deleting a Advertiser I want to delete all related PtcAds and PtcCampaigns. The Advertiser has many PtcCampaigns through PtcAds.
Advertiser Model
use SoftDeletes;
protected $dates = ['deleted_at'];
public function ptcAds()
{
return $this->hasMany('App\PtcAd');
}
public function ptcCampaigns()
{
return $this->hasManyThrough('App\PtcCampaign', 'App\PtcAd');
}
public function delete()
{
$this->ptcAds()->delete();
// I'VE TRIED WITH AND WITHOUT THIS
$this->ptcCampaigns()->delete();
return parent::delete();
}
PtcAd Model
use SoftDeletes;
protected $fillable = ['advertiser_id', 'title'];
protected $dates = ['deleted_at'];
public function advertiser()
{
return $this->belongsTo('App\Advertiser');
}
public function ptcCampaigns()
{
return $this->hasMany('App\ptcCampaign');
}
public function delete()
{
$this->ptcCampaigns()->delete();
return parent::delete();
}
PtcCampaign Model
use SoftDeletes;
public $timestamps = false;
protected $fillable = ['ptc_ad_id', 'clicks'];
protected $dates = ['paused_at', 'deleted_at'];
public function ptcAd()
{
return $this->belongsTo('App\PtcAd');
}
My tests:
public function test_delete_advertiser()
{
$advertiser = factory(Advertiser::class)->create();
$ptcAd = factory(PtcAd::class)->create(['advertiser_id' => $advertiser->id]);
$ptcCampaign = factory(PtcCampaign::class)->create(['ptc_ad_id' => $ptcAd->id]);
$this->assertTrue($advertiser->delete());
$this->assertFalse(Advertiser::all()->contains($advertiser));
$this->assertFalse(PtcAd::all()->contains($ptcAd));
// THE FOLLOWING TEST DOESN'T WORK!
$this->assertFalse(PtcCampaign::all()->contains($ptcCampaign));
}
// ALL OF THE FOLLOWING TESTS WORK!
public function test_delete_ad()
{
$ptcAd = factory(PtcAd::class)->create();
$ptcCampaign = factory(PtcCampaign::class)->create(['ptc_ad_id' => $ptcAd->id]);
$this->assertTrue($ptcAd->delete());
$this->assertFalse(PtcAd::all()->contains($ptcAd));
$this->assertFalse(PtcCampaign::all()->contains($ptcCampaign));
}
The $this->assertFalse(PtcCampaign::all()->contains($ptcCampaign)) in the test_delete_advertiser() test fails, why?
I have more tests to make sure all the relationships work so I really don't know what could possibly be wrong. My next attempt would be to make foreach in the Advertiser's delete() method but maybe there's something simpler and I want to understand why this doesn't work.
It looks the problem is with the sequence of delete statement.
Try by changing the sequence like below:
public function delete()
{
$this->ptcCampaigns()->delete();
$this->ptcAds()->delete();
return parent::delete();
}
You can use Laravel's Model Events (deleting) to delete related models like this:
class Advertiser extends Eloquent
{
public function ptcAds()
{
return $this->hasMany('PtcAd');
}
// this is a recommended way to declare event handlers
protected static function boot() {
parent::boot();
static::deleting(function($adv) { // before delete() method call this
$adv->ptcAds()->delete();
// do the rest of the cleanup...
});
}
}
// Same for PtcCompaigns
class PtcAd extends Eloquent
{
public function ptcCompaigns()
{
return $this->hasMany('PtcCompaigns');
}
// this is a recommended way to declare event handlers
protected static function boot() {
parent::boot();
static::deleting(function($ptc_ad) { // before delete() method call this
$ptc_ad->ptcCompaigns()->delete();
// do the rest of the cleanup...
});
}
}
Hope this helps!

Categories