change hasManyThrough() relation attribute name through accessor - laravel

I have 3 Models
Campaign PK(id)
CampaignMedium FK(campaign_id)
AccountReceivable FK(campaign_medium_id) (has an amount column)
Controller function:
public function all()
{
return Campaign::with(['customer', 'receivedPayments'])->get();
}
In Campaign Model relationships are defined as follows:
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function accountReceivable()
{
return $this->hasManyThrough(AccountReceivable::class, CampaignMedium::class);
}
public function receivedPayments()
{
return $this->accountReceivable()
->selectRaw('sum(account_receivables.amount) as total')
->groupBy('campaign_id');
}
public function getReceivedPaymentsAttribute()
{
if (!array_key_exists('receivedPayments', $this->relations)) {
$this->load('receivedPayments');
}
$relation = $this->getRelation('receivedPayments')->first();
return ($relation) ? $relation->total : 0;
}
Final Output:
{
"data": [
{
"id": 8,
"name": "example",
"image": "campaign/90375849f6c3cc6b0e542a0e3e6295b890375849f6c3cc6b0e542a0e3e6295b8.jpeg",
"amount": 10,
"description": "saddsa",
"start_at": "2019-02-12 00:00:00",
"end_at": "2019-02-12 00:00:00",
"due_at": "2019-02-12 00:00:00",
"status": "active",
"customer": {
"id": 1,
"name": "test",
"email": "info#test.com",
"image": "customer/ec812116705ff3ae85298234fe6c4e97ec812116705ff3ae85298234fe6c4e97.jpeg",
"address": "sample address"
},
"received_payments": [
{
"total": "700",
"laravel_through_key": 8
}
]
},
{
"id": 9,
"name": "example",
"image": "campaign/fff9fadc92a809513dc28134379851aafff9fadc92a809513dc28134379851aa.jpeg",
"amount": 10,
"description": "saddsa",
"start_at": "2019-02-12 00:00:00",
"end_at": "2019-02-12 00:00:00",
"due_at": "2019-02-12 00:00:00",
"status": "active",
"customer": {
"id": 1,
"name": "test",
"email": "info#test.com",
"image": "customer/ec812116705ff3ae85298234fe6c4e97ec812116705ff3ae85298234fe6c4e97.jpeg",
"address": "sample address"
},
"received_payments": []
}
]
}
summary: trying to get the sum of AccountReceivable amount attribute, which is working fine but the getReceivedPaymentsAttribute() isn't working which needs to return the total value only. also can anyone please help me to explain why laravel_through_key is added with received_payments?

I've never tried to use an attribute modifier to modify a relation this way. You are overriding the expected result of receivedPayments(). You might be better off to define a separate attribute like so:
public function getSumReceivedPaymentsAttribute()
{
// ...your code...
}
Now you can access the attribute using $model->sum_received_payments or always preload it using:
// model.php
protected $appends = ['sum_received_payments'];

Related

Filter Data with Pivot Table Laravel Eloquent

I want to filter users based on their subscription_status which s stored in a pivot table.
I have Three tables users , subscription_packages , subscription_package_user
$user=User::with(['studentDetails','subscriptionsSatus.courses'])
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();
this code return the response is
[
{
"id": 44,
"first_name": "Abcd Test",
"last_name": "Test lastname",
"student_details": null,
"subscriptions_satus": [
{
"id": 1,
"name": "Gold",
"price": 3000,
"user_id": "2"
"pivot": {
"user_id": 44,
"subscription_package_id": 1,
"subscription_status": "on_free_trial",
"expires_on": null,
"id": 9
},
"courses": [
{
"id": 18,
"title": "English Grammar for Class 3",
"price": 400,
"strikethrough_price": null,
"status": "draft",
"user_id": 2,
"image": "http://127.0.0.1:8000/courses/1615702915.png",
"description": null,
"pivot": {
"subscription_package_id": 1,
"course_id": 18,
}
}
]
}
]
}]
i want to return only users who having subscription_status =$filter.
$filter='acive'or 'on_free_trail'
my model is
public function subscriptionsSatus()
{
return $this->belongsToMany(SubscriptionPackage::class)->withTimestamps()->withPivot('subscription_status','expires_on','id');
}
I havetried
$filter=$request->input('filter')??"active";
$user=User::with(['studentDetails','subscriptionsStatus.courses'])
->whereHas('subscriptionsStatus', function($query) use($filter){
$query->wherePivot('subscription_status','=',$filter);
})
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();
But Got error Column not found 'pivot'
You need to use wherePivot along with the orWhere like below:
public function subscriptionsStatus()
{
return $this->belongsToMany(SubscriptionPackage::class)
->withTimestamps()
->withPivot('subscription_status','expires_on','id')
->wherePivot(function($q){
return $q->where('subscription_status','=','active')
->orWhere('subscription_status','=','on_free_trail');
});
}
Update
Or in your controller:
$user=User::with(['studentDetails','subscriptionsStatus.courses'])
->whereHas('subscriptionsStatus', function($query) use($filter){
$query->withPivot('subscription_status')
->wherePivot('subscription_status','=',$filter);
})
->withPagination($offset,$perPage)
->get()
->sortBy('first_name')->values();

