I have a query that sums up the total of fields in my database.
//HoursRepository.php
public function findHoursTotal($user)
{
return $this->createQueryBuilder('h')
->where('h.user = :user')
->select('SUM(h.total)')
->setParameter('user', $user)
->getQuery()
->getResult();
}
This query returns:
array:1 [▼
0 => array:1 [▼
1 => "52400"
]
]
My question is how do i get just the "52400" result as a string and not in an array?
you should use getSingleScalarResult(), bellow the usage example :
return $this->createQueryBuilder('h')
->where('h.user = :user')
->select('SUM(h.total)')
->setParameter('user', $user)
->getQuery()
->getSingleScalarResult();
Related
I try to select count and group with Laravel query, but they are return same value with different field.
This is my code:
$kategoris = ['NUK', 'Hubkel', 'Sta_kawin'];
foreach ($kategoris as $kategori) {
$raw[] = 'count('.$kategori.') as '.$kategori;
}
$implodeRaw = implode(', ', $raw);
$desas = DB::table('arts')
->select('arts.id', 'KDKEC', 'KDDESA', DB::raw($implodeRaw))
->where(['KDKEC' => $kodeKecamatan])
->groupBy('KDDESA')
->orderBy('KDDESA', 'ASC')
->get();
Result:
results: {
0 => {
'id': 10
'NUK': 6
'Hubkel': 6
'Sta_kawin': 6
}
1 => {
'id': 13
'NUK': 1
'Hubkel': 1
'Sta_kawin': 1
}
}
So, what's wrong with this code? I want the NUK, Hubkel, Sta_kawin return different value because the source data is different.
In the Orders Table Model I need the category ids of the products associated with the order
Model/Table/OrdersTable.php
public function updateQuantityForInventoryItems(array $orders_items): void
{
$ordersItemsIds = [];
foreach ($orders_items as $orders_item) {
array_push($ordersItemsIds, $orders_item->product_id);
}
$catIds = $this->find('ordersItemsCategories', ['ordersItemsIds' => $ordersItemsIds])->toArray();
dd($catIds);
$InventoriesTable = TableRegistry::getTableLocator()->get('Inventories');
$InventoriesTable->updateQuantityForInventoryItems('orders', $catIds);
}
public function findOrdersItemsCategories(Query $query, array $options): Query
{
$query = $this->OrdersItems->Products
->find()
->select(['Products.id','CategoriesProducts.category_id'])
->matching(
'CategoriesProducts', function (Query $q) use ($options) {
return $q->where([
'CategoriesProducts.product_id IN' => $options['ordersItemsIds'],
]);
});
return $query->hydrate(false);
}
the generated SQL query
SELECT Products.id AS `Products__id`, CategoriesProducts.category_id AS `CategoriesProducts__category_id` FROM products Products INNER JOIN categories_products CategoriesProducts ON (CategoriesProducts.product_id in (4325,3632) AND Products.id = (CategoriesProducts.product_id))
When I print out the array with dd($catIds); , I get an array with _matchingData
array:4 [▼
0 => array:2 [▼
"id" => 3632
"_matchingData" => array:1 [▼
"CategoriesProducts" => array:1 [▼
"category_id" => 10
]
]
]
1 => ...
]
how do i get category_id under id
(i have already checked that thread How to print _matchingData object value in cakephp 3 but still no success)
got it. i need to alias the category_id to prevent nesting
->select(['category_id' => 'CategoriesProducts.category_id'])
I have Json Data like this :
$data = '[
{
"OrderId": "1038806370",
"qtty": "1",
"Item": "Strawberry 250 gr",
"SKU": "20091"
},
{
"OrderId": "1038806370",
"qtty": "2",
"Item": "Strawberry 130 gr",
"SKU": "20092"
},
{
"OrderId": "1038806370",
"qtty": "1",
"Item": "Strawberry 130 gr",
"SKU": "20092"
}
]';
and I want to Save in my database MySql using PHP Laravel,...
I Want To save data from json to my table, there are table Order values [orderID,...] and OrderDetail values [orderID, SKU, Qty]
This is my code in controller
$order = json_decode($data, true);
foreach ($order as $ord) {
$check = Order::where('orderid', $ord['OrderId'])->get();
if (count($data) > 0) {
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
} else {
Order::create([
'orderid'=> $ord['OrderId'],
]);
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
}
}
but i dont get what i want, I get QTY of SKU 20091 is 2 but actual json data is 3
I'm not sure why you're counting the $data instead of $check variable. You don't really need the $check variable either though. I'll rewrite your code below.
$order = json_decode($data, true);
foreach ($order as $ord) {
// use EXIST query to check if Order exists or not.
if (Order::where('orderid', $ord['OrderId'])->exists())
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
} else {
Order::create([
'orderid'=> $ord['OrderId'],
]);
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
}
}
But your if/else could also be removed by using the firstOrCreate() method.
$orders = json_decode($data, true);
foreach ($orders as $order) {
// Get Order Model with orderid = $order['OrderId'] or create it if it doesn't exist
$model = Order::firstOrCreate([
'orderid'=> $order['OrderId']
]);
// Get OrderDetail with provided SKU, qtty and orderid or create it if it doesn't exist.
OrderDetail::firstOrCreate([
'order_id' => $model->orderid
'sku_id' => $order['SKU'],
'qty' => $order['qtty']
]);
}
You could also do it inline.
$orders = json_decode($data, true);
foreach ($orders as $order) {
OrderDetail::firstOrCreate([
'order_id' => Order::firstOrCreate(['orderid'=> $order['OrderId']])->orderid,
'sku_id' => $order['SKU'],
'qty' => $order['qtty'],
]);
}
Receiving the request in array format
[
[
[
'condition1',
'value1',
],
[
'condition2',
'value2',
],
],
[
'condition3',
'value4',
]
]
Im trying to build query builder with values1 and values 2 in 'or' condition and value3 in 'and' condition
$result = DB::table('table ')
foreach($values as $value){ //
$result->where(function ($qry) use ($value) { // array 0,1 with and condition
foreach($value as $val){ // values1 , values2
$qry->where();
}
});
}
How to add 'or' condition between the values1 and values2 and then 'and' condition with value3.
Don't need any loop, you need sub query, like this :
$result = DB::table('table')
->where(function($query) use($value1) {
$query->where('condition1', $value1)
->orWhere('condition2', $value1);
})
->where('condition3', $value2)
->get();
I am making an inventory management system.
When a product is out of stock, I make an entry in a table and note the "oos_at" field with the date/time.
later, when it is back in stock, i find that entry and update the "restocked_at" timestamp field.
However, when I do the second action, my "oos_at" field is overwritten with the timestamp of the query ('updated_at') field...
I had to keep track of this "oos_at" field on another entity so it wouldn't get overwritten and then use that field to update the "oos_at" field a second time when updating that table...
Below is my code....
class Pusher extends Model {
/**
*
*
* #param Carbon $oos_at
* #return bool
*/
public function setAsOutOfStock(Carbon $oos_at)
{
Log::info([
'FILE' => get_class($this),
'method' => 'setAsOutOfStock',
'pusher' => $this->id,
'param:oos_at' => $oos_at->toDateTimeString(),
]);
$this->pusherOutOfStocks()->create([
'location_id' => $this->location_id,
'product_id' => $this->product_id,
'oos_at' => $oos_at->toDateTimeString(),
]);
$this->oos = true;
$this->oos_at = $oos_at;
return $this->save();
}
/**
* Clear the PusherOutOfStocks attached to $this Pusher
* (This Pusher has been restocked!)
*
* #param Carbon $time
* #return bool
*/
public function setAsInStock(Carbon $time)
{
Log::info([
'FILE' => get_class($this),
'method' => 'setAsInStock',
'pusher' => $this->id,
'param:time' => $time->toDateTimeString(),
]);
$this->pusherOutOfStocks()->where('restocked_at', null)
->update(['restocked_at' => $time->toDateTimeString()]);
$this->oos = false;
$this->oos_at = null;
return $this->save();
}
}
When I die and dump the PusherOutOfStocks BEFORE the pusher is restocked, then the "oos_at" is set appropriately.
Illuminate\Database\Eloquent\Collection {#340
#items: array:1 [
0 => Newave\Engineering\PusherOutOfStock {#343
#fillable: array:5 [
0 => "pusher_id"
1 => "location_id"
2 => "product_id"
3 => "oos_at"
4 => "restocked_at"
]
#dates: array:2 [
0 => "oos_at"
1 => "restocked_at"
]
#connection: null
#table: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:9 [
"id" => 246
"pusher_id" => 216
"location_id" => 634
"product_id" => 378
"oos_at" => "2016-03-11 03:00:00"
"restocked_at" => null
"created_at" => "2016-03-11 12:12:01"
"updated_at" => "2016-03-11 12:12:01"
"deleted_at" => null
]
#original: array:9 [
"id" => 246
"pusher_id" => 216
"location_id" => 634
"product_id" => 378
"oos_at" => "2016-03-11 03:00:00"
"restocked_at" => null
"created_at" => "2016-03-11 12:12:01"
"updated_at" => "2016-03-11 12:12:01"
"deleted_at" => null
]
#relations: []
#hidden: []
#visible: []
#appends: []
#guarded: array:1 [
0 => "*"
]
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
#forceDeleting: false
}
]
}
When I die and dump the PusherOutOfStocks AFTER the pusher is restocked, then the "oos_at" is the same as "updated_at"
Illuminate\Database\Eloquent\Collection {#408
#items: array:1 [
0 => Newave\Engineering\PusherOutOfStock {#775
#fillable: array:5 [
0 => "pusher_id"
1 => "location_id"
2 => "product_id"
3 => "oos_at"
4 => "restocked_at"
]
#dates: array:2 [
0 => "oos_at"
1 => "restocked_at"
]
#connection: null
#table: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:9 [
"id" => 244
"pusher_id" => 214
"location_id" => 626
"product_id" => 374
"oos_at" => "2016-03-11 12:10:23"
"restocked_at" => "2016-03-11 04:00:00"
"created_at" => "2016-03-11 12:10:22"
"updated_at" => "2016-03-11 12:10:23"
"deleted_at" => null
]
#original: array:9 [
"id" => 244
"pusher_id" => 214
"location_id" => 626
"product_id" => 374
"oos_at" => "2016-03-11 12:10:23"
"restocked_at" => "2016-03-11 04:00:00"
"created_at" => "2016-03-11 12:10:22"
"updated_at" => "2016-03-11 12:10:23"
"deleted_at" => null
]
#relations: []
#hidden: []
#visible: []
#appends: []
#guarded: array:1 [
0 => "*"
]
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
#forceDeleting: false
}
]
}
I have even used DB::getQueryLog() and saw NOWHERE that 'oos_at' was being explicitly set/updated....
Nowhere else in my code is this table modified...
Does anyone understand what is happening here????
Thank you!!
=============
Extra Code Snippets
Table Migration::
Schema::create('pusher_out_of_stocks', function (Blueprint $table) {
$table->increments('id');
$table->integer('pusher_id');
$table->integer('location_id');
$table->integer('product_id');
$table->timestamp('oos_at');
$table->timestamp('restocked_at')->nullable();
$table->timestamps();
$table->softDeletes();
});
PusherOutOfStock Class
class PusherOutOfStock extends Model
{
use SoftDeletes;
protected $fillable = [
'pusher_id',
'location_id',
'product_id',
'oos_at',
'restocked_at',
];
protected $dates = [
'oos_at',
'restocked_at'
];
/**
* A PusherOutOfStock belongsTo a Product
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function product()
{
return $this->belongsTo(Product::class);
}
/**
* A PusherOutOfStock belongsTo a Pusher
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function pusher()
{
return $this->belongsTo(Pusher::class);
}
/**
* A PusherOutOfStock belongsTo a Location
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function location()
{
return $this->belongsTo(Location::class);
}
}
Below is the sequence the code goes through to hit that update method
First, it hits my InventoryController in my API namespace
public function upload(Request $request)
{
$data = $request->all();
$header = $this->getHeader($data);
$body = $this->getBody($data);
$reader = $this->getReaderFromHeader($header);
if ( ! $this->guardAgainstNoReader($reader))
return (new Response("Reader with mac-address: ". $header['reader_mac'] . " does not exist.", 409));
$result = $this->inventoryRepository->uploadPusherData($reader, $header, $body);
return $result;
}
Then it sends the request to the InventoryRepository
public function uploadPusherData(Reader $reader, $header, $body)
{
foreach ($body as $pusherData)
{
$result[] = $this->processPusherData($pusher, $header['timestamp'], $pusherData);
}
return $result;
}
Then, inside the repository, it processes one line at a time (in my test, there is only one line)
private function processPusherData(Pusher $pusher, $timestamp, $pusherData)
{
$latestInventory = $pusher->latestInventory;
if (! $latestInventory)
return $this->updatePusher($pusher, $timestamp, $pusherData);
if ($latestInventory->tags_blocked == $pusherData['data_TAGSBLKED'])
return $this->noChangeRecorded($pusher, $latestInventory, $timestamp);
return $this->updatePusher($pusher, $timestamp, $pusherData);
}
Then the pusher is updated...
public function updatePusher($pusher, $timestamp, $pusherData)
{
// See if there are any existing already
$prevInv = $pusher->latestInventory;
// Create the new data
$inventory = Inventory::create([
'pusher_id' => $pusher->id,
'product_id' => $pusher->product_id,
'reader_id' => $pusher->reader->id,
'tags_blocked' => $pusherData['data_TAGSBLKED'],
'paddle_exposed'=> $pusherData['paddle_exposed'],
'created_at' => Carbon::createFromTimestamp($timestamp)
->toDateTimeString(),
]);
if ( !$prevInv || $prevInv->id == $inventory->id )
{
return "first-data" . $timestamp;
}
return $this->checkForEvents($inventory, $prevInv);
}
We check if any events should be triggered... In this case, previous inventory had 9 items in stock... now there are 0.
private function checkForEvents(Inventory $currentInventory, Inventory $previousInventory)
{
if ( ! $previousInventory->oos && $currentInventory->oos && $previousInventory->pusher->oos_notified == 0)
{
$currentInventory->pusher->oos_notified = true;
$currentInventory->pusher->save();
return Event::fire(new InventoryOutOfStock($currentInventory));
}
if ( ( $previousInventory->oos || $previousInventory->status == "RESTOCK" )
&& $currentInventory->tags_blocked > 2 )
{
return Event::fire(new PusherWasRestocked($currentInventory));
}
if ( $currentInventory->status == "RESTOCK" && $previousInventory->pusher->low_stock_notified == 0)
{
$currentInventory->pusher->low_stock_notified = true;
$currentInventory->pusher->save();
return Event::fire(new LowStockAlert($currentInventory));
}
return "no-events";
}
This then fires the event InventoryOutOfStock
That triggers 3 events... 2 are related to notifications being sent etc..
'App\Events\InventoryOutOfStock' => [
'App\Listeners\InventoryOutOfStockUpdater',
'App\Listeners\EmailInventoryOutOfStockNotification',
'App\Listeners\SMSInventoryOutOfStockNotification',
// 'App\Listeners\OutOfStocksUpdater',
],
Which leads us to ...
public function handle(InventoryOutOfStock $event)
{
$pusher = $event->pusher;
$inventory = $event->inventory;
$product = $pusher->product;
$oos = $pusher->setAsOutOfStock($inventory->created_at);
$locationPushers = $product->getPushersByLocation($pusher->location);
$isInStock = false;
foreach ($locationPushers as $pusher)
if ($pusher->oos == 0)
$isInStock = true;
if (! $isInStock)
$product->productOutOfStocks()->create([
'location_id' => $pusher->location_id,
'oos_at' => $event->inventory->created_at,
]);
}
I think that you do not have to use the timestamp method to create your fields, but you should use the dateTime method:
Schema::create('pusher_out_of_stocks', function (Blueprint $table) {
$table->increments('id');
$table->integer('pusher_id');
$table->integer('location_id');
$table->integer('product_id');
$table->dateTime('oos_at');
$table->dateTime('restocked_at')->nullable();
$table->timestamps();
$table->softDeletes();
});
This should work :)
Hope it helped!