Select where to display values from MySQL DB in CodeIgniter - php

I want to display the values from MySQL database using CodeIgniter. Here, I am using SELECT to query to compare the multiple values using the WHERE condition.
I want to display the checked rows values from one page to another. I am passing the the checked value via URL. In the second page, I am getting the value from the URL, and using the explode() function to split the value and display using a for loop. Here, values are displaying correctly. But, when passing the array values to the SELECT query, it displays only the last rows.
I want to display all checked rows from the database.
For example, sample code:
<?php
$id = $this->uri->segment(4);
$arr = explode(',', $id);
for ($kk = 0; $kk < count($arr); $kk++) {
echo $id_val13 = $arr[$kk];
$basicUrl = $this->config->item("basicUrl");
$basicUrl['bread_crumb'] = $this->breadcrumb();
$query = $this->db->query("SELECT aa.id as id,customer_type_id,start_time,close_time,dd.name as customer_name,bb.name as vehicle_name,cc.name as driver_name,other_expensive,depature_city,destination_city,journey_status,payment,tour_file,DATE_FORMAT(aa.created_date, '%d/%m/%Y') as created_date FROM " . $this->tbl . " as aa
left join vehicle as bb on aa.vehicle_id=bb.id
left join driver as cc on aa.driver_id=cc.id
left join tbl_customer as dd on aa.customer_id=dd.id
WHERE aa.id = $id_val13");
$result = array();
if ($query->num_rows()) {
$i = 1;
foreach ($query->result() as $row) {
$result_row = array();
$result_row[] = '<input type="checkbox" name="chk_id" id="chk_id" value="' . $row->id . '" />';
$result_row[] = $row->id;
$result_row[] = $row->customer_name;
if ($row->customer_type_id == "1")
$result_row[] = "Tour";
else if ($row->customer_type_id == "2")
$result_row[] = "Company";
else if ($row->customer_type_id == "3")
$result_row[] = "Guest";
$result_row[] = $row->driver_name;
$result_row[] = $row->vehicle_name;
$result_row[] = $row->destination_city;
$result_row[] = $row->start_time;
$result_row[] = $row->close_time;
$result_row[] = $row->payment;
$result_row[] = $row->other_expensive;
$result_row[] = $row->journey_status == "1" ? "Complete" : "On Progress";
if ($row->tour_file != "") {
$result_row[] = '' . $row->tour_file . '';
} else {
$result_row[] = "No File";
}
$result_row[] = $row->created_date;
$action_btn = action_button("Edit", $row->id) . action_button("Delete", $row->id) . action_button("Select", $row->id);
$result_row[] = $action_btn;
$result[] = $result_row;
$i++;
}
}
}
$tbl_header = array(
"",
"S NO",
"Customer Name",
"Type",
"Driver Name",
'Vehicle Name',
"Destination City",
"Start Time",
"Close Time",
"Rupee",
"Other Expensive",
"Journey Status",
"Itinerary",
"Created Date",
array(
"Edit",
"Delete"
)
);
$basicUrl['table'] = $this->makeTable($result, $tbl_header, $bool = TRUE);
$this->parser->parse("admin/center", $basicUrl);
?>
For example:
$array = array("1","2","6");
Normally using explode() and for loop, it display all the values. When I use select query using CodeIgniter, it displays the last row only.

Try this (I have defined $result before for loop) Also this is not a good practice to use your code like this use controller and models to do all the logical and database work....
<?php
$id = $this->uri->segment(4);
$arr = explode(',', $id);
$result=array();
for ($kk = 0; $kk < count($arr); $kk++)
{
echo $id_val13 = $arr[$kk];
$basicUrl = $this->config->item("basicUrl");
$basicUrl['bread_crumb'] = $this->breadcrumb();
$query=$this->db->query("SELECT aa.id as id,customer_type_id,start_time,close_time,dd.name as customer_name,bb.name as vehicle_name,cc.name as driver_name,other_expensive,depature_city,destination_city,journey_status,payment,tour_file,DATE_FORMAT(aa.created_date, '%d/%m/%Y') as created_date FROM ".$this->tbl." as aa
left join vehicle as bb on aa.vehicle_id=bb.id
left join driver as cc on aa.driver_id=cc.id
left join tbl_customer as dd on aa.customer_id=dd.id
WHERE aa.id = $id_val13");
if($query->num_rows()){
$i=1;
foreach($query->result() as $row){
$result_row=array();
$result_row[]='<input type="checkbox" name="chk_id" id="chk_id" value="'.$row->id.'" />';
$result_row[]=$row->id;
$result_row[]=$row->customer_name;
if($row->customer_type_id=="1")
$result_row[]="Tour";
else if($row->customer_type_id=="2")
$result_row[]="Company";
else if($row->customer_type_id=="3")
$result_row[]="Guest";
$result_row[]=$row->driver_name;
$result_row[]=$row->vehicle_name;
$result_row[]=$row->destination_city;
$result_row[]=$row->start_time;
$result_row[]=$row->close_time;
$result_row[]=$row->payment;
$result_row[]=$row->other_expensive;
$result_row[]=$row->journey_status=="1" ? "Complete" : "On Progress";
if($row->tour_file!="")
{
$result_row[]=''.$row->tour_file.'';
}
else
{
$result_row[]="No File";
}
$result_row[]=$row->created_date;
$action_btn=action_button("Edit",$row->id).action_button("Delete",$row->id).action_button("Select",$row->id);
$result_row[]=$action_btn;
$result[]=$result_row;
$i++;
}
}
}
$tbl_header=array("","S NO","Customer Name","Type","Driver Name",'Vehicle Name',"Destination City","Start Time","Close Time","Rupee","Other Expensive","Journey Status","Itinerary","Created Date",array("Edit","Delete"));
$basicUrl['table']=$this->makeTable($result,$tbl_header,$bool=TRUE);
$this->parser->parse("admin/center",$basicUrl);
?>

Related

Multiple nested array from MySQL query in PHP

I'm using foreach loops to access records in a nested array.
I need to nest 3 arrays (so the first array contains an array, which also contains an array). I'm having success with 2 arrays but I can't get 3 to work.
I had my code working with 2 arrays (which worked just fine) but I can't get 3 arrays to be nested.
This is the result that I want:
[
{
"site_id": "1",
"user_plants": [
{
"user_plant_id": "1",
"site_id": "1",
"plant_id": "1",
"plant_images": [
{
"plant_image_id": "1"
},
{
"plant_image_id": "2"
},
{
"plant_image_id": "3"
},
]
}
]
}
]
My current code:
$query = "SELECT A.site_id FROM sites A WHERE A.user_id='".$user_id."' GROUP BY A.site_id";
$result = $this->conn->query($query);
$json_response = array();
$sites = array();
if ($result-> num_rows > 0) {
while ($item = $result->fetch_object())
$sites[] = $item;
foreach($sites as $item) {
$row_array = (array)$item;
$site_id = $item->site_id;
$user_plants = "SELECT A.user_plant_id, A.site_id, A.plant_id FROM user_plants A RIGHT JOIN sites B ON A.site_id ='".$site_id."'
JOIN plants C ON A.plant_id = C.plant_id GROUP BY A.user_plant_id";
$resultSet = $this->conn->query($user_plants);
$user_plants = array();
if ($resultSet-> num_rows > 0) {
while ($item = $resultSet->fetch_object())
$user_plants[] = $item;
foreach ($user_plants as $item) {
$row_array['user_plants'][] = (array)$item;
$plant_id = $item->plant_id;
$user_plant_id = $item->user_plant_id;
$plant_images = "SELECT A.plant_image_id FROM plants_images A WHERE A.plant_id ='".$plant_id."' UNION SELECT B.plant_image_id FROM user_plant_image B JOIN user_plants C ON B.user_plant_id ='".$user_plant_id."' WHERE C.user_id ='".$user_id."' GROUP BY B.plant_image_id ORDER BY plant_image_id";
$resultSet = $this->conn->query($plant_images);
$plant_images = array();
if ($resultSet->num_rows > 0) {
while ($item = $resultSet->fetch_object())
$plant_images[] = $item;
foreach ($plant_images as $item) {
$row_array['user_plants'][]['plant_images'][] = $item;
}
} else if ($resultSet->num_rows == 0) {
$row_array['plant_images'] = [];
}
}
$json_response[] = $row_array;
}
}
}
return $json_response;
The result of above code:
[
{
"site_id": "1",
"user_plants": [
{
"user_plant_id": "1",
"site_id": "1",
"plant_id": "1"
},
{
"plant_images": [
{
"plant_image_id": "1"
},
{
"plant_image_id": "2"
},
{
"plant_image_id": "3"
},
]
}
]
}
]
How should I adjust the foreach loops above to cater for this?
There's plenty of room for improvement in this code but I've ignored that and tried to keep the code matching yours in this example.
The main changes are:
Create a temporary variable $user_plant_array which we store "plant_images" against
Push that temporary variable to the $site_array at the end of the loop
Rename some loop variables to making it easier to identify what you're referencing
$json_response = array();
$sites = array();
if ($result->num_rows > 0) {
while ($site = $result->fetch_object()) {
$sites[] = $site;
}
foreach ($sites as $site) {
$site_array = (array)$site;
$site_id = $site->site_id;
$user_plants = "SELECT A.user_plant_id, A.site_id, A.plant_id FROM user_plants A RIGHT JOIN sites B ON A.site_id ='" . $site_id . "'
JOIN plants C ON A.plant_id = C.plant_id GROUP BY A.user_plant_id";
$resultSet = $this->conn->query($user_plants);
$user_plants = array();
if ($resultSet->num_rows > 0) {
while ($user_plant = $resultSet->fetch_object())
$user_plants[] = $user_plant;
foreach ($user_plants as $user_plant) {
// create a temporary variable here that we will map
// all "plant_images" to
$user_plant_array = (array)$user_plant;
$plant_id = $user_plant->plant_id;
$user_plant_id = $user_plant->user_plant_id;
$plant_images = "SELECT A.plant_image_id FROM plants_images A WHERE A.plant_id ='" . $plant_id . "' UNION SELECT B.plant_image_id FROM user_plant_image B JOIN user_plants C ON B.user_plant_id ='" . $user_plant_id . "' WHERE C.user_id ='" . $user_id . "' GROUP BY B.plant_image_id ORDER BY plant_image_id";
$resultSet = $this->conn->query($plant_images);
$plant_images = array();
if ($resultSet->num_rows > 0) {
while ($plant_image = $resultSet->fetch_object())
$plant_images[] = $plant_image;
foreach ($plant_images as $plant_image) {
$user_plant_array['plant_images'][] = $plant_image;
}
} else if ($resultSet->num_rows == 0) {
$user_plant_array['plant_images'] = [];
}
// the temporary variable now contains all "plant_images"
// now we can push that to the site array
$site_array['user_plants'][] = $user_plant_array;
}
$json_response[] = $site_array;
}
}
}
return $json_response;
Creating a separate answer as an alternate solution with some code improvements.
"Improvements" being more readability and/or more performant.
A few of the main changes I would suggest as "improvements" have been implemented in this example. The main ones being:
Using prepared SQL statements (not always required but good practice to use, especially in anything accepting user input, also can make for cleaner code)
Reducing the amount of loops (in a few places you were looping just to create an array and then looping again)
Returning/continuing early where possible (helps to prevent unnecessary nesting)
Removing unnecessary if statements (e.g. most of the while loops will be skipped if the results are empty - checking beforehand isn't entirely necessary)
More readable variable names (it's common for new coders to try and abbreviate a lot of variables and often take it too far - making them readable will save you a lot of time when debugging)
The code using mysqli might not be the best as I generally work with PDO.
function getSitesData() {
// assumes that $user_id is set somewhere before this
// assumes that $this->conn references a valid database connection
$sql = "SELECT A.site_id FROM sites A WHERE A.user_id = ? GROUP BY A.site_id";
$query = $this->conn->prepare($sql);
$query->bind_param("i", $user_id);
$query->execute();
$site_result = $query->get_result();
$sites = [];
while ($site = $site_result->fetch_assoc()) {
// using fetch_assoc gives us an associative array
// initialise empty array
$site["user_plants"] = [];
// get user_plants
$sql = "SELECT A.user_plant_id, A.site_id, A.plant_id FROM user_plants A RIGHT JOIN sites B ON A.site_id = ?
JOIN plants C ON A.plant_id = C.plant_id GROUP BY A.user_plant_id";
$query = $this->conn->prepare($sql);
$query->bind_param("i", $site["site_id"]);
$query->execute();
$user_plant_result = $query->get_result();
while ($user_plant = $user_plant_result->fetch_assoc()) {
// intialise empty array
$user_plant["plant_images"] = [];
// get plant images
$sql = "SELECT A.plant_image_id FROM plants_images A WHERE A.plant_id = ? UNION SELECT B.plant_image_id FROM user_plant_image B JOIN user_plants C ON B.user_plant_id = ? WHERE C.user_id = ? GROUP BY B.plant_image_id ORDER BY plant_image_id";
$query = $this->conn->prepare($sql);
$query->bind_param("iii", $user_plant["plant_id"], $user_plant["user_plant_id"], $user_id);
$query->execute();
$plant_image_result = $query->get_result();
while ($plant_image = $plant_image_result->fetch_assoc()) {
$user_plant["plant_images"][] = $plant_image;
}
$sites["user_plants"][] = $user_plant;
}
$sites[] = $site;
}
return $sites;
}

display only if has group of numbers

I need to return list with prices only if there have groups i try already if else empty not !=
nothing help any suggestions ?
$usergroups = '11,9,10';
if (empty($usergroups)) {
return;
}
$fields = 'MIN(IF(prices.percentage_discount = 0, prices.price, prices.price - (prices.price * prices.percentage_discount)/100)) as price, prices.usergroup_id as usergroup_id, ud.usergroup as usergroup_name';
$condition = db_quote(' prices.product_id = ?i AND prices.usergroup_id IN (?p) AND ud.lang_code = ?s', $product['product_id'], $usergroups, DESCR_SL);
$group_by = 'usergroup_id';
$join = '?:usergroup_descriptions as ud ON ud.usergroup_id = prices.usergroup_id';
$opt_prices = db_get_array("SELECT ?p FROM ?:product_prices as prices LEFT JOIN ?p WHERE ?p GROUP BY ?p", $fields, $join, $condition, $group_by);
$currencies = Registry::get('currencies');
foreach ($opt_prices as &$price) {
$price['current'] = 0;
if (in_array($price['usergroup_id'], $auth['usergroup_ids'])) {
$price['current'] = 1;
$product['price'] = $price['price'];
}
$price['price'] = number_format($price['price'], 2, '.', ' ') . ' $';
}
$product['group_discounts'] = $opt_prices;
}
So i want display $product['group_discounts'] = $opt_prices;
only if there is $usergroups = '11,9,10';
Answer your comment:
You used that but ok here an example :
<?php
$usergroups = array('11','9','10');
$opt_prices='11';
if (in_array($opt_prices,$usergroups)){
echo 'yes';
}else{
echo 'no';
}
?>

Ambiguous column in Codeigniter Datatables server side

I'm working on a system that has several server-side datatables but i facing issues with 2 joins when i try to order de columns.
I receive the following message when try to sort the columns:
Query error: Column 'notes' in order clause is ambiguous - Invalid query: SELECT *
FROM `tbl_project`
LEFT JOIN `tbl_client` ON `tbl_project`.`client_id`=`tbl_client`.`client_id`
LEFT JOIN `tbl_account_details` ON `tbl_project`.`created_by` = `tbl_account_details`.`user_id`
LEFT JOIN `tbl_notes` ON `tbl_project`.`notes` = `tbl_notes`.`notes_id`
WHERE `tbl_project`.`client_id` = '100'
ORDER BY `notes` DESC
LIMIT 10
This is the code with my query:
$id = $this->input->post("client_id");
$client_details = get_row('tbl_client', array('client_id' => $id));
$draw = intval($this->input->post("draw"));
$start = intval($this->input->post("start"));
$length = intval($this->input->post("length"));
$order = $this->input->post("order");
$search= $this->input->post("search");
$search = $search['value'];
$col = 0;
$dir = "";
if(!empty($order))
{
foreach($order as $o)
{
$col = $o['column'];
$dir= $o['dir'];
}
}
if($dir != "desc" && $dir != "desc")
{
$dir = "desc";
}
$valid_columns = array(
0=>'project_id',
1=>'client',
2=>'fullname',
3=>'notes',
4=>'origen',
5=>'end_date',
6=>'project_status',
7=>'action',
);
if(!isset($valid_columns[$col]))
{
$order = null;
}
else
{
$order = $valid_columns[$col];
}
if($order !=null)
{
$this->db->order_by($order, $dir);
}
$searchQuery = "";
if($search != ''){
$searchQuery = " (tbl_project.project_id like'%".$search."%' OR tbl_project.end_date like'%".$search."%' OR tbl_project.project_status like'%".$search."%' OR tbl_notes.notes like'%".$search."%' OR tbl_notes.eco like'%".$search."%' OR tbl_account_details.origen like'%".$search."%' OR tbl_client.name like'%".$search."%') ";
}
$this->db->select('*');
$this->db->from('tbl_project');
$this->db->join('tbl_client', 'tbl_project.client_id=tbl_client.client_id','left');
$this->db->join('tbl_account_details', 'tbl_project.created_by = tbl_account_details.user_id','left');
$this->db->join('tbl_notes', 'tbl_project.notes = tbl_notes.notes_id','left');
$this->db->where('tbl_project.client_id', $client_details->client_id);
if($searchQuery != '')
$this->db->where($searchQuery);
$this->db->limit($length,$start);
$cita = $this->db->get()->result();
For some reason the ORDER BY is not set as tbl_notes.notes
Any suggestion on how to fix this?
Thanks in advance
EDIT: i have added more code so there is more visibility of the process
The error occurs, because your column name is not unique, it exists in more than one table.
append the table name of the searched column to your query to make it unique:
for example in this line:
$this->db->order_by('my_table_name.'.$order, $dir);
that would generate something like
ORDER BY `my_table_name.notes` DESC
edit: or in case you have to address columns from several different tables you could change your $valid_columns array:
$valid_columns = array(
0=>'my_table_name1.project_id',
1=>'my_table_name2.client',
2=>'my_table_name2.fullname',
3=>'my_table_name3.notes',
// etc.
);
and maintain the remaining original code.

php mysql and in_array performance

Is there anything to get more performance? Because it tooks about 8 secs. car_models database has over 100.000 records, cars database has over 20.000 records and finaly car_parts has over 20.000 records. I could do for that a database something like keywords. But the problem is the databases are dynamic. I mean the records adding everyday by editors. And I can't touch the part of the software because it is not open source...
$news = dbquery("SELECT * FROM " . DB_NEWS . " ORDER BY news_id DESC LIMIT 0,1");
while ($news_data = dbarray($news))
{
echo $news_data['news_subject'];
$news_first_part = str_replace("\\", "", $news_data['news_news']);
$news_first_part = explode('.', $news_first_part); //first phrase
$news_first_part = $news_first_part[0];
$news_second_part = str_replace("\\", "", $news_data['news_extended']);
$find = array();
$keywords = dbquery("SELECT name FROM cars GROUP BY name");
while ($keywords_data = dbarray($keywords))
{
$my_keyword = $keywords_data['name'];
$news_first_part = str_replace($my_keyword, "<a href='keyword.php?keyword=$my_keyword' title='$my_keyword'>$my_keyword</a>", $news_first_part);
$news_second_part = str_replace($my_keyword, "<a href='keyword.php?keyword=$my_keyword' title='$my_keyword'>$my_keyword</a>", $news_second_part);
if ($news_first_part OR $news_second_part AND !in_array($my_keyword, $find,true))
{
array_push($find, $my_keyword);
}
}
$my_keyword="";
$keywords = dbquery("SELECT name FROM car_models GROUP BY name");
while ($keywords_data = dbarray($keywords))
{
$my_keyword = $keywords_data['name'];
if (strlen($my_keyword) > 10 && !in_array($my_keyword, $find, true))
{
$news_first_part = str_replace($my_keyword, "<a href='keyword.php?keyword=$my_keyword' title='$my_keyword'>$my_keyword</a>", $news_first_part);
$news_second_part = str_replace($my_keyword, "<a href='keyword.php?keyword=$my_keyword' title='$my_keyword'>$my_keyword</a>", $news_second_part);
}
}
$keywords = dbquery("SELECT name FROM car_parts GROUP BY name");
while ($keywords_data = dbarray($keywords))
{
$my_keyword = $keywords_data['name'];
if (strlen($my_keyword) > 10)
{
$news_first_part = str_replace($my_keyword, "<a href='keyword.php?keyword=$my_keyword' title='$my_keyword'>$my_keyword</a>", $news_first_part);
$news_second_part = str_replace($my_keyword, "<a href='keyword.php?keyword=$my_keyword' title='$my_keyword'>$my_keyword</a>", $news_second_part);
}
}
$my_keyword="";
echo $news_first_part . '.'; //note I added the final ponctuation
$news_first_part .= ".";
$news_second_part = str_replace($news_first_part, "", $news_second_part);
echo nl2br($news_second_part);
}
You could build some kind of array tree-structure, to limit the size of the sub-arrays. The array would then become:
$arr['a']['apple'];
$arr['a']['anna'];
$arr['a']['awesome'];
$arr['b']['bread'];
$arr['b']['beer'];
$arr['c']['cucumber'];
Instead of
$arr['apple'];
$arr['anna'];
$arr['awesome'];
$arr['bread'];
$arr['beer'];
$arr['cucumber'];
As you can see, an in_array would become lots faster.
If we would like to check "php", there is no array for the first-letter "p": nothing has to be walked through again
If we would like to check "ananas", we would have to lookup 3 items, instead of 6!
Note: the "outer" array could consist of the 1st letter (or 2, 3, 4, etc.) depending on the size of your set.
In PHP code you would get something like
$word = "ananas";
$arr = array();
if (!isset($arr[$word{0}]) || !in_array($word, $arr[$word{0})) {
// New word
if (!isset($arr[$word{0}])) {
$arr[$word{0}] = array($word);
} else {
$arr[$word{0}][] = $word;
}
}
Try it this way, it is much faster.
if ($news_first_part OR $news_second_part AND !isset($find[$my_keyword]))
{
$find[$my_keyword] = 1;
}
Update the rest of the code correspondingly. Actually, you do not need to use a !isset($find[$my_keyword]) check here.

How can I load the title of parent item in Drupal

I want to extend Nodes with the title of the parentnode so I can display a hierarchy link.
I have a solution that sometimes works:
function modulename_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL)
{
switch ($op)
{
case 'view':
loadParentTitle($node);
break;
}
}
function loadParentTitle(&$node)
{
$title = $node->title;
$query = "SELECT mlid, p1, p2,p4,p5,p6,p7,p8,p9 FROM menu_links WHERE link_title like '%%%s%%'";
$data = db_fetch_array(db_query($query, $title));
$mlid = $data["mlid"];
$i = 9;
while (($data["p". $i] == 0 || $data["p". $i] == $mlid) && $i >= 0)
{
$i--;
}
if ($i > 0)
{
$query = "SELECT `link_title` as parentTitle from `menu_links` WHERE mlid = " . $data["p" . $i];
$data = db_fetch_array(db_query($query));
$parentTitle = ($data["parentTitle"]);
}
else
{
$parentTitle = $title;
}
$node->content['#parentTitle'] = $parentTitle;
}
This works as long as the title of the item is the same as the Menu Title. However i'm looking for a solution that will work all the time. Any ideas?
You did not specify really what do you mean by 'parent node' but the mlid of the parent of a menu link is stored in menu_links.plid. Now, the link_path is going to be node/nid and you can fetch the title from there.
$mlid = db_result(db_query("SELECT plid FROM {menu_links} WHERE link_path = 'node/%d'", $node->nid));
$link_path = db_result(db_query("SELECT link_path FROM {menu_links} WHERE mlid = %d", $mlid));
$title = db_result(db_query("SELECT title FROM {node} WHERE nid = %d", substr($link_path, 5));
The first two queries can be unified by a JOIN but I strongly recommend against getting the third in there too (you can with CONCAT('node/', nid) = parent.link_path) because that is not going to be indexable. These three queries should be practically instant.
P.S. You won't forget to check_plain($title) before printing, would you? :)

Categories