PHP 7.1 - Build associative Multidimensional Array from sql query - php

I have a sql server table, VATTable like this:
VatCode | VATRate | Description | Active
00 0 VAT Rate 0.00% 1
04 4 VAT Rate 4.00% 1
06 6 VAT Rate 6.00% 1
...
21 21 VAT Rate 21.00% 1
....
with this query
$query = "SELECT VatCode, VatRate, Description, 0 as Goods, 0 as eFees, 0 as pFees, 0 as sFees, 0 as VAT, 0 as Total from VATTable where active=1";
$result = sqlsrv_query($conn,$query);
I need to build a multidimensional array with such data, that looks like this:
$VATTable = array
(
'04'=> array(
'VATRate'=>'4',
'Desc'=>'VAT 4.00%',
'Goods'=>0,
'eFees'=>0,
'pFees'=>0,
'sFees'=>0,
'Taxable'=>0,
'VAT'=>0,
'Total'=>0
),
'06'=> array(
'VATRate'=>'06',
'Desc'=>'VAT 6.00%',
'Goods'=>0,
'eFees'=>0,
'pFees'=>0,
'sFees'=>0,
'Taxable'=>0,
'VAT'=>0,
'Total'=>0
),
'10'=> array(
'VATRate'=>'10',
'Desc'=>'VAT 10.00%',
'Goods'=>0,
'eFees'=>0,
'pFees'=>0,
'sFees'=>0,
'Taxable'=>0,
'VAT'=>0,
'Total'=>0
)
);
so to be able to manage it in the following way:
$vatCode='10';
$VATTable[$vatCode]['Goods']=15;
echo $VATTable[$vatCode]['Desc'].': '.$VATTable[$vatCode]['Goods'];
although my php knowledge is poor I think I have first to build the inner array and then use array_push to add to VATTable Array, but while searching for such solution,
I found some example where I understood (??) that perhaps this can be done while fetching the recordset, and I thought I could do in this way:
$VATTable = array();
while($row = sqlsrv_fetch_array($result))
{
$VATTable[$row['VATCode']]['VATRate']=$row['VATRate'];
$VATTable[$row['VATCode']]['Desc']=$row['Description'];
$VATTable[$row['VATCode']]['Goods']=$row['Goods'];
};
but it does not work.
can suggest solution?
Thanks