how to return a json response based on database relationship

I'm quite new to Laravel,
Let's say I have 2 tables: main_sport and sub_sport. These two tables have a one-to-many relationship. 1 sport can have many sub sports.
I want the following json format
{
"success": "1",
"sports": [
"id": 1,
"name_of_categories": "Popular Sports",
"sub_sports:[
{
"id": 1,
"name_sub_sport_category": "Badminton"
},
{
"id": 2,
"name_sub_sport_category": "Football"
},
{
"id": 3,
"name_sub_sport_category": "Cricket"
},
]
]
"sports":[
"id": 2,
"name_of_categories": "Team Sports",
"sub_sports:[
{
"id": 4,
"name_sub_sport_category": "Badminton"
},
{
"id": 5,
"name_sub_sport_category": "Football"
},
]
]
}
I try for this function and i am getting following result
public function fetch()
{
$query= DB::table('details')
->join('table_sub_sport_category','table_sub_sport_category.id','=','details.sub_id')
->join('table_main_sport_category','table_main_sport_category.id','=','details.main_id')
->select(DB::raw('table_main_sport_category.id as id'),'table_main_sport_category.name_of_categories','table_sub_sport_category.name_sub_sport_category')
->get()
return response()->json(['success' =>'1','data'=>$query]);
}
{
"success": "1",
"data": [
{
"id": 1,
"name_of_categories": "Popular Sports",
"name_sub_sport_category": "Badminton"
},
{
"id": 1,
"name_of_categories": "Popular Sports",
"name_sub_sport_category": "Football"
},
{
"id": 1,
"name_of_categories": "Popular Sports",
"name_sub_sport_category": "Cricket"
},
]
}
Could you help me to get the desired result?
You should define sub_sport in the main sport Model like this:
class Sport extends Model{
public function sub_sport(){
return $this->hasMany(SubSport::class);
}
}
And in your controller you should write this:
$data = Sport::with('sub_sport')->get();
Use below code
$query= DB::table('details')
->join('table_sub_sport_category','table_sub_sport_category.id','=','details.sub_id')
->join('table_main_sport_category','table_main_sport_category.id','=','details.main_id')
->select(DB::raw('table_main_sport_category.id as id'),'table_main_sport_category.name_of_categories','table_sub_sport_category.name_sub_sport_category')
->get()
return Response::json([
'status' => 'error',
'sports' => $query
], 200);

Laravel get only one column from relation

I have a table user_childrens whose contains id_parent and id_user.
I'm trying to list all childrens of the parent with this:
code:
//relation in model via belongsTo
$idparent = auth('api')->user()->id;
$list = UserChildren::where('id_parent',$idparent)
->with('child:id,name,email')
->get();
return $list->toJson();
The return is:
[
{
"id": 1,
"id_parent": 1,
"id_user": 1,
"created_at": null,
"updated_at": null,
"child": {
"id": 1,
"name": "Mr. Davin Conroy Sr.",
"email": "prempel#example.com"
}
},
{
"id": 4,
"id_parent": 1,
"id_user": 2,
"created_at": null,
"updated_at": null,
"child": {
"id": 2,
"name": "Krystel Lehner",
"email": "cernser#example.net"
}
}
]
But it's API so I want only the child column like:
[
{
"id": 1,
"name": "Mr. Davin Conroy Sr.",
"email": "prempel#example.com"
},
{..}
]
UserChildren Model:
public function child() {
return $this->belongsTo('App\User','id_user','id');
}
I know that I could do this via .map() on collection but maybe there is other solution already on this query
You can use this code
$idparent = auth('api')->user()->id;
$childs = User::whereHas('user_childrens', function ($query) use ($idparent) {
$query->where('id_parent', $idparent);
})->get(['id', 'name', 'email']);
dd($childs->toJson());
And User model define user_childrens relation.
public function user_childrens()
{
return $this->hasMany('App\UserChildren','id_user','id');
}
See also docs https://laravel.com/docs/5.5/eloquent-relationships#querying-relationship-existence

remove data from laravel fractal

I'm using laravel-fractal to transform my data and here is a response
how can I delete data;
I made a search and I realized I need to use a Serializer;
But I just want to remove data for all includes(relations)
{
"data": [
{
"id": 1,
"name": "test name",
"status": null,
"tags": [
"first",
"second"
],
"created_at": "1396/9/3",
"contacts": {
"data": [
{
"value": "test#test.com",
"type": "email",
"icon": "fa fa-email"
}
]
}
},
{
"id": 2,
"name": "name test 2",
"status": null,
"tags": [],
"created_at": "1396/9/3",
"contact": {
"data": []
}
}
]
I found my answer at GitHub. The following answer is copied from thephpleague/fractal on GitHub:
You can write your own serializer for that.
class YourDataSerializer extends ArraySerializer
{
public function collection($resourceKey, array $data)
{
if ($resourceKey) {
return [$resourceKey => $data];
}
return $data;
}
public function item($resourceKey, array $data)
{
if ($resourceKey) {
return [$resourceKey => $data];
}
return $data;
}
}
Register your serializer with manager
$manager = new Manager();
$manager->setSerializer(new YourDataSerializer());
and when you want to have data or anything else you can pass in resourceKey to your Item or Collection as a third param.
$resource = new Collection($folders, new AccountFolderTransformer(), 'data');
use array serializer:
Fractal::create()
->item($item, new MyTransformer())
->serializeWith(new ArraySerializer())

How can I output the return value of a Method like totalAmount in an Spring Rest Entity

is it possible to output a return Value totalAmount of an Entity ShoppingCart that is not a Value in the Class but a Method? So for example I have a Class Shoppingcart with a List of Items. and a Method totalAmount. Now when I make a request to the API with the URL http://localhost:8082/carts/1 I want to get a response like the following:
{
"creationDate": "2016-12-07T09:45:38.000+0000",
"items": [
{
"itemName": "Nintendo 2DS",
"description": "Konsole from Nintendo",
"price": 300.5,
"quantity": 3
},
{
"itemName": "Nintendo Classic",
"description": "Classic nintendo Console from the 80th...",
"price": 75,
"quantity": 2
}
],
"totalAmount": "1051,50",
"_links": {
"self": {
"href": "http://localhost:8082/carts/2"
},
"cart": {
"href": "http://localhost:8082/carts/2"
},
"checkout": {
"href": "http://localhost:8083/order"
}
}
}
Currently the response of an API request looks like the following:
{
"creationDate": "2016-12-07T09:45:38.000+0000",
"items": [
{
"itemName": "Nintendo 2DS",
"description": "Konsole from Nintendo",
"price": 300.5,
"quantity": 3
},
{
"itemName": "Nintendo Classic",
"description": "Classic nintendo Console from the 80th...",
"price": 75,
"quantity": 2
}
],
"_links": {
"self": {
"href": "http://localhost:8082/carts/2"
},
"cart": {
"href": "http://localhost:8082/carts/2"
},
"checkout": {
"href": "http://localhost:8083/order"
}
}
}
Is there an Annotation that do this job or something other. I tried to add it in the CartResourceProcessor (org.springframework.hateoas.ResourceProcessor) but there is only the possibility to add additional links. Or do I need to add a Class value totalAmount?
Yes you can achieve that by annotating your method with Jackson #JsonProperty annotation
Code sample
#JsonProperty("totalAmount")
public double computeTotalAmount()
{
// compute totalAmout and return it
}
And to answer the possible next question you get after reading this. How the totalAmount is calculated. Here the snippet
public Class Cart{
// some Class values
#JsonProperty("totalAmount")
public BigDecimal total(){
return items.stream()
.map(Item::total)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
public class Item{
// some Item values
#JsonProperty("totalAmount")
public BigDecimal total(){
return price.multiply(new BigDecimal(this.quantity));
}
}
Outputs something similar to this:
{
"creationDate": "2016-12-07T09:45:38.000+0000",
"items": [
{
"itemName": "Nintendo 2DS",
"description": "Konsole from Nintendo",
"price": 300.5,
"quantity": 3,
"totalAmount": 901.5
},
{
"itemName": "Nintendo Classic",
"description": "Classic nintendo Console from the 80th...",
"price": 75,
"quantity": 2,
"totalAmount": 150
}
],
"totalAmount": 1051.5,
"_links": {
"self": {
"href": "http://localhost:8082/carts/2"
},
"cart": {
"href": "http://localhost:8082/carts/2"
},
"checkout": {
"href": "http://localhost:8083/order"
}
}
}
Hope it helps you :)

Resources