Laravel 6 id change after sort by relationship - laravel

I don't know how to explain it...
On Tinker:
$m = App\Models\Mobiliari::Buscar('5')
$m->get()
=> Illuminate\Database\Eloquent\Collection {#3038
all: [
App\Models\Mobiliari {#3051
id: "5",
entitat_id: "3",
tipus_mobiliari_id: "2",
descripcio: null,
data_compra: null,
proveidor_id: "2",
factura: null,
cost: ".0000",
ubicacio_id: "2",
},
],
}
Buscar is a function to filter on some fields:
public function scopeBuscar($query, $filtre)
{
if ($filtre)
{
return $query->where('mobiliari.id', $filtre)
->orWhere('descripcio', 'like', '%'.$filtre.'%')
->orWhereHas('Entitat', function($q) use ($filtre) {
$q->where('entitat', 'like', '%'.$filtre.'%');
})
->orWhereHas('TipusMobiliari', function($q) use ($filtre) {
$q->where('tipus', 'like', '%'.$filtre.'%');
})
->orWhereHas('Proveidor', function($q) use ($filtre) {
$q->where('proveidor', 'like', '%'.$filtre.'%');
})
->orWhereHas('Ubicacio', function($q) use ($filtre) {
$q->where('edifici', 'like', '%'.$filtre.'%')
->orWhere('ubicacio', 'like', '%'.$filtre.'%');
});
}
}
Then, when try to order the result through a related table, the ID change te value
$m->join('entitat', 'mobiliari.entitat_id', '=', 'entitat.id')->orderBy('entitat.entitat','asc')->get()
=> Illuminate\Database\Eloquent\Collection {#3041
all: [
App\Models\Mobiliari {#3040
id: "3",
entitat_id: "3",
tipus_mobiliari_id: "2",
descripcio: null,
data_compra: null,
proveidor_id: "2",
factura: null,
cost: ".0000",
ubicacio_id: "2",
entitat: "UAB Idiomes",
rao_social: "Escola d'Idiomes Moderns Casa Convalescència SL",
},
],
}
I captured the query generated with DB::enableQueryLog(); and dd(DB::getQueryLog()), executed it on de SQL Server and returns the correct ID...
Anyone knows or can explain why ID is changing?

When you are joining tables, the id can be ambiguous and the Laravel ORM will take one of the id even from your joins.
Adding select() with your current table will help your problem. You can still select extra columns if you need, but if using ids from other tables rename the columns in the SQL.
->select('mobiliari.*');
So try the following code.
$m->join('entitat', 'mobiliari.entitat_id', '=', 'entitat.id')
->orderBy('entitat.entitat','asc')
->select('mobiliari.*')
->get();

Related

"message": "Call to undefined method Closure::getRelationExistenceQuery()", laravel

I have created a function to get data from db but the function returns an error when i test with postman.
public function payments(){
$data = Investigations::whereHas(function($query){
$query->where('name', 'LIKE', '%consultation%' );
})->get();
return $data;
}
The table has these columns
protected $fillable = [
"visit", "admission_id", "type", "procedure", "quantity", "price", "discount",
"amount", "user", "instructions", "ordered", "invoiced", "reasons", "assigned_to",
"performing_doctor", "on_credit", "comments", "credit_status", "is_walkin",
'service_sale_id', "cancelled", 'cancel_text', "date_changed_by", "date_adjusted_from",
"assigned_by", "assigned_on",
'moved_from_chargesheet', 'package_id',
"created_at",
];
I can't see there is a "name" column.
'whereHas' used to query in a relation
Investigations::whereHas('relation_name', function($query){
$query->where('name', 'LIKE', '%consultation%' );
})->get();
If you want to search in the current table, you can use 'where'.
it can be a condition or a function
Investigations::where('name', 'LIKE', '%consultation%' )->get()
 
Investigations::where(function($query){
$query->where('name', 'LIKE', '%consultation%' );
})->get()

How to get specific column after call load() in Eloquent Laravel

I try to show specific columns of my data after call load() , let say 'id','kd_prop_id' only. can somebody help me
public function show(Provinsi $provinsi)
{
abort_if(Gate::denies('provinsi_show'), Response::HTTP_FORBIDDEN, '403 Forbidden');
return new ProvinsiResource($provinsi->load([])); // <-- i want show specific column here..
}
right now its show all fields :
"data": {
"id": 616,
"kd_prop_id": 11,
"kd_kab": 1102,
"kd_dt1": "06",
"kd_dt2": "10",
"nama_kab": "KAB. ACEH",
"lat": 3.3,
"lng": 97.69,
"kd_bast": "061300",
"created_at": null,
"updated_at": null,
"deleted_at": null
}
plase help..thanks
Actually my choice would be to show the fields I want in the ProvinsiResource.
But you can review for only model:
$company = Company::query()
->first();
//$company->load(['customer']); // All company columns and customer columns
$company->load([
'customer' => function($query) {
return $query->select(['id', 'name']);
}
]);
$company->only(['id', 'customer_id', 'name', 'customer']); // Only specific columns in Company and Customer columns
If you have collection, this way could be better:
$companies = Company::query()
->get();
$companies->map(function ($company) {
return collect($company->toArray())
->only(['id', 'name', 'email'])
->all();
});

