Inserting multiple arrays into different rows - php

I'm collecting input fields as an array to be inserted into the different rows in the database. However it only inserts the first row of the array.
Please kindly assist. I have some issues handling arrays. I don't know how to construct the query and I've tried to search online and I couldn't get enough help. I'll really appreciate help with the query.
Here is my HTML code:
<input type = "text" class = "form_element" name = "wat_office_type[]" />
<input type = "number" name = "wat_office_price[]" class = "form_element" />
while I use jQuery to add more input boxes.
Here is my php:
$wat_office_type_post = $_POST['wat_office_type'];
$wat_office_price_post = $_POST['wat_office_price'];
$wat_office_type = array();
$wat_office_price = array();
foreach ($wat_office_type_post as $type) {
if (!empty($type))
$wat_office_type[] = $afrisoft->antiHacking($type);
}
foreach ($wat_office_price_post as $post) {
if (!empty($post))
$wat_office_price[] = $afrisoft->antiHacking($post);
}
I want to insert into 2 separate rows and achieve something like this:
--------------------------------------------
| Pk | wat_office_type | wat_office_price |
--------------------------------------------
| 1 | executive office | 1000 |
--------------------------------------------
| 2 | Training room | 4000 |
--------------------------------------------
| 3 | Events room | 5000 |
--------------------------------------------
I'll kindly appreciate if I can get help with the insert query (mysql,php) on how I can insert all values of the first array in one column, and values of the second array into the second column, while each are matching d numbers of arrays supplied.
Thanks.

If I understand correctly, you need to combine the two arrays into something like
$list = array(
array('pk' => 1, 'type' => 'executive', 'price' => 1000),
array('pk' => 2, 'type' => 'training room', 'price' => 4000),
array('pk' => 3, 'type' => 'events room', 'price' => 5000)
);
then you can call a foreach loop to query the database with each element, like
foreach($list as $key => $value) {
$sql = "INSERT INTO table_name (pk, type, price) VALUES (?, ?, ?)";
$query = $this->db->prepare($sql);
$params = array($value['pk'], $value['type'], $value['price']);
if($query->execute($params)) {
return true;
} else {
return false;
}
}
so instead doing two foreach loops and putting results in different arrays, you could use one foreach loop and create an associative array for each set of results (I assume the count on both of your arrays is the same?) as I mentioned above.

Related

Codeigniter 4 query builder join display only 1 time from first table

I have done up a query builder using join. I would like to show table 2, 3, 4, 5, 6 and so on based on the user id on table 1. I tried to query the result, it is showing like this :
My Tables
Table users
user_id | username | email
1 | userA | userA#email.com
2 | userB | userB#gmail.com
Table add_game
game_id | user_id | ign | acc_id
1 | 1 | ignA | accA
2 | 1 | ignB | accB
1 | 2 | ignB | accB
3 | 2 | ignD | accD
I will be using foreach loop and I believe it will display out multiple times based on the records in the database. What should I do if I only want to display the information highlighted in the red box (which is from users table) just 1 time and all the records associated with user id in add_game table?
This is my current code :
Controller
public function login()
{
$data = [];
helper(['form']);
$validation = \Config\Services::validation();
$db = db_connect();
$model = new LoginModel($db);
$user = $model->login($this->request->getVar('userlogin'));
$this->setUserSession($user[0]);
echo view('templates/header', $data, $user);
echo view('account/login', $data, $user);
echo view('templates/footer', $data, $user);
}
private function setUserSession($user){
$data = [
'user_id' => $user['user_id'],
'username' => $user['username'],
'email' => $user['email'],
'firstname' => $user['firstname'],
'lastname' => $user['lastname'],
'dob' => $user['dob'],
'country' => $user['country'],
'country_code' => $user['c_code'],
'contact' => $user['contact'],
'game_id' => $user['game_id'],
'ign' => $user['ign'],
'acc_id' => $user['acc_id'],
'isLoggedIn' => true
];
session()->set($data);
return true;
}
Model:
return $this->db->table('users')
->groupStart()
->where('username', $str)
->orWhere('email', $str)
->groupEnd()
->join('add_game', 'add_game.user_id = users.user_id')
->get()
->getResultArray();
I have a few more tables but not yet created for now so I have only joined 1 table for the time being. What am I missing? Or do I have to loop twice? Is there a way that I just need to loop 1 time? Hope someone can help me out here. Thanks in advance guys!
the easiest way to achieve this (display 2 records from add_game table and 1 record from users table) you need to create a foreach loop in your view, and exclude duplicated data from users table to be shown.
controller:
$data['my_data']=$this->Your_model->your_method(); // your query example
$this->load->view('your_view',$data)
view:
<?php $my_id=0;foreach($my_data as $row):?>
<?php if($my_id!=$row->user_id):?>
<div><?=$row->username?></div> <!--data from table user-->
<div><?=$row->created_at?></div> <!--data from table add_game-->
<?php else:?>
<div><?=$row->created_at?></div> <!--only data from table add_game-->
<?php endif;?>
<?php $my_id=$row->user_id;endforeach;?>

PHP processing data and create array

I have a mysql query with result like this:
ID | index | Mapping index | Date
1 | 27 | value27 | 2019-04
2 | 28 | value28 | 2019-05
3 | 28 | value28 | 2019-05
4 | 32 | value32 | 2019-07
5 | 32 | value32 | 2019-05
The results should be prepared to display stacked charts. As result i need in php:
// array to display google chart
['2019-04', 1, 0, 0,],
['2019-05', 0, 2, 1,],
['2019-07', 0, 0, 1,],
// explanation
ID | value27 | value28 | value 32 | Date
1 | 1 | 0 | 0 | 2019-04
2 | 0 | 2 | 1 | 2019-05
2 | 0 | 0 | 1 | 2019-07
This is my php script:
$preparevar = array();
foreach($data["timechart"] as $date){
array_push($preparevar,[$date->date, $date->count , '\''.$date->repcontent.'\'' ]);
}
$googleChartArray = array(); //Use this array to group the results using date.
foreach( $preparevar as $d ) {
$date = $d[0];
$value = $d[1];
if( !isset( $googleChartArray[$date] ) ) {
$googleChartArray[$date] = array( "'". $date. "'" ); //Date needs to be enclosed in quote.
}
$googleChartArray[$date][] = $value;
}
$f = array(); //Format the above array to split value in a comma separated format.
foreach( $googleChartArray as $g ) {
$f[] = implode( ',' , $g );
}
$json_out = json_encode(array_values($googleChartArray));
The problem with this format is, that the zero values will be ignored:
[
['2019-04',1],
['2019-05',2,1],
['2019-07',1]
]
should be:
[
['2019-04',1,0,0],
['2019-05',0,2,1],
['2019-07',0,0,1]
]
Here an example of $data["timechart"]:
array(11) {
[0]=>
object(stdClass)#43 (14) {
["id"]=>
string(2) "46"
["index"]=>
string(2) "31"
["index2"]=>
string(1) "0"
["keynr"]=>
string(2) "31"
["repcontent"]=>
string(41) "Value31"
["count"]=>
string(1) "1"
["date"]=>
string(7) "2007-06"
}
And here an example of my query. I canĀ“t use SUM(CASE) for example beacause index are variable.
SELECT
orders.id,
positions_list.index,
RepK.keynr,
RepK.content AS repcontent,
RepK.p_company,
COUNT(positions_list.index) AS count,
DATE_FORMAT(orders.date_placement, '%Y-%m') AS date
from orders
JOIN tools
ON tools.id=orders.tool_id
JOIN positions_list ON positions_list.order_id = orders.id
LEFT JOIN repkey as RepK
ON RepK.keynr=positions_list.index
AND RepK.p_company=orders.comp_id
WHERE
tools.id =:id
AND RepK.keynr IS NOT NULL
group by DATE_FORMAT(orders.date_placement, '%Y-%m'),positions_list.index
MySQL doesn't currently offer variable width pivots, so you can either:
make two queries, the first to collect the unique repcontent columns, then build a second query to implement a pivot technique by writing a SELECT clause with dynamic CASE WHEN statements for each column or
make one query, and let php prepare the results (this can be scripted up in a few different ways, but I'll recommend this one)
Code: (Demo)
$resultSet = [
['repcontent' => 'Value 27', 'date' => '2019-04'],
['repcontent' => 'Value 28', 'date' => '2019-05'],
['repcontent' => 'Value 28', 'date' => '2019-05'],
['repcontent' => 'Value 32', 'date' => '2019-07'],
['repcontent' => 'Value 32', 'date' => '2019-05'],
];
$columns = array_unique(array_column($resultSet, 'repcontent'));
$lookupKeys = range(1, count($columns));
$lookup = array_combine($columns, $lookupKeys);
$defaults = array_fill_keys($lookupKeys, 0);
foreach ($resultSet as $row) {
if (!isset($result[$row['date']])) {
$result[$row['date']] = array_merge([$row['date']], $defaults);
}
++$result[$row['date']][$lookup[$row['repcontent']]];
}
echo json_encode(array_values($result));
Output:
[["2019-04",1,0,0],["2019-05",0,2,1],["2019-07",0,0,1]]
For simplicity, generate a result set as an array of arrays.
Extract the unique repcontent values
Generate an array with values ranging from 1 to the unique repcontent count
Forge a lookup array consisting of #1 as keys and #2 as values -- this will determine where each "count" will stored when looping later
Create a default array consisting of #2 as keys and zeros as values
Now, loop through the result set and if a given row has a repcontent value which is encountered for the first time, create a new row in the output array using the date as the first element and the elements from #4 to follow.
Unconditionally, add 1 to the row's column that corresponds with with the repcontent value
If you don't quite understand why any of the variables ($columns, $lookupKeys, $lookup, $defaults) are generated or what they contain, call var_export() on my variables before entering the loop -- that should clear up any confusion.
I have a feeling that I could refine your query, but I won't venture a guess without having some realistic sample data to play with.
I don't see why you would need to add additional quotes to your json for the Google chart to work. If the chart doesn't render without the additional quotes, this is probably a symptom that you are passing the php variable to javascript in an improper fashion.
p.s. I see that you some development with Joomla, if this is a Joomla script and you are not able to craft your query with Joomla's query building methods, please post your best effort on Joomla Stack Exchange and I'll see if I can help.

PHP combine two arrays in foreach loop

I need guidance on how to combine two arrays in foreach loop. I have a list of checkboxes that will add user to corresponding list.
To grab my checkboxes as an array using :
<input type="checkbox" name="checkbox_list[]" value="Austin Metro">
<input type="checkbox" name="checkbox_list[]" value="Central Austin">
<input type="checkbox" name="checkbox_list[]" value="Georgetown">
...
Here is my loop:
foreach($_POST['checkbox_list'] as $check) {
$myValues = array('Austin Metro','Central Austin','Georgetown','Lake Travis | Westlake','Leander | Cedar Park','Northwest Austin','Round Rock | Pflugerville | Hutto','San Marcos | Buda | Kyle','Southwest Austin','DFW Metro','Frisco','Grapevine | Colleyville | Southlake','McKinney','Plano','Houston Metro','Conroe | Montgomery','Cy-Fair','Katy','Pearland | Friendswood','Spring | Klein','Sugar Land | Missouri City','Tomball | Magnolia','The Woodlands');
$myIds = array('3','4','5','6','7','8','9','10','11','25','12','13','14','15','24','16','17','18','19','20','21','23','22');
if (isset($check) && array_search($check, $myValues) !== false){
$index = array_search($check, $myValues);
$indeed_mail->indeed_wysija_subscribe( $myIds[$index], $email );
}
}
Currently it is adding user to the right list but is sending one email confirmation per list, instead of merging all subscribed lists in one single email.(in other words if user selects "Austin" & "Houston" lists, it will get one email for "Austin" and one email for "Houston")
Any suggestions on how to fix? Thanks!
Here is function that add subscriber and sends email confirmation:
public function indeed_wysija_subscribe( $listId, $e_mail, $first_name='', $last_name='' ){
$user_data = array(
'email' => $e_mail,
'firstname' => $first_name,
'lastname' => $last_name);
$data = array(
'user' => $user_data,
'user_list' => array('list_ids' => array($listId))
);
$helper = &WYSIJA::get('user', 'helper');
if($helper->addSubscriber($data)) return 1;
else return 0;
}
You should define the array with checkbox names/IDs outside of your loop, and use a more appropriate structure for them:
$map = array (
3 => 'Austin Metro',
4 => 'Central Austin',
5 => 'Georgetown',
6 => 'Lake Travis | Westlake',
7 => 'Leander | Cedar Park',
8 => 'Northwest Austin',
9 => 'Round Rock | Pflugerville | Hutto',
10 => 'San Marcos | Buda | Kyle',
11 => 'Southwest Austin',
25 => 'DFW Metro',
12 => 'Frisco',
13 => 'Grapevine | Colleyville | Southlake',
14 => 'McKinney',
15 => 'Plano',
24 => 'Houston Metro',
16 => 'Conroe | Montgomery',
17 => 'Cy-Fair',
18 => 'Katy',
19 => 'Pearland | Friendswood',
20 => 'Spring | Klein',
21 => 'Sugar Land | Missouri City',
23 => 'Tomball | Magnolia',
22 => 'The Woodlands',
);
Now you can even remove the loop completely and continue with this code:
// take from map only those entries that have been checked:
$checks = array_intersect($map, $_POST['checkbox_list']);
// pass the IDs of those values to the emailing class:
$indeed_mail->indeed_wysija_subscribe( array_keys($checks), $email );
You just now need to adapt that indeed_wysija_subscribe so it can deal with arrays. There is only one line to change:
'user_list' => array('list_ids' => $listId)
Notice that array($listId) becomes just $listId because that argument is now already an array.
PHP have array_combine function
http://php.net/manual/en/function.array-combine.php
Ignoring the Title of your questions and focusing on the question asked.
Currently it is adding user to the right list but is sending one email confirmation per list, instead of merging all subscribed lists in one single email.
You need to collate the user ids selected, before you pass it into the subscribe function.
Currently your calling the subscribe function, indeed_wysija_subscribe, inside the foreach loop foreach($_POST['checkbox_list'] as $check) {.
You need to move the subscribe call outside the loop and pass in an array of $listId.
This may require you to modify the indeed_wysija_subscribe function to support the array. Or there may be another function in the library.
I am not sure what is part of the library or not.
Also, you can perform the mapping between city name to numeric id in more direct manner.
$myValues = array('Austin Metro','Central Austin','Georgetown');
$myIds = array('3','4','5','6');
$cityToIdMap = array(
'Austin Metro'=>'3',
'Central Austin'=>'4',
'Georgetown'=>'5'
);
$subscriberIds = array();
foreach($_POST['checkbox_list'] as $check) {
if(!empty($check) && isset($cityToIdMap[$check])){
$subscriberIds[] = $cityToIdMap[$check];
}
}

php sort merge arrays

I have a list of (xml) items, each item has a category and a name:
Category | Name
1 | Joe
2 | Carol
3 | Bruce
1 | Michael
1 | Alan
2 | Brian
I want to sort the names ascending within categories descending like so:
Category | Name
3 | Bruce
2 | Brian
2 | Carol
1 | Alan
1 | Joe
1 | Michael
with the aim of creating a Select dropdown on a web page with each category as an OptGroup and the names sorted within the OptGroup.
I have very little experience with PHP, I think I need to sort merge arrays, but after many hours trying to understand how to, I'm not making much progress.
Any help greatly appreciated
$data[] = array('category' => 1, 'name' => 'Joe');
$data[] = array('category' => 2, 'name' => 'Carol');
$data[] = array('category' => 3, 'name' => 'Bruce');
$data[] = array('category' => 1, 'name' => 'Michael');
$data[] = array('category' => 1, 'name' => 'Alan');
$data[] = array('category' => 2, 'name' => 'Brian');
<?php
// Obtain a list of columns
$category =array();
$name =array();
foreach ($data as $key => $row) {
$category[$key] = $row['category'];
$name[$key] = $row['name'];
}
// Sort the data with category descending, name ascending
// Add $data as the last parameter, to sort by the common key
array_multisort($category, SORT_DESC, $name, SORT_ASC, $data);
echo '<pre>'; print_r($category);
?>
Hi thanks to everybody for your help including all the other Stackoverflow questions which I googled to piece this together, not sure how I did it, bit of a case of an infinite number of monkeys or should that be newbies, anways here's what worked for me.
Sorts names ascending within contributions descending
function compare($a, $b) {
if ($a['contribution'] == $b['contribution']) {
return ($a['name'] < $b['name']) ? -1 : 1;
} else {
return ($b['contribution'] - $a['contribution']);
}
}
usort($ads_by_cotribution, 'compare');
It's all magic to me, that's the beauty of it. I didn't include the case of names being equal
'cause there shouldn't be any and as I understand equal values would still stay together just in a different order. I'd like to understand how these functions work, do they continuously walk through the array until there's no change in the order - what we used to call a bubble sort? Does ($b['contribution'] - $a['contribution']) indicate which is the larger? Finley is there a difference between sorting contributions - a numeric field and names - an alpha field?
$name = array("Joe", "Carol", "Bruce", "Michael","Alan","Brian");
sort($name);
php-in built function sort will produce desire result

Merge meta table with main table

I have two tables, a main one, and one that supports the main table, very very similar to what wordpress has, posts and posts_meta.
Main table:
id
title,
content
id | title | content
1 | one | content one
2 | two | content two
Meta table:
id
item_id
key
value
id | item_id | key | value
1 | 1 | template | single
2 | 1 | group | top
1 | 2 | template | page
2 | 2 | group | bottom
And my goal is, in the end, have an array with the data from the main table, merged with the meta table. example:
$data = array(
array(
'id' => 1,
'title' => 'one',
'content' => 'content one',
'template' => 'single',
'group' => 'top'
),
array(
'id' => 2,
'title' => 'two',
'content' => 'content two',
'template' => 'page',
'group' => 'bottom'
)
);
What is the best way to achieve this in a way that preforms good?
I am using PDO to connect to my database, and how Im doing right now is, I first query the data on the first table, and then for each result, i query the meta table, I use prepared statements for this, since it's suposed to be fast, but even so, it's harming the performance of my script.
Thank you
Instead of querying meta table for each result from first query
you should extract the ids from the first result:
$rows = q('SELECT * FROM posts');
$byIds = [];
foreach ($rows as &$row)
{
$byIds[$row['id']] =& $row;
}
and run second query:
$rows2 = q('SELECT * FROM posts_meta WHERE item_id IN (' . implode(',', array_keys($byIds)) . ')');
Then loop the results in PHP and merge with first query results.
foreach ($rows2 as $row2)
{
$byIds[$row2['item_id']][$row2['key']] = $row2['value'];
}
You have your merged results in $rows variable now:
var_dump($rows);
This way you will have only 2 db requests.
Please note that i have used $byIds as array of references so i dont have to search row with specific id in second loop. This way order of elements in $rows are preserved.

Categories