Laravel - How to update data calculate by it's column - php

How to update data with calculating by it's column
I have table item
+---------+-------+-------+-----------+
| item_id | stock | price | name |
+---------+-------+-------+-----------+
| 1 | 10 | 9.4 | Paper |
+---------+-------+-------+-----------+
| 2 | 10 | 12.8 | Pencil |
+---------+-------+-------+-----------+
| 3 | 10 | 99.9 | Note Book |
+---------+-------+-------+-----------+
and then I wanna update the sock by calculating stock column
stock - $request->qty
If I do manualy base query
update items set stock = stock - 3 where item_id = 1
it's working, but when I use laravel eloquent the stock become 0 (zero), I dunno why,
here is my controller
public function saveOrder(Request $request) {
$item = new Item;
$item->where('item_id', '=', $request->item_id)->update(['stock' => 'stock - '. $request->qty]);
return redirect('order');
}
any solution? Thanks for answer, sorry for bad english :)

Try this one:
$item = new Item;
$item->where('item_id', '=', $request->item_id)->decrement('stock', $request->qty);

You could try something like this:
$item = Item::where('item_id', '=', $request->item_id)->first();
$item->stock = (int)$item->stock - (int)$request->qty;
$item->save();
Alternatively you could try to use DB::raw expression.

This should do the trick for you
public function saveOrder(Request $request) {
Item::where('item_id', $request->item_id)
->decrement('stock', $request->qty);
return redirect('order');
}