How to send a separate array inside Laravel eloquent with function?

I have written as below in my code in LineSheet controller and the items function is in LineSheet model, and I have an array call $seasons. Now I need to send this $seasons array with items
LineSheet Controller:
$linesheetItems = LineSheetItem::select('linesheet_id', 'items.season', 'items.amt_item')
->join('items', function ($join) {
$join->on('items.amt_item', '=', 'linesheet_items.item_code');
$join->on('items.company', '=', 'linesheet_items.company');
$join->on('items.division', '=', 'linesheet_items.division');
})
->where('linesheet_items.linesheet_id', '=', $id)
->groupBy('items.amt_item', 'items.season')
->get();
foreach ($linesheetItems as $linesheetItem) {
$seasons[] = Season::where('code', $linesheetItem['season'])->first();
}
$linesheet = LineSheet::where('linesheet.id', '=', $id)
->select('linesheet.*')->with(['items', 'creator:id,username', 'updater:id,username'])
->first();
LineSheet Model:
public function items()
{
return $this->hasMany('\App\Models\LineSheetItem', 'linesheet_id', 'id')
->join('items', function ($join) {
$join->on('items.amt_item', '=', 'linesheet_items.item_code');
$join->on('items.company', '=', 'linesheet_items.company');
$join->on('items.division', '=', 'linesheet_items.division');
})
->join('inventory_items', function ($join) {
$join->on('inventory_items.item', '=', 'linesheet_items.item_code');
$join->on('inventory_items.company', '=', 'linesheet_items.company');
$join->on('inventory_items.division', '=', 'linesheet_items.division');
})
->select('linesheet_items.linesheet_id', 'items.id', 'items.amt_item', 'items.image_name',
'items.company', 'items.division', 'items.color_description', 'items.item_description',
'items.season', 'items.wholesale_price', 'items.retail_price', 'items.color_code',
'items.vendor_desc', 'items.vendor_code', 'inventory_items.on_hand', 'inventory_items.cost',
'items.brand', 'items.category_code', 'items.category', 'items.fabric_code', 'items.fabric_desc')
->groupBy('linesheet_items.item_code', 'linesheet_items.company', 'linesheet_items.division');
}
with items I need to attach my $seasons array also and get a response as below
I expect a final output as below:
"items": [
{
"linesheet_id": 44,
"id": 61,
"amt_item": "PS839730WT",
"image_name": "image_name",
"company": "01",
"division": "PAP",
"color_description": "colordes1",
"item_description": "itemdes1",
"season": "S1",
"wholesale_price": "100",
"retail_price": "100",
"color_code": "colorcode1",
"vendor_desc": "vendor_desc",
"vendor_code": "vendor_code",
"on_hand": "40",
"cost": "3.70",
"brand": "brand",
"category_code": "category",
"category": "category1",
"fabric_code": "code1",
"fabric_desc": "fabric_desc",
seasons: [
//array elements
]
}
]
How to achieve this?
You can use belongsTo relationship and then eager load them. A LineSheetItem seems to belong to a Session.
So you can do LineSheetItem::with('season')->get().
https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-inverse
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading

Laravel Merge to merge same ID

