WHMCS - Catch SQL errors - php

I am using WHMCS for managing the members of my website, and I am facing a problem with my sql queries.
Here is the logic of the code :
while(!$boolean && tries<10){
... CODE...
if($count==0)
{
$table = "name_of_table";
$value = array("field"=>"value", ...);
$newid = insert_query($table,$values);
$boolean = true;
break;
}
tries++;
}
if($boolean){
$table = "other_table";
$value = array("field"=>"value", ...);
$newid = insert_query($table,$values);
}
The problem is that the second query does not run.
I did a few verifications : the programs goes into the if(boolean) condition, but the insert_query inside of it returns the id.... of the previous query (the one in the loop) !
Does anyone have an idea of what is happening here ?

Related

Join multiple strings from php & sql foreach loop and return as 1 string

I'm trying to build a permission/action control system for my users.
There are 3 tables:
appName_actions:
appName_roles:
appName_roles_members:
There are 2 functions that will obtain the relevant data:
$memRoleIDs = AccessControl::get_memberRoleIDs($appName);
$memActionIDs = AccessControl::get_memberActionIDs($appName, $memRoleIDs);
get_memberRoleIDs works fine, it targets member 327 and returns the desired '2,4'
That is then passed to get_memberActionIDs as '2,4'
It's at this point I'm having trouble working out how to return all the actionIDs in one variable/string.
get_memberActionIDs:
public static function get_memberActionIDs($appName = NULL, $memRoleIDs = NULL)
{
if($appName !== NULL && $memRoleIDs !== NULL)
{
$tbl = 'app_'.$appName.'_roles';
$memRoleID = explode(',',$memRoleIDs);
foreach($memRoleID as $value)
{
$db = openDB();
$sql = $db->prepare("SELECT actionIDs FROM $tbl WHERE roleID = '$value'");
if(!$sql->execute())
{
logThis('ERROR_crit' , 'Database Query Failed !!!' , 1 , __FILE__ , __LINE__);
die('<h2>There was a critical error and data has not been loaded correctly. Developers have been notified.</h2><h3>Please try reloading the page</h3>');
}
else
{
// sql executed ok - bind fetch results
$sql->bind_result($actionID);
$sql->fetch();
print $actionID.'<br>';
}
}// return all the actionIDs as 1 variable here
}
}// end func
Now with this, there is success up-to-a-point. It prints out the correct info:
1,2,3,4
5
And this is where I cannot go any further :(
I've looked into GROUP_CONCAT and CONCAT in the SELECT statement and .= in the PHP loop, but I just cannot figure this out.
I'd like to return this as '1,2,3,4,5' all in 1 string.
If you could point me in the right direction I would be very grateful :)
Instead of printing out separate results, create a single string and print after the loop exits. You say you've tried this but you didn't include the relevant code to check if the implementation is correct. Is this what you did?
public static function get_memberActionIDs($appName = NULL, $memRoleIDs = NULL)
{
if($appName !== NULL && $memRoleIDs !== NULL)
{
$tbl = 'app_'.$appName.'_roles';
$memRoleID = explode(',',$memRoleIDs);
$result = "";
foreach($memRoleID as $value)
{
$db = openDB();
$sql = $db->prepare("SELECT actionIDs FROM $tbl WHERE roleID = '$value'");
if(!$sql->execute())
{
logThis('ERROR_crit' , 'Database Query Failed !!!' , 1 , __FILE__ , __LINE__);
die('<h2>There was a critical error and data has not been loaded correctly. Developers have been notified.</h2><h3>Please try reloading the page</h3>');
}
else
{
// sql executed ok - bind fetch results
$sql->bind_result($actionID);
$sql->fetch();
$result .= $actionID;
}
}// return all the actionIDs as 1 variable here
print $result.'<br>';
}
}// end func

Can I fetch multiple different SQL statements in one times loop? in PHP

I have to query SQL-SERVER's Query and MYSQL's Query (That have the same result format but it's difference database)
, But I want to call them in one while loop in PHP, Can I do that?
Ex.
$mssql_query = mssql_query(..mssql..);
$mysql_query = mysql_query(..mysql..);
while( $mssql_rs = mssql_fetch_assoc($mssql_query)|| $mysql_sql = mysql_fetch_assoc($mysql_query) )
{
..some action..
}
EDITED :
I just have an solved answer. It's work for me Idea from #Drew while(bContinue)
this my code
$mssql_query = mssql_query(..mssql..);
$mysql_query = mysql_query(..mysql..);
$continue = true;
while( $continue ){
$ms_rs = mssql_fetch_assoc($mssql_query);
$my_rs = mysql_fetch_assoc($mysql_query);
if($ms_rs){ ..some action.. }
if($my_rs ){ ..some action.. }
$continue = $ms_rs|| $my_rs;
}
Thank you for all ideas.
You can shoot in the dark and try to use both data_seek flavors of each, if they have both the same number of rows and same column names.
Here's the idea / here's some pseudo code too (untested of course):
$mssql_query = mssql_query(< the mssql query statement >);
$mysql_query = mysql_query(< the mysql query statement >);
$ms_num_rows = mssql_num_rows($mssql_query);
$my_num_rows = mssql_num_rows($mysql_query);
if($ms_num_rows === $my_num_rows) { // same number of rows on both result sets
for($i = 0; $i < $my_num_rows; $i++) {
mssql_data_seek($mssql_query, $i);
mysql_data_seek($mysql_query, $i);
$ms_row = mysql_fetch_assoc($mssql_query);
$my_row = mysql_fetch_assoc($mysql_query);
echo $ms_row['same_field_1'];
echo $my_row['same_field_1'];
// and others
}
}
Note: Of course you might get deprecation warnings for using these functions, most likely these functions have their PDO counterparts and you could port them into using those instead.
Manual entries:
http://php.net/manual/en/function.mssql-data-seek.php
http://php.net/manual/en/function.mysql-data-seek.php
I just had an answer. It's working for me
Idea from #Drew while($continue)
Here is my code
$mssql_query = mssql_query(..mssql..);
$mysql_query = mysql_query(..mysql..);
$continue = true;
while( $continue )
{
$ms_rs = mssql_fetch_assoc($mssql_query);
$my_rs = mysql_fetch_assoc($mysql_query);
if($ms_rs){ ..some action.. }
if($my_rs ){ ..some action.. }
$continue = $ms_rs|| $my_rs;
}
Thank you for all the ideas.

class definative commands out of sync solution

After about a week search I seem to find no conclusive / efficient / upto date / standard way of doing this.
The obvious solution is to run a query get the result into a variable and clear down ready for the next query - for efficiency NOT closing the connection.
This is being done in a wrapper class which has select / update / insert which in turn call a query or queries (for mysqli multi_query() ) so ideally it would be good to clear any result prior to next within query / queries to ensure it runs with no concern of what has gone before.
This does not seem possible as some solutions need a result set.
Currently the select / update / insert call:
private function queryclearup($dataresource) {
//clear up if required
switch ($this->dbtype) {
case "mysqli":
#mysqli_next_result($this->connection);
#mysqli_free_result($dataresource); //clear result to avoid out of sync issues
break;
}
}
after dealing with the result set - for example converting to a data array in the case of select, or just logging an error in the case of update / insert.
Still this problem persists with some (update), but not others (select / insert).
public function select($query, $args = array()) {
$this->loghelper->write("SQL Select\n" . $query);
$args = _PHP::array_defaults($args, array(
"pk" => null
));
$data_table = array();
$errors = null;
$query = utf8_decode($query);
switch ($this->dbtype) {
case "mysqli":
$dbdata = $this->query($query);
$data_table = $this->resourceToDataTable($dbdata, $args);
break;
}
return $data_table;
}
Then
private function resourceToDataTable($dataresource, $args = array()) {
$data_table = array();
if (gettype($dataresource) == "resource" || gettype($dataresource) == "object") {
do {
switch ($this->dbtype) {
case "mysqli":
$row = $dataresource->fetch_assoc();
break;
}
if ($row) {
array_push($data_table, $row);
}
} while ($row);
if (!empty($args["pk"])) {
$pktable = array();
foreach ($data_table as $d) {
if (!array_key_exists($args["pk"], $pktable)) {
$pktable[$d[$args["pk"]]] = $d;
}
}
$data_table = $pktable;
}
}
$this->queryclearup($dataresource);
return $data_table;
}
This appears to be whats required
private function queryclearup($dataresource) {
//clear up if required
switch ($this->db["contype"]) {
case "mysqli":
while ($dump = #mysqli_next_result($this->connection)) {
$donothing = 1;
}
#mysqli_free_result($dataresource); //clear result to avoid out of sync issues
break;
}
}

How to add INSERT IGNORE INTO in Codeigniter batch insert query

How to make codeigniter function that works same as insert_batch() but generates query Like INSERT IGNORE INTO ?
I need INSERT IGNORE INTO because one of my table's key is unique and its showing error when duplicate entry comes.
I searched code for add "INSERT IGNORE INTO " instead of "INSERT INTO" in codeigniter batch insert query but I didn't found results for that.
Yes we can made our custom batch insert query by using PHP login But if you want to do it in codeigniter use this function.
Add this function in (codeigniter/system/database/DB_active.rec.php).
/*
*Function For Batch Insert using Ignore Into
*/
public function custom_insert_batch($table = '', $set = NULL)
{
if ( ! is_null($set))
{
$this->set_insert_batch($set);
}
if (count($this->ar_set) == 0)
{
if ($this->db_debug)
{
//No valid data array. Folds in cases where keys and values did not match up
return $this->display_error('db_must_use_set');
}
return FALSE;
}
if ($table == '')
{
if ( ! isset($this->ar_from[0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->ar_from[0];
}
// Batch this baby
for ($i = 0, $total = count($this->ar_set); $i < $total; $i = $i + 100)
{
$sql = $this->_insert_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_keys, array_slice($this->ar_set, $i, 100));
$sql = str_replace('INSERT INTO','INSERT IGNORE INTO',$sql);
//echo $sql;
$this->query($sql);
}
$this->_reset_write();
return TRUE;
}
To use this function
$this->db->custom_insert_batch($table_name, $batch_data);
Thanks !

Working with multiple rows from a MySQL query

Before I begin, I want to point out that I can solve my problem. I've rehearsed enough in PHP to be able to get a workaround to what I'm trying to do. However I want to make it modular; without going too much into detail to further confuse my problem, I will simplify what I am trying to do so that way it does not detract from the purpose of what I'm doing. Keep that in mind.
I am developing a simple CMS to manage a user database and edit their information. It features pagination (which works), and a button to the left that you click to open up a form to edit their information and submit it to the database (which also works).
What does not work is displaying each row from MySQL in a table using a very basic script which I won't get into too much detail on how it works. But it basically does a database query with this:
SELECT * FROM users OFFSET (insert offset here) LIMIT (insert limit here)
Essentially, with pagination, it tells what number to offset, and the limit is how many users to display per page. These are set, defined, and tested to be accurate and they do work. However, I am not too familiar how to handle these results.
Here is an example query on page 2 for this CMS:
SELECT * FROM users OFFSET 10 LIMIT 10
This should return 10 rows, 10 users down in the database. And it does, when I try this command in command prompt, it gives me what I need:
But when I try to handle this data in PHP like this:
<?php
while ($row = $db->query($pagination->get_content(), "row")) {
print_r($row);
}
?>
$db->query method is:
public function query($sql, $type = "assoc") {
$this->last_query = $sql;
$result = mysql_query($sql, $this->connection);
$this->confirm_query($result);
if ($type == "row") {
return mysql_fetch_row($result);
} elseif ($type == "assoc" || true) {
return mysql_fetch_assoc($result);
} elseif ($type == "array") {
return mysql_fetch_array($result);
} elseif ($type == false) {
return $result;
}
}
$pagination->get_content method is:
public function get_content() {
global $db;
$query = $this->base_sql;
if (!isset($_GET["page"])) {
$query .= " LIMIT {$this->default_limit}";
return $query;
} elseif (isset($_GET["page"]) && $_GET["page"] == 1) {
$query .= " LIMIT {$this->default_limit}";
return $query;
} elseif (isset($_GET["page"])) {
$query .= " LIMIT {$this->default_limit}";
$query .= " OFFSET " . (($_GET["page"] * $this->default_limit) - 10);
return $query;
}
}
And my results from the while loop (which should print out each row of the database, no?) gives me the same row everytime, continuously until PHP hits the memory limit/timeout limit.
Forgive me if its something simple. I rarely ever handle database data in this manner. What I want it to do is show the 10 users I requested. Feel free to ask any questions.
AFTER SOME COMMENTS, I'VE DECIDED TO SWITCH TO MYSQLI FUNCTIONS AND IT WORKS
// performs a query, does a number of actions dependant on $type
public function query($sql, $type = false) {
$sql = $this->escape($sql);
if ($result = $this->db->query($sql)) {
if ($type == false) {
return $result;
} elseif ($type == true || "assoc") {
if ($result->num_rows >= 2) {
$array;
$i = 1;
while ($row = $result->fetch_assoc()) {
$array[$i] = $row;
$i++;
}
return $array;
} elseif ($result->num_rows == 1) {
return $result->fetch_assoc();
}
} elseif ($type == "array") {
if ($result->num_rows >= 2) {
$array;
$i = 1;
while ($row = $result->fetch_array()) {
$array[$i] = $row;
$i++;
}
return $array;
} elseif ($result->num_rows == 1) {
return $result->fetch_array();
}
}
} else {
die("There was an error running the query, throwing error: " . $this->db->error);
}
}
Basically, in short, I took my entire database, deleted it, and remade another one based on the OOD mysqli (using the class mysqli) and reformatted it into a class that extends mysqli. A better look at the full script can be found here:
http://pastebin.com/Bc00hESn
And yes, it does what I want it to. It queries multiple rows, and I can handle them however I wish using the very same methods I planned to do them in. Thank you for the help.
I think you should be using mysql_fetch_assoc():
<?php
while ($row = $db->query($pagination->get_content())) {
print_r($row);
}
?>

Categories