Retrieving all posts from db with a certrain id - php

I'm want to retrieve all posts with a certain listId from the database, but only retrieves the last one. Below is the code, what am I doing wrong?
from listModel.php:
public function GetListElements($listId) {
$query = "SELECT le.listElemId, le.listElemName, le.listElemOrderPlace, led.listElemDesc
FROM listElement AS le
INNER JOIN listElemDesc as led
ON le.listElemId = led.listElemId
WHERE le.listId=?";
$stmt = $this->m_db->Prepare($query);
$stmt->bind_param("i", $listId);
$listElements = $this->m_db->GetListElements($stmt);
return $listElements;
}
from database.php:
public function GetListElements(\mysqli_stmt $stmt) {
if ($stmt === FALSE) {
throw new \Exception($this->mysqli->error);
}
//execute the statement
if ($stmt->execute() == FALSE) {
throw new \Exception($this->mysqli->error);
}
//Bind the $ret parameter so when we call fetch it gets its value
if ($stmt->bind_result($listElemId, $listElemName, $listElemOrderPlace, $listElemDesc) == FALSE) {
throw new \Exception($this->mysqli->error);
}
// Hämtar ids och användarnamn och lägger i arrayen.
while ($stmt->fetch()) {
$listElements = array('listElemId' => $listElemId,
'listElemName' => $listElemName,
'listElemOrderPlace' => $listElemOrderPlace,
'listElemDesc' => $listElemDesc);
}
$stmt->Close();
return $listElements; // contains only the last post in the table
}
The tables
listElement: listElemId, listElemName, listId, listElemDescId, listElemOrderPlace
listElemDesc: listElemDescId, listElemId, listElemDesc

You are overwriting $listElements variable on each iteration, to fix it you can use an array variable:
$listElements = array();
while ($stmt->fetch()) {
$listElements[] = array('listElemId' => $listElemId, //notice brackets: []
'listElemName' => $listElemName,
'listElemOrderPlace' => $listElemOrderPlace,
'listElemDesc' => $listElemDesc);

Related

MVC Query doesn't fetch all records from the database

The DB stores several accounts: [winnie, winnie9, winnie10], however the query only returns one record when I fetch the data. What would be the solution?
Model method:
protected function getApprovedUsers($login) {
$sql = "SELECT `email`, `login`, `name`, `reg_date`, `pass`, `role` FROM `approved` WHERE `login` LIKE ?";
$stmt = $this->connect()->prepare($sql);
$stmt->execute([$login]);
if($users = $stmt->fetchAll())
return $users;
return null;
}
Controller call to the Model:
public function getCertainApprovedUser($login) {
$users = $this->getApprovedUsers($login);
if(is_array($users) || is_object($users)) {
foreach ($users as $user) {
return array("email"=>$user["email"], "login"=>$user["login"], "pass"=> $user["pass"],
"name"=> $user["name"], "reg_date"=> $user["reg_date"], "role"=> $user["role"]);
}
}
else {
throw new Exception("Nothing to fetch");
}
}
}
Processing the data so that LIKE statement would work properly (%%):
$record = $userContr->getCertainApprovedUser("%$login%");
$someJSON = array(
[
"login"=>"{$record['login']}",
"email"=>"{$record['email']}",
"name"=>"{$record['name']}",
"reg_date"=>"{$record['reg_date']}"
]
);
$newJSON = json_encode($someJSON);
echo $newJSON;
in the method getCertainApprovedUser(), you are returning a value in the foreach. This breaks immediatly the loop at the first iteration.
Changes your loop to something like :
$result = []; // initialize an empty array
foreach ($users as $user) {
// add a user to that array
$result[] = array("email"=>$user["email"], "login"=>$user["login"], "pass"=> $user["pass"], "name"=> $user["name"], "reg_date"=> $user["reg_date"], "role"=> $user["role"]);
}
// return the array containing the users
return $result;
And then, to build your json, apply the same logic :
$someJSON = [];
foreach ($record as $user)
{
$someJSON[] = [
"login"=>$user['login'],
"email"=>$user['email'],
"name"=>$user['name'],
"reg_date"=>$user['reg_date']
];
}

How to Loop through query result and compare results with input field