Hello I have query that is already working and it combines two queries, but what I need is to combine the same product _id and not output it into another array.
Here is my code:
$first = DB::table('delivery_receipt_detail');
$first->join('delivery_receipts', 'delivery_receipt_detail.delivery_receipt_id', '=', 'delivery_receipts.id');
$first->where(function ($first) use ($start_date, $end_date) {
$first->whereBetween('delivery_receipts.posting_date', [new Carbon($start_date), new Carbon($end_date)]);
$first->orWhereDate('delivery_receipts.posting_date', '=', new Carbon($start_date));
$first->orWhereDate('delivery_receipts.posting_date', '=', new Carbon($end_date));
});
$first->groupBy('delivery_receipt_detail.product_id');
$first->select('delivery_receipt_detail.product_id as delivery_product_id', DB::raw('SUM(product_qty) as delivery_product_qty'));
$result_one = $first->get();
//Sales
$query = DB::table('sale_detail');
$query->join('sales', 'sale_detail.sale_id', '=', 'sales.id');
$query->where(function ($query) use ($start_date, $end_date) {
$query->whereBetween('sales.posting_date', [new Carbon($start_date), new Carbon($end_date)]);
$query->orWhereDate('sales.posting_date', '=', new Carbon($start_date));
$query->orWhereDate('sales.posting_date', '=', new Carbon($end_date));
});
$query->groupBy('sale_detail.product_id');
$query->select('sale_detail.product_id as sales_product_id', DB::raw('SUM(product_qty) as sales_product_qty'));
$test = $query->get();
$merged = $result_one->merge($test);
$result = $merged->all();
return $result;
and my result is this:
[
{
"delivery_product_id": "1",
"delivery_product_qty": 4
},
{
"delivery_product_id": "2",
"delivery_product_qty": 1
},
{
"sales_product_id": "1",
"sales_product_qty": "3"
},
{
"sales_product_id": "2",
"sales_product_qty": "3"
}
]
What I need is this output
[
{
"product_id": "1",
"delivery_product_qty": 4
"sales_product_qty": "3"
},
{
"product_id": "2",
"delivery_product_qty": 1
"sales_product_qty": "3"
}
]
I need to combine this and merging the same product_id and show their different quantities.
For this case, I think you only need to specify the same name for the product_id when selecting and ->merge will do the rest
$first = DB::table('delivery_receipt_detail')
->select('delivery_product_id as product_id', 'delivery_product_qty');
// ...
$query = DB::table('sale_detail')
->select('sales_product_id as product_id', 'sales_product_qty');
// ...
$merged = $result_one->merge($test);

Laravel: Query across relation-defined table

I have $donor, which is the Donor model.
Also, I have Log that is associated with Donor as defined by this relationship in the Donor model:
public function Log(){
return $this->hasMany(Log::class,'DonorID','DonorID');
}
$donor->load('Log');, which eager load the Donor with all Log associated to it, would return this following
{
"DonorID": "59060001",
"DonorCitizenID": "1000000000009",
"DonorPrefix": "Mx.",
"DonorName": "John",
"DonorSurname": "Smith",
"created_at": "2016-06-21 08:06:44.000",
"updated_at": "2016-06-23 02:15:10.000",
"log": [
{
"LogID": 6,
"DonorID": "59060001",
"EventTypeID": "1",
"EventDate": "2016-06-15",
"EventBrief": "Donor Added",
"created_at": "2016-06-15 06:01:06.000",
"updated_at": "2016-06-15 06:01:06.000"
},
{
"LogID": 21,
"DonorID": "59060001",
"EventTypeID": "2",
"EventDate": "2016-06-23",
"EventBrief": "Donor has rested in peace.",
"created_at": "2016-06-23 02:30:49.000",
"updated_at": "2016-06-23 02:30:49.000"
}
]
}
Now, I have this code of query that takes the inputted text from the field, finds the specific donor, and returns it.
$donors = Donor::
where('DonorCitizenID', 'LIKE', '%'.Input::get('DonorCitizenID').'%')->
where('DonorName', 'LIKE', '%'.Input::get('DonorName').'%')->
where('DonorSurname', 'LIKE', '%'.Input::get('DonorSurname').'%')->
get();
It does as it says, get all the Donors, only if it match the several criteria, and it worked well, as long as the data I matched is stored in the Donor.
But, I want another search field. This one would match the latest Log (as one Donor can has many Logs) in any donor by matching the EventTypeID in the loaded Log. How can I write the condition to do this?
Please kindly note that the returned value is expected to be the list of all Donors matching the criteria.
its should be done like this if i understood what you are saying
edit
$donors = Donor::
where('DonorCitizenID', 'LIKE', '%'.Input::get('DonorCitizenID').'%')
->where('DonorName', 'LIKE', '%'.Input::get('DonorName').'%')
->where('DonorSurname', 'LIKE', '%'.Input::get('DonorSurname').'%')
->with(['Log' => function ($query) {
$query->where('EventType', 'LIKE', '%'.Input::get('EventType').'%')->get();
}])->get();
$donor->Log // result
Use whereHasmethod
$donors = Donor::
where('DonorCitizenID', 'LIKE', '%'.Input::get('DonorCitizenID').'%')
->where('DonorName', 'LIKE', '%'.Input::get('DonorName').'%')
->where('DonorSurname', 'LIKE', '%'.Input::get('DonorSurname').'%')
->whereHas('Log', function ($query) {
$query->where('EventType', 'LIKE', '%'.Input::get('EventType').'%');
})->get();

Resources