public function saveOrder(Request $request){
$stockdetails = \DB::table('tablename')->where('itemid',$request->itemid)->first(['stock as stock']);
//update query
$update= \DB::table('tablename')->update(['stock'=>($stockdetails->stock)-($request->quantity)])->where(itemid',$request->itemid);
if($update){
//sucecss
}else{
//Fail
}

Related

How to sum a colum from a related model efficiently on Laravel

Ok I got this table
affiliates_referral_clicks
id | affiliate_id | clicks | date
1 | 1 | 10 | 2021-07-14
2 | 1 | 2 | 2021-07-11
3 | 2 | 1 | 2021-07-11
4 | 2 | 14 | 2021-07-10
...
Of course my Model Affiliate has a relationship with referralClicks
Affiliate.php
public function referralClicks(){
return $this->hasMany(AffiliateReferralClick::class,'affiliate_id');
}
Now I want to bring all Affiliates with the SUM of all their clicks that have a date between a given date. I implemented it like this
$affiliate = Affiliate::with(['referralClicks' => function($query) use($params) {
$query->whereDate('date','>=', $params['dateFrom'])
->whereDate('date','<=', $params['dateTo'])
->select('clicks')
;
}])->get();
foreach ($affiliates as $affiliate){
$affiliate->totalClicks = $affiliate->referralClicks->sum('clicks');
}
this works fine, but since the affiliates_referral_clicks table is waaaay too big and the request ends up being too slow, I think if you do the query without using Eloquent's helpers you can get a much faster query.
So my question would be...how can I do the same I just did but with raw querys (or whatever the most efficient way is)? Im using a MySQL DB I hope you guys can help me!
Haven't tried that yet but that's how I'd solve this (if we assume, you only need the sum and nothing else from the relationship):
$affiliate = Affiliate::withSum(['referralClicks.clicks as totalClicks' => function($query) use($params) {
$query->whereDate('date','>=', $params['dateFrom'])
->whereDate('date','<=', $params['dateTo'])
->select('clicks')
;
}])->get();

Mysql where clause on multiple fields which one might be null

In my products table, I have 2 columns: price and discounted_price in which discounted_price is null most of the time unless there is a promotion for that product:
+----+--------------------+-------+------------------+
| id | name | price | discounted_price |
+----+--------------------+-------+------------------+
| 1 | test 1 | 79.00 | null |
| 2 | test 2 | 50.00 | 45.00 |
+----+--------------------+-------+------------------+
The product with id of 2 is now on promotion and has discounted_price.
Now I want to query products to get products cheaper than 50 but in my query I need to check if discounted_price is null then look into price, otherwise look into discounted_price. What Google said is using:
$products = Product::where('coalesce(price, discounted_price) <= 50);
But it's not working :(
Alternative, you can use sub query, like this :
$q = 50;
$product = Product::where(function($query) use($q) {
$query->where('discounted_price', '<=', $q)
->orWhere('price', '<=', $q)
})
->get();
you can use whereRaw
instead of where or where(DB::raw('coalesce(price, discounted_price') <= 50))
also be carful to close your where by ' character
i recommend using where with clouser like this:
$products = Product::where(function ($query)
{
$query->where('discounted_price',null)->where('price','<=',50);
})->orWhere('discounted_price','<=',50)->get();

Eloquent using foreach inside each function

I want to exchange image order(Data retrieved from angularjs/ui-sortable, so the $newImgOrder array is representing the new order.)
(array) $newImgOrder = ['test.jpeg', 'another.jpeg'];
Images::select('url')->where('project_id', '=', $args['id'])->get()
->each(function($img) use (&$newImgOrder) {
foreach ($newImgOrder as $item) {
$img->url = $item;
$img->save();
}
});
* UPDATED = RIGHT WAY FOR THE PERFORMING THIS ACTION *
Thanks #Devon
Removed foreach + select()
(array) $newImgOrder = ['test.jpeg', 'another.jpeg'];
Images::where('project_id', '=', $args['id'])->get()
->each(function($img) use (&$newImgOrder) {
$img->url = array_shift($item);
$img->save();
}
});
Here is a quick demonstration for what i want to do:
Table state before the action
+---------+-------------+--------------+
| id | project_id | url |
+---------+-------------+--------------+
| 1 | 15 | another.jpeg |
+---------+-------------+--------------+
| 2 | 15 | test.jpeg |
+---------+-------------+--------------+
Expected results =
+---------+-------------+--------------+
| id | project_id | url |
+---------+-------------+--------------+
| 1 | 15 | test.jpeg |
+---------+-------------+--------------+
| 2 | 15 | another.jpeg |
+---------+-------------+--------------+
Actual results =
+---------+-------------+--------------+
| id | project_id | url |
+---------+-------------+--------------+
| 1 | 15 | another.jpeg |
+---------+-------------+--------------+
| 2 | 15 | another.jpeg |
+---------+-------------+--------------+
What's the problem with that iteration. I tried with double foreach but i got the same results... Am i something missing out? Any help would be very appreciated. Thanks.
For each image, your code is looping through $newImageOrder and saving the url for that image. Hence, you're performing two saves for every image, which is clearly not what you want.
There is no reason for the inner foreach loop. If you're certain the number of elements in $newImageOrder will match the number of rows from your query and since you're passing $newImageOrder as a reference to the closure, you could make use of shift:
each(function($img) use (&$newImgOrder) {
$img->url = array_shift($newImgOrder);
$img->save();
});
This will shift the first element off of the array and return it, meaning you'll be removing and using the first element of $newImgOrder for each iteration.
Keep in mind, this is a mutable change. $newImgOrder is mutated by the closure. If this is not what you want, you may want to use a running count for the offset instead.

select rows with the same value using Codeingiter

How to select all with the same value using codeigniter.
+-------+-------------+------------+
| id | coupon_code | Barcode |
+-------+-------------+------------+
| 1 | COUPON02 | 12542 |
| 2 | COUPON02 | 11229 |
| 3 | COUPON03 | 11823 |
| 4 | COUPON03 | 47875 |
+-------+-----------+--------------+
public function fetch_available_coupon(){
$coupon_code = $this->uri->segment(3);
$this->db->select('*');
$this->db->from('barcode');
$this->db->where('coupon_code', $coupon_code);
$query = $this->db->get();
if ($query->num_rows() > 0) {
foreach ($query->result() as $row) {
$data[] = $row;
}
return $data;
}else{
return false;
}
}
in my result it only show 1 row not the not all the same Coupon_Code
Im using codeigniter as my active record. Please Help thank you
use where condition instead of group by
$this->db->where('coupon_code', $coupon_code);
You can use GROUP BY to group values from a column, and, if you wish, perform calculations on that column. You can use COUNT, SUM, AVG, etc., functions on the grouped column.

Yii criteria selecting all rows

I am useing Yii framework to do a criteria selection for all rows that fit the criteria.
I am trying to take the ID of one table and search another tables codes that contain the prefix of the ID. (exp ID-code or 1-sdfa). Currently the code below is returning all of the rows as a result. Below are the details, any insight would help. Thank you.
[table 1]
tbl_School
---------------------------
| ID | Name |
---------------------------
| 1 | forist hills |
| 2 | Dhs |
---------------------------
[table 2]
tbl_ticket
------------------
| ID | code |
------------------
| 1 | 1-fd23s |
| 2 | 2-fdet2 |
| 3 | 1-4wscd |
| 4 | 2-oifjd |
| 5 | 1-zzds6 |
------------------
After runing the function on ID=1 I would like to see
------------------
| ID | code |
------------------
| 1 | 1-fd23s |
| 3 | 1-4wscd |
| 5 | 1-zzds6 |
------------------
Here is my code:
public static function get_tickets($ticket_ID){
$match = '';
$match = addcslashes($match, "$ticket_ID".'_%');
$q = new CDbCriteria( array(
'condition' => "code LIKE :match",
'params' => array(':match' => "$match%")
) );
$rows = Ticket::model()->findAll( $q );
return $rows;
}
PDO does escaping for you so you don't need to do the addcslashes yourself (I didn't even know that existed, always used addslashes :) )
Secondly, you end up selecting on [NUMBER]_%%, those are 3 wildcards.
As Ryan already changed in its comment, you might want to select on -% instead:
public static function get_tickets($ticket_ID){
$ticket_ID = intval($ticket_ID);
if (!$ticket_ID)
return null;
$q = new CDbCriteria( array(
'condition' => "code LIKE :match",
'params' => array(':match' => $ticket_ID . "-%")
) );
$rows = Ticket::model()->findAll( $q );
return $rows;
}
As you can see, I did do a numeric sanity check for the ticket number, just like being cautious.
Lastly: I hope you don't mind the suggestion, but isn't it simply possible adding the ticket number as a separate column? You are going to end up with perfectly avoidable performance problems if there are a lot of rows in this table. With a separate column that is an index you'd use a lot less cpu for the same result.

Categories