I want to loop through the results of a query and then compare each results to an input field, if the value is repeated it must return false if not the result is true, I know that I could use unique index in database to avoid repeated values and then catch the error, but in this case repeated values are possible but they can´t both be "active" there a column called "status" with two values A or I (active and inactive) so "clabe" value can be repeated only when one is active and the other inactive.
Controller:
function agregar()
{
$this->load->helper('date');
date_default_timezone_set('America/Mexico_City');
$now = date('Y-m-d H:i:s');
$Interno = $this->input->post('intern');
$clabe = $this->input->post('clabe2') . $this->input->post('control2');
$cve_banco = $this->input->post('cve_banco');
$Banco = $this->input->post('Banco2');
$Observaciones = $this->input->post('Observaciones');
$data = array(
'Interno' => $Interno,
'clabe' => $clabe,
'cve_banco' => $cve_banco,
'Banco' => $Banco,
'Observaciones' => $Observaciones,
'Fecha_alta' => $now,
);
if($this->consultas_M->insert($data) == true){
//redirect('Inicio/busqueda', 'refresh');
} else{
echo "Hubo un problema al insertar";
}
}
Model:
function insert($data)
{
$clabe = $this->input->post('clabe2') . $this->input->post('control2');
$this->db->select('Clabe');
$this->db->where('Status =', 'A');
$query= $this->db ->get('cuentas');
return $query->row();
foreach ($query as $row) {
$i = $row;
if ($clabe = $i) {
return false;
} else {
$this-> db -> insert('cuentas', $data);
if ($this->db->affected_rows() > 0) {
return true;
}
}
}
}
Why would you want to have possible duplicated index ? If you want to have different rows with a common "index" for some reason you can create a column called index or something and add in your WHERE clause that index.
PS: in your model in the foreach loop's if condition use :
if ($clabe == $row){...
instead of
$i = $row
if ($clabe = $i){...
I solved myself the issue, i´m posting in in case it helps anybody, it was easier than I thought.
function insert($data, $clabe)
{
$Status = 'A';
$clabe = $this->input->post('clabe2') . $this->input->post('control2');
$this->db->select('Clabe');
$this->db->where('Status =', $Status);
$this->db->where('Clabe =', $clabe);
$q= $this->db ->get('cuentas');
if($q -> num_rows() > 0){
return false;
}else{
$this-> db -> insert('cuentas', $data);
return true;
}
And this is the controller:
if($this->consultas_M->insert($data, $clabe) == true){
redirect('Inicio/busqueda', 'refresh');
} else{
echo "There was a problem";
$this->load->view('errors/error');
}
The only thing I needed and wasn´t doing was to select the "clabe" I wanted and then compare it with the input where user writes this "clabe". And then just a simple if-else statement.
function insert($data)
{
$Status = 'A';
$clabe = $this->input->post('clabe2') . $this->input->post('control2');
$this->db->select('Clabe');
$this->db->where('Status', $Status);
$query= $this->db ->get('cuentas');
$flag=true;
foreach ($query as $row) {
$i = $row;
if ($clabe = $i){
$flag=false;
}
}
if($flag){
$this-> db -> insert('cuentas', $data);
if ($this->db->affected_rows() > 0) {
$flag= true;
}
}
return $flag;
}
Your code will add it on first else block ad return. Instead it should check all the rows first to decide.

PHP Improve performance to execute multiple queries while reading a file with thousand lines

I'm trying to build a script where I need to read a txt file and execute some process with the lines on the file. For example, I need to check if the ID exists, if the information has updated, if yes, then update the current table, if no, then insert a new row on another temporary table to be manually checked later.
These files may contain more than 20,30 thousand lines.
When I just read the file and print some dummie content from the lines, it takes up to 40-50ms. However, when I need to connect to the database to do all those verifications, it stops before the end due to the timeout.
This is what I'm doing so far:
$handle = fopen($path, "r") or die("Couldn't get handle");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$segment = explode('|', $buffer);
if ( strlen($segment[0]) > 6 ) {
$param = [':code' => intval($segment[0])];
$codeObj = Sql::exec("SELECT value FROM product WHERE code = :code", $param);
if ( !$codeObj ) {
$param = [
':code' => $segment[0],
':name' => $segment[1],
':value' => $segment[2],
];
Sql::exec("INSERT INTO product_tmp (code, name, value) VALUES (:code, :name, :value)", $param);
} else {
if ( $codeObj->value !== $segment[2] ) {
$param = [
':code' => $segment[0],
':value' => $segment[2],
];
Sql::exec("UPDATE product SET value = :value WHERE code = :code", $param);
}
}
}
}
fclose($handle);
}
And this is my Sql Class to connect with PDO and execute the query:
public static function exec($sql, $param = null) {
try {
$conn = new PDO('mysql:charset=utf8mb4;host= '....'); // I've just deleted the information to connect to the database (password, user, etc.)
$q = $conn->prepare($sql);
if ( isset($param) ) {
foreach ($param as $key => $value) {
$$key = $value;
$q->bindParam($key, $$key);
}
}
$q->execute();
$response = $q->fetchAll();
if ( count($response) ) return $response;
return false;
} catch(PDOException $e) {
return 'ERROR: ' . $e->getMessage();
}
}
As you can see, each query I do through Sql::exec(), is openning a new connection. I don't know if this may be the cause of such a delay on the process, because when I don't do any Sql query, the script run within ms.
Or what other part of the code may be causing this problem?
First of all, make your function like this,
to avoid multiple connects and also o get rid of useless code.
public static function getPDO() {
if (!static::$conn) {
static::$conn = new PDO('mysql:charset=utf8mb4;host= ....');
}
return static::$conn;
}
public static function exec($sql, $param = null) {
$q = static::getPDO()->prepare($sql);
$q->execute($param);
return $q;
}
then create unique index for the code field
then use a single INSERT ... ON DUPLICATE KEY UPDATE query instead of your thrree queries
you may also want to wrap your inserts in a transaction, it may speed up the inserts up to 70 times.

Array execute in php if empty pdo php [duplicate]

This question already has answers here:
PHP PDO Insert Using Loop
(2 answers)
Closed 5 months ago.
foreach($parentinfojson as $value) {
if (!empty($parentinfojson )) {
$stmt2 = $dbh -> prepare("INSERT INTO parentinfo (last_name,first_name,status) VALUES (:lastname,:firstname,:status)");
$stmt2_ = $stmt2 -> execute(array(':firstname' => $value['firstname'], ':lastname' => $value['lastname'], ':status' => $status));
} else {
$stmt2_ = $stmt2 -> execute();
}
}
if ($stmt2_ && $stmt3_ && $stmt1_ && $stmt_ && $stmt5_ && $stmt4_) {
echo json_encode(array(
'error' => false,
'message' => "Added"
));
}
This is my execute in Inserting new data in the table. When i tested the adding of empty data(parentinfojson is empty) i get error that Notice: Undefined variable: stmt2_. What i did is i added an else statement and i initialize the variable still i get error. I tried to echo something in the else statement as well but i get error. Now I run out of idea on how to initialize the variable when the json is empty so that i dont get the error undefined variable
You just defined $stmt2 inside the loop, if $parentinfojson is empty it'll certainly get undefined. Why not define/initialize it.
// initialize up top
$stmt_ = $stmt1_ = $stmt2_ = $stmt3_ = $stmt4_ = $stmt5_ = false;
$stmt2 = $dbh->prepare("INSERT INTO parentinfo (last_name,first_name,status) VALUES (:lastname,:firstname,:status)");
foreach($parentinfojson as $value) {
$stmt2_ = $stmt2->execute(array(
':firstname' => $value['firstname'],
':lastname' => $value['lastname'],
':status' => $status
));
}
if ($stmt2_ && $stmt3_ && $stmt1_ && $stmt_ && $stmt5_ && $stmt4_) {
echo json_encode(array(
'error' => false,
'message' => "Added"
));
}
Sidenote: Another way would be to build the query dynamically, including the placeholders and the values. So that in turn, you don't have to loop each batches of insert but instead, creating the SQL batch insert then binding all of the values into one single insert invocation:
$stmt_ = $stmt1_ = $stmt2_ = $stmt3_ = $stmt4_ = $stmt5_ = false;
if(!empty($parentinfojson)) {
$base_query = 'INSERT INTO parentinfo (last_name, first_name, status) VALUES ';
$placeholders = implode(',', array_map(function($batch){
return '(' . implode(',', array_fill(0, count($batch), '?')) . ')';
}, $parentinfojson));
$base_query .= $placeholders;
$parentinfojson = call_user_func_array('array_merge', array_map('array_values', $parentinfojson));
$stmt2 = $dbh->prepare($base_query);
$stmt2_-> $stmt2->execute($parentinfojson);
}
There might be a chance that the json variable you are receiving is not empty, so you should also add a check for valid json, this is the function to check a valid json
function isJson($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}

insert array element into database

I have this function : it's work correctly,
function ms_get_did_detail($id) {
global $link;
$q2="select Dest,Priority from destpr where Id='$id'";
if($res2=mssql_query($q2)) {
while($row2[]=mssql_fetch_array($res2,MSSQL_ASSOC)) {
return $row2;
}
return 0;
}
return 0;
}
I want insert every element (every Dest & Priority) into MYSQL
if($info=ms_get_did_detail($value)) {
print_r($info);
$destination = $info['Dest'];
$priority = $info['Priority'];
my_did_destination ($priority , $dest , $active , $did_voip , $cc_id);
}
It returns array like this :
[0]=> Array (
[Dest] => 100
[Priority] => 1
)
[1]=> Array (
[Dest] => 200
[Priority] => 3
)
[2] => (
)
also , I have this function to insert value in database :
function my_did_destination($priority="",$destination="") {
global $link_voip;
$sql="INSERT INTO cc_did_destination (destination,priority)
VALUES ('$destination','$priority')";
$retval = mysql_query( $sql , $link_voip);
if(! $retval ) {
die('Could not enter data: ' . mysql_error());
}
}
but It's insert empty value within
You are inserting all rows with an ID of 0, so, if a row with id=0 already exists, it will fail and will not be inserted.
Maybe the easiest solution would be to make yout ID column autoincrement with an SQL statement like:
ALTER TABLE cc_did_destination
MODIFY COLUMN id INT auto_increment;
And then change your INSERT statement for:
$sql="INSERT INTO cc_did_destination (destination,priority)
VALUES ('$destination','$priority')";
Your $info is array of rows, it has numeric keys, not 'Dest'.
You should add index, like $dest = $info[0]['Dest'].
if($info=ms_get_did_detail($value))
{
print_r($info);
$dest = $info[0]['Dest'];
$priority = $info[0]['Priority'];
my_did_destination ($priority , $dest , $active , $did_voip , $cc_id);
}
Or you can iterate through $info with a loop:
if($info=ms_get_did_detail($value))
{
foreach($info as $row) {
$dest = $row['Dest'];
$priority = $row['Priority'];
my_did_destination ($priority , $dest);
}
}
also, remove id from your insert statement
your array is:
[0]=> Array (
[Dest] => 100
[Priority] => 1
)
[1]=> Array (
[Dest] => 200
[Priority] => 3
)
[2] => (
)
so it is a multidimensional array. if you need to insert all those entries, you shouldn't run multiple queries for the same thing. just use mysql batch insert syntax. (e.g. INSERT INTO tbl (col1,col2,col3) VALUES(a,b,c),(d,e,f),(g,h,i))
build the query string for insert.
foreach($a as $i => $v)
{
$b[] = '("'.$v['Dest'].'","'.$v['Priority'].'")';
}
$c = implode(',', $b);
$sql = "INSERT INTO cc_did_destination (destination,priority)
VALUES ".$c;
then run the query
N.B.
Please, don't use mysql_* functions in new code. They are no longer maintained and are officially deprecated. See the red box? Learn about prepared statements instead, and use PDO or MySQLi - this article will help you decide which. If you choose PDO, here is a good tutorial.
There are a couple of issues here.
Firstly your first function returns an array of arrays. Ie, it returns an array with subscript 0 for the first row (it only ever returns one rows details), which is an array containing that rows details.
You assign this to the $info variable, so it contains:-
[0]=> Array (
[Dest] => 100
[Priority] => 1
)
You then assign $info['Dest'] to $destination and $info['Priority'] to $priority. However neither of these exist. You would need $info[0]['Dest'] and $info[0]['Priority'].
2nd issue is that you are trying to assign a specific value to the auto increment id field. Just leave it out of the insert, or give it a value of null.
Quick rewrite and I would suggest you need something like this:-
<?php
if($info=ms_get_did_detail($value))
{
print_r($info);
foreach($info AS $info_row)
{
$destination = $info_row['Dest'];
$priority = $info_row['Priority'];
my_did_destination ($priority , $dest , $active , $did_voip , $cc_id);
}
}
function ms_get_did_detail($id)
{
global $link;
$q2="select Dest,Priority from destpr where Id='$id'";
if($res2=mssql_query($q2))
{
if ($row2[]=mssql_fetch_array($res2,MSSQL_ASSOC))
{
while ($row2[]=mssql_fetch_array($res2,MSSQL_ASSOC))
{
}
return $row2;
}
else
{
return 0;
}
}
return 0;
}
function my_did_destination($priority="",$destination="")
{
global $link_voip;
$priority = mysql_real_escape_string($priority);
$destination = mysql_real_escape_string($destination);
$sql="INSERT INTO cc_did_destination (id,destination,priority) VALUES (NULL,'$destination','$priority')";
$retval = mysql_query( $sql , $link_voip);
if(! $retval )
{
die('Could not enter data: ' . mysql_error());
}
}
EDIT
If you want to avoid multiple inserts unnecessarily then it might be easier to use an object. This way you can do the inserts easily when there are enough batched up (I normally do 255 at a time).
Something like this, although you probably should use mysqli_*
<?php
if($info=ms_get_did_detail($value))
{
print_r($info);
$insert_object = new insert_details($link_voip);
foreach($info AS $info_row)
{
$insert_object->set_row($info_row['Priority'], $info_row['Dest']);
}
unset($insert_object);
}
function ms_get_did_detail($id)
{
global $link;
$q2="select Dest,Priority from destpr where Id='$id'";
if($res2=mssql_query($q2))
{
if ($row2[]=mssql_fetch_array($res2,MSSQL_ASSOC))
{
while ($row2[]=mssql_fetch_array($res2,MSSQL_ASSOC))
{
}
return $row2;
}
else
{
return 0;
}
}
return 0;
}
class insert_details()
{
private $db;
private $insert_row = array();
public function __CONSTRUCT($db)
{
$this->db = $db;
}
public function __DESTRUCT()
{
$this->do_insert();
}
public function set_row($priority="",$destination="")
{
$priority = mysql_real_escape_string($priority, $this->db);
$destination = mysql_real_escape_string($destination, $this->db);
$this->insert_row[] = "(NULL,'$destination','$priority')";
if (count($this->insert_row) > 255)
{
$this->do_insert();
}
}
private function do_insert()
{
$sql="INSERT INTO cc_did_destination (id,destination,priority) VALUES ".implode(',', $this->insert_row);
$retval = mysql_query($sql, $this->db);
if(! $retval )
{
die('Could not enter data: ' . mysql_error());
}
$this->insert_row = array();
}
}
Quick rough mysqli_* equivalent, assuming that $link_voip is a mysqli connection. Note that prepared statements with bound parameters are an option (and it makes it harder to forget to escape variables), but it can become a bit messy when you are doing multiple inserts like this.
<?php
if($info=ms_get_did_detail($value))
{
print_r($info);
$insert_object = new insert_details($link_voip);
foreach($info AS $info_row)
{
$insert_object->set_row($info_row['Priority'], $info_row['Dest']);
}
unset($insert_object);
}
function ms_get_did_detail($id)
{
global $link;
$q2="select Dest,Priority from destpr where Id='$id'";
if($res2=mssql_query($q2))
{
if ($row2[]=mssql_fetch_array($res2, MSSQL_ASSOC))
{
while ($row2[]=mssql_fetch_array($res2, MSSQL_ASSOC))
{
}
return $row2;
}
else
{
return 0;
}
}
return 0;
}
class insert_details()
{
private $db;
private $insert_row = array();
public function __CONSTRUCT($db)
{
$this->db = $db;
}
public function __DESTRUCT()
{
$this->do_insert();
}
public function set_row($priority="",$destination="")
{
$priority = mysqli_real_escape_string($this->db, $priority);
$destination = mysqli_real_escape_string($this->db, $destination);
$this->insert_row[] = "(NULL,'$destination','$priority')";
if (count($this->insert_row) > 255)
{
$this->do_insert();
}
}
private function do_insert()
{
$sql="INSERT INTO cc_did_destination (id,destination,priority) VALUES ".implode(',', $this->insert_row);
$retval = mysqli_query($this->db, $sql);
if(! $retval )
{
die('Could not enter data: ' . mysqli_sqlstate($this->db));
}
$this->insert_row = array();
}
}

Categories