This should work:
while($row = sqlsrv_fetch_array($result)) {
$id = $row['VATCode'];
$VATTable[$id] = [
'VATRate' => $row['VATRate'],
'Desc' => $row['Description'],
'Goods' => $row['Goods'],
}
print_r($VATTable);
Also, you don't need the word "array" in php7.
You can use
$VATTable[$id] = [ ... ]
instead of
$VATTable[$id] = array( ... );
If you don't want to hardcode indexes:
while($row = sqlsrv_fetch_array($result)) {
$id = $row['VATCode'];
$VATTable[$id] = $row;
unset($VATTable[$id]['VATCode']);
}

while($row = sqlsrv_fetch_array($result))
{
$tempVariable = array (
'VATRate'=>$row['VATRate'],
'Desc' =>$row['Description'],
'Goods' =>$row['Goods'],
'eFees' =>$row['eFees'],
'pFees' =>$row['pFees'],
'sFees' =>$row['sFees'],
'Taxable'=>$row['Taxable'],
'VAT' =>$row['VAT'],
'Total' =>$row['Total']
);
$VATTable[$row['VatCode']] = $tempVariable;
};
Now $VATTable contains your multidimensional array

Related

How to sum multiple rows into 1 group in laravel?

I'm doing export but don't know how to foreach calculate
get the employee's total time worked and how much the total amount.
data is retrieved from the database
$data = Clocks::orderBy('updated_at', 'desc')->get();
$row = [];
foreach ($data as $index) {
$row[] = array(
'0' => $index->user_id,
'1' => $index->total_time,
'2' => $index->earned_amount,
'3' => $index->bonus_pay,
);
}
return (collect($row));
I want to output it like this
user time amount bonus
1 25:30 400 20
3 9:00 150
Please help me, thank you for viewing this article.
I found a way
$data = Clocks::groupBy('user_id')
->selectRaw('SEC_TO_TIME( SUM(time_to_sec(`total_time`))) as total_time,
SUM(`earned_amount`) as earned_amount,
SUM(`bonus_pay`) as bonus_pay, user_id')
->get();

How to divide incoming rows of data to be executed by CodeIgniter's update_batch() and insert_batch()?

My objective is to use a combination of CodeIgniter's insert_batch() and update_batch() to add incoming data to my macro_plan table.
In my script below I am attempting to query the database for existing rows based on sr_no values then appropriately call the batch querying methods.
function insert_batch($dataSet)
{
$query = $this->db->query("select sr_no from macro_plan");
$data = $query->result_array();
$sr_nos=array();
foreach($data as $key => $value):
$sr_nos[$key]=$value['sr_no'];
endforeach;
$query1= $this->db->query("select * from macro_plan WHERE sr_no IN ('".$sr_nos."')");
$update_query = $query1->result();
if ($update_query->num_rows() > 0) {
$this->db->update_batch($dataSet,$this->macro_plan);//update if ids exist
} else {
$this->db->insert_batch($dataSet,$this->macro_plan);//insert if does not exist
}
}
However, I am getting the "array to string conversion" error.
$dataset will resemble this:
Array (
[0] => Array (
[quantity_update] => 88
[sr_no] => 2020-11-1
[batch] => Batch 2
[quantity_date_update] => 05-May-20
[inq_id] => 49
)
[1] => Array (
[quantity_update] => 99
[sr_no] => 2020-11-2
[batch] => Batch 1
[quantity_date_update] => 11-May-20
[inq_id] => 49
)
)
My table structure looks like this:
Query your table for pre-existing rows that contain the sr_no values that exist in your $dataSet.
Then apply keys to the result set rows from the sr_no values -- this allows the swift lookup on new data against the old data (to see if the respective new rows should be inserted, executed as an update, or completely ignored because the data is the same.
Untested Suggestion:
function insertUpdateMacroPlan($dataSet)
{
$keyedExistingRows = array_column(
$this->db
->where_in('sr_no', array_column($dataSet, 'sr_no'))
->get('macro_plan')
->result_array(),
null,
'sr_no'
);
foreach ($dataSet as $data) {
if (isset($keyedExistingRows[$data['sr_no']])) {
// sr_no exists in the db, add known id to new data array
$identified = ['id' => $keyedExistingRows[$data['sr_no']]['id']] + $data;
if ($identified != $keyedExistingRows[$data['sr_no']]) {
$updateBatch[] = $identified;
}
// if the arrays contain the same data, the new data will be discarded
} else {
$insertBatch[] = $data;
}
}
if (!empty($insertBatch)) {
$this->db->insert_batch('macro_plan', $insertBatch);
}
if (!empty($updateBatch)) {
$this->db->update_batch('macro_plan', $updateBatch, 'id');
}
}
p.s. if your business logic requires that sr_no values are unique, I recommend that you reflect that in your table configuration by setting the sr_no column as a Unique Key.

How to insert data into table as per Json object value using PHP and Mysql

I need one help. I need to insert multiple data as per some Json object value into table using PHP and MySQL. I am explaining my code below.
$commnt=[{
'day_id':2,
'comment':'vodka1'
},{
'day_id':3,
'comment':'vodka2'
}
]
$result=[{
'day_id':1,
'restaurant':'193'
},{
'day_id':2,
'restaurant':'193'
},{
'day_id':3,
'restaurant':'193'
}
]
Here i need to enter all data from both Json object into this below table as per day_id. I am explaining column of my table below.
db_details:
id day_id restaurant comment
Here my requirement is when day_id will same the respective comment field value will entry into table other wise the comment filed value will remain blank.The expected out put is given below.
id day_id restaurant comment
1 1 193
2 2 193 vodka1
3 3 193 vodka3
My query is given below.
$insertintodetails=mysqli_query($connect,'INSERT INTO db_details
(day_id,restaurant,comment) values ("'. $result.'","'.$result[$i]['restaurant'].'","'.$commnt[$i]['comment'].'")');
Here there may be many use cases,like both Json object length may be same or different but the comment should insert as per day_id otherwise it will remain blank. In my query i can not insert as per required. Please help me to resolve this issue.
$newArray = $insertintodetails = array();
foreach($result as $rs)
{
$newArray[$rs->day_id] = [
"`day_id`=>'{$rs->day_id}'",
"`restaurant`=>'{$rs->restaurant}'"
];
}
foreach($commnt as $rs){
$newArray[$rs->day_id][] = "`comment`='{$rs->comment}'";
}
foreach($newArray as $rs){
$insertintodetails[]=mysqli_query($connect,'INSERT INTO db_details SET '.implode(',',$rs));
}
I create an example from above your question detail. You can try below code. And it should work for you...
//For example taken array and convert it to JSON
$comment = json_encode(array(array('day_id' => '2', 'comment' => 'vodka1'), array('day_id' => '3', 'comment' => 'vodka2')));
$result = json_encode(array(array('day_id' => '1', 'restaurant' => '193'), array('day_id' => '2', 'restaurant' => '193'), array('day_id' => '3', 'restaurant' => '193')));
//Convert JSON to array...
$arrComment = json_decode($comment, true);
$arrResult = json_decode($result, true);
foreach($arrResult AS $keyResult => $dataResult){
$day_id = $dataResult['day_id'];//day_id
$restaurant = $dataResult['restaurant'];//rasturant
$strComment = '';//comment
//Check and extract comment value from multi dimensional comment($arrComment) array...
if($getComment = find_comment_with_dayid($arrComment, $day_id)){
$strComment = $getComment;
}
//Insert records...
$insertintodetails=mysqli_query($connect,'INSERT INTO db_details
(day_id, restaurant, comment) values ("'. $day_id .'","'. $restaurant .'","'. $strComment .'")');
}
//Function will return comment for matched day_id
function find_comment_with_dayid($arrComment, $fieldKey) {
foreach($arrComment as $indCommenr => $dataComment) {
//Check for day_id, matched then return comment...
if($dataComment['day_id'] == $fieldKey) return $dataComment['comment'];
}
return FALSE;
}
Here, I taken example array for avoid JSON issue reported on your question. Hope this work well!

CakePHP's "saveAll" need over 3 minutes to save?

I am making an application using CakePHP. I made an action which uses saveAll function.
And I thought it works well, because it doesn't need so much data, but it took over 3 minutes to save using saveAll, or other save function.
Does anyone find my mistakes?
phpMyadmin's columns:
id, rank, school_detail_id, total_score, school_name,
(there is about 300~400 data)
public function rank_update(){
$check_scores = $this->ClubScore->find('all', array('fields'=>array('id','total_score')));
$check_scores2 = Set::sort($check_scores, "{n}.ClubScore.total_score","DESC");
$rank_id=0;
$temp_score=0;
$temp = null;
$for_count=0;
foreach ($check_scores2 as $check_score):
if($temp_score != $check_score['ClubScore']['total_score']){
$rank_id++;
$temp_score = $check_score['ClubScore']['total_score'];
// make ranking by score. same score is same ranking.
}
$this->ClubScore->id = $check_score['ClubScore']['id'];
$this->ClubScore->saveField('rank', $rank_id);
endforeach;
}
Divide the query from foreach to simpler approach
get distinct total_score in desc order
$data = $this->ClubScore->find('all', array('fields'=>array('DISTINCT total_score'), 'order' => 'total_score DESC'));
and then simply save the key as rank for each total_score using updateAll and foreach
Thank you very much Abhishek and AgRizzo ,Nunser!!
Now, I've completely solved this problem. It takes only 1 or 2 seconds!!!!!
Here is the source code.
public function rank_update(){
$data = $this->ClubScore->find('all', array('fields'=>array('DISTINCT total_score'), 'order' => 'total_score DESC'));
$check_scores = $this->ClubScore->find('all', array('fields'=>array('id','total_score')));
$check_scores2 = Set::sort($check_scores, "{n}.ClubScore.total_score","DESC");
$ii = 0;
$temp = 0;
foreach($check_scores2 as $scores):
if($data[$ii]['ClubScore']['total_score']
== $scores['ClubScore']['total_score']){
$temp=$ii+1;
}else{
$ii++;
$temp=$ii+1;
}
$update_arr[] = array(
'ClubScore' => array(
'id' => $scores['ClubScore']['id'],
'rank' =>$temp,
)
);
endforeach;
$update_arr = Set::sort($update_arr, "{n}.ClubScore.id","ASC");
var_dump($update_arr);
foreach($update_arr as $update_arrs):
$this->ClubScore->updateAll(
array(
'ClubScore.rank' => $update_arrs['ClubScore']['rank'],
),
array(
'ClubScore.id' => $update_arrs['ClubScore']['id'],
)
);
endforeach;
}
Thank you very much.
Best regards.

Associative Array - duplicated key values

I am doing a simple shopping application were user may choose books from the store based on the title, price, quantity etc. At the moment all details of the books are kept in an associative array which looks like this:
$menu = array(
array ('id' => '1', 'catagory' => 'newbooks','title' => 'Alex','price' => 4.95, 'desc' => 'bbbb'),
array('id' => '2','catagory' => 'newbooks','title' => 'David ','price' => 5.95, 'desc' => 'sss'),);
}
What I am trying to achieve is merge or remove duplicated entries of book id's also each book title will be printed in one single row containing 'title', 'id', 'price'
for example:
Alex qty:2 price 4.95
David qty:2 price 5.95
and so on...
And this is my cart file:
$buy = array();
$qty = 0;
$total = 0;
foreach ($_SESSION['buy'] as $id) {
foreach ($menu as $book ) {
if ($book['id'] == $id) {
$buy[] = $book;
$total += $book['price'];
}
}
}
}
if (count($buy) > 0)
if (count($book) > 0)
{
echo"<table>";
echo"<tr><th>Item Description</th><th>Quantity</th><th>Price</th></tr>";
foreach ($buy as $book){
$f_price = sprintf("%0.2f", $book["price"]);
echo"<tr><td>" .$book["title"] ."</td>";
echo"<td>" .$qty."</td><";
echo"<td>" .$f_price."</td></tr>";
}
echo"<tr><td>Total</td><td>".$total."</td></tr>";
echo"</table>";
}
I will be extremely grateful for any help or advice cause I spent long long time to resolve this problem trying use unique functions, for statements foreach loop but in vain I am still novice also please try to be a little tolerant . Cheers!
Untested but this should do what you want using array_count_values to obtain the quantities you were looking for along with a few changes to make the script more efficient and easier to manage.
<?php
//the ids of the items the user wants to buy
$ids=$_SESSION['buy'];
//Your database of items
$menu = array(
array ('id' => '1', 'catagory' => 'newbooks','title' => 'Alex','price' => 4.95, 'desc' => 'bbbb'),
array('id' => '2','catagory' => 'newbooks','title' => 'David ','price' => 5.95, 'desc' => 'sss')
);
//Create a reverse look-up for the database
$lookUp=array();
foreach($menu as $i=>$v)$lookUp[$v['id']]=$menu[$i];
//populate the cart with items, their quantities, and a total
$cart = array();
$total = 0;
foreach (array_count_values($ids) as $id=>$quantity)
{
if (!array_key_exists($id, $lookUp))continue;
$item=$lookUp[$id];
$itemTotal=$item['price']*$quantity;
$total+=$itemTotal;
$cart[]=array_merge($item,array('quantity'=>$quantity,'itemTotal'=>$itemTotal));
}
if(count($cart) > 0)
{
echo '<table>';
echo '<tr><th>Item Description</th><th>Quantity</th><th>Price</th><th>Item Total</th></tr>';
foreach ($cart as $item)
{
echo sprintf('<tr><td>%s</td><td>%s</td><td>%0.2f</td><td>%0.2f</td></tr>',
$item["title"],$item['quantity'],$item['price'],$item['itemTotal']);
}
echo '<tr><td colspan="3" style="text-align:center;">Total</td><td>'.$total.'</td></tr>';
echo '</table>';
}
If it's just based off the id, when you build the array, store the book id as the key in the larger array, so your end array would be:
$books = array(
1=> array ('id' => '1', [...]),
2=> array ('id' => '2', [...])
);
You could also add some code that checks when you try to assign a value to that array to see if the key is already set.
if(!isset($books[$book_id])){
//Add to the array
}else{
//Maybe display an error?
}
PS: Category only has one a in it.
It's a pretty cumbersome way to make a stock overview of the books in your collection, but that aside :)
If i was to work with an array like that, (and i would never do that :)) i would first select all unique keys, and then go through them one by one, counting the number of times it occur in the $menu array.
As follows:
$unique_books = array_unique($menu);
foreach($unique_books as $book){
$qty = array_keys($menu, $book["id"])
$book["qty"] = $qty;
$stock = $book;
}
As you can see, now $stock will be the unique array, with a qty added to it, containing the number of times, the id was seen in $menu.
This is just a fast code block, and should be testet, but the theory works i think. As i mentioned before, the way you'r making this in the first place, is not very smart, and you should really reconsider the whole thing imo :)
If you don't wanna duplicates simple use the book_id as the key of buy array
Example:
$menu = array(
array('id' => '1', 'catagory' => 'newbooks','title' => 'Alex','price' => 4.95, 'desc' => 'bbbb'),
array('id' => '2','catagory' => 'newbooks','title' => 'David ','price' => 5.95, 'desc' => 'sss')
);
$session=array(1,2,2,2,1);
$buy = array();
foreach ($session as $id) {
foreach ($menu as $book) {
if ($book['id'] == $id) {
if(isset($buy[$id])){
$buy[$id]['qty']++; // increase quantity
$buy[$id]['total'] += $book['price']; // total price only for this id
$buy['total'] += $book['price']; // All ids price total
}else{
$buy[$id] = $book; // assign new id to the buy array
$buy[$id]['qty'] = 1; // quantity reset to 1
$buy[$id]['total'] = $book['price']; // id price
$buy['total'] += $book['price']; // total price
}
}
}
}
print_r($buy);
You can test it here!
http://codepad.org/wH2WskLG
Instead of merging duplicates you should add book id and qty as array row to session.
On session start..
if (!isset($_SESSION['buy']))
$_SESSION['buy'] = array();
When adding new..
$new_book = $added_book; // just for example
$qty = $added_qty; // Added qty
// Check if book already exists in shopping cart and update qty
if (array_key_exists($new_book['id'], $_SESSION['buy'])) {
$_SESSION['buy'][$new_book['id']] += $qty;
} else {
$_SESSION['buy'][$new_book['id']] = $qty;
}
Then on shopping cart view just loop thru your items..
foreach($menu as $book ) {
if (array_key_exists($book['id'], $_SESSION['buy'])) {
// User bought this book..
$qty = $_SESSION['buy'][$book['id']];
}
}

Categories