What is the problem to the code? I cannot upload to database. It comes the message:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ACQUA'))' at line 2
query was:
SELECT `vals`.*, `opt`.*
FROM `eav_attribute_option_value` AS `vals`
INNER JOIN `eav_attribute_option` AS `opt` ON opt.option_id = vals.option_id
WHERE (opt.attribute_id='191')
AND (vals.value in ('ALESSANDRO DELL'ACQUA'))
PHP Code:
<?php
/**
* Adapted by Christopher Shennan
* http://www.chrisshennan.com
*
* Date: 20/04/2011
*
* Adaptered from original post by Srinigenie
* Original Post - http://www.magentocommerce.com/boards/viewthread/9391/
*/
class Mage_Eav_Model_Import extends Mage_Eav_Model_Mysql4_Entity_Attribute {
private $fileName;
private $delimiter = '|';
private $enclosure = '"';
private function &getCsv() {
$file = fopen($this->fileName, "r");
while (!feof($file)) {
$csvArr[] = fgetcsv($file, 0, $this->delimiter, $this->enclosure);
}
fclose($file);
return $csvArr;
}
protected function populateOptionTable($attribId) {
echo "Upload Begin<br/>";
$fields = array();
$values = array(); // store id => values
$optionValues = array(); // option id => $values
$option = array('value' => $optionValues);
$updateOptionValId;
$values = null;
$row = null;
$disCounter = 0;
$optionTable = $this->getTable('attribute_option');
$optionValueTable = $this->getTable('attribute_option_value');
$write = $this->_getWriteAdapter();
$csvStoreArr = array();
// Get CSV into Array
$csv = & $this->getCsv();
$read = $this->_getReadAdapter();
// exit if the csv file is empty or if it contains only the headers
if (count($csv) < 1 or count($csv) == 1)
return;
$fields = $csv[0]; // get the field headers from first row of CSV
// get the store Ids
$stores = Mage::getModel('core/store')
->getResourceCollection()
->setLoadDefault(true)
->load();
// determine the stores for which option values are being uploaded for
foreach ($fields as $hdr) {
if ($hdr === 'position' || $hdr === 'isDefault' || $hdr === 'ERROR') {
continue;
}
foreach ($stores as $store) {
if ($store->getCode() === $hdr)
$csvStoreArr[$hdr] = $store->getId();
}
}
// start reading the option values - from row 1 (note that 0 represents headers)
for ($indx = 1; $indx < count($csv); $indx++) {
$values = null; // initialize to null
$row = $csv[$indx]; // get row
if (isset($row) && count($row) > 0) {
//escape the single quote
//$whereParam = $read->quote($row);
if (is_array($row))
$whereParam = '(\'' . implode($row, '\',\'') . '\')';
else if (strlen($row))
$whereParam = '(\'' . $row . '\')';
$select = $read->select()->from(array('vals' => $optionValueTable))
->join(array('opt' => $optionTable), 'opt.option_id=vals.option_id')
->where('opt.attribute_id=?', $attribId);
$select = $select
->where('vals.value in ' . $whereParam);
$optionValData = $read->fetchAll($select);
unset($select);
// get the option Id for this option
if (count($optionValData) > 0) {
$optionValDataRow = $optionValData[0];
$optionId = $optionValDataRow['option_id'];
} else
$optionId = null;
$intOptionId = (int) $optionId;
if (!$intOptionId) {
$data = array(
'attribute_id' => $attribId,
'sort_order' => isset($option['order'][$optionId]) ? $option['order'][$optionId] : 0,
);
try {
$write->insert($optionTable, $data);
$intOptionId = $write->lastInsertId();
} catch (Exception $e) {
Mage::log($e->getMessage());
}
} else {
$data = array(
'sort_order' => isset($option['order'][$optionId]) ? $option['order'][$optionId] : 0,
);
$write->update($optionTable, $data, $write->quoteInto('option_id=?', $intOptionId));
}
$colIndx = 0; //initialize row's column index
if (isset($row) && is_array($row) && count($row) > 0) {
foreach ($row as $optVal) {
if ($fields[$colIndx] !== 'position' || $fields[$colIndx] !== 'isDefault' || $fields[$colIndx] !== 'ERROR') {
$values[$csvStoreArr[$fields[$colIndx]]] = $optVal; // store id => option value
}
$colIndx++;
}
}
}
if (isset($values) && is_array($values) && count($values) > 0) {
foreach ($values as $storeId => $value) {
if (!empty($value) || strlen($value) > 0) {
$value = trim($value);
$data = array(
'option_id' => $intOptionId,
'store_id' => $storeId,
'value' => $value,
);
$optionValInsert = true;
$optionValUpdate = false;
foreach ($optionValData as $valData) {
if ((int) $valData['option_id'] === $intOptionId &&
(int) $valData['store_id'] === $storeId) {
$optionValInsert = false;
if (strcasecmp(trim($valData['value']), $value) !== 0) {
$optionValUpdate = true;
$updateOptionValId = $valData['value_id'];
}
break;
}
}
if ($optionValInsert) {
$write->insert($optionValueTable, $data);
Mage::log('Inserted Value -' . $value);
} else if ($optionValUpdate) {
$write->update($optionValueTable, $data, $write->quoteInto('option_id=?', $updateOptionValId));
Mage::log('Updated Value -' . $value);
}
}
}
}
$optionValues[$optionId] = $values;
if ($indx % 20 == 0) {
echo "" . $indx . ' - uploaded!!<br />';
Mage::log($indx . ' - attributes uploaded!!', null, $this->fileName . '.log');
}
}
echo "" . $indx . ' - uploaded!!<br />';
echo '<b> Attribute Upload Finished </b><br />';
$option['value'] = $optionValues;
return null;
}
/**
* Enter description here...
*
* #param Mage_Core_Model_Abstract $object
* #return Mage_Eav_Model_Mysql4_Entity_Attribute
*/
public function saveOptionValues($attributeId, $fn) {
$option = array();
$this->fileName = $fn;
echo '<strong>Importing Attributes</strong><br/><br/>Reading file contents - ' . $this->fileName . '<br />';
Mage::log("Upload Begin", null, $this->fileName . '.log');
// Step 1 -- Get attribute Id from attribute code
$atrribId = $attributeId; //569
// Step 2 Obtain the option values into an array
$option = $this->populateOptionTable($atrribId);
}
}
Error is because of single Quotes in the string : 'ALESSANDRO DELL'ACQUA.
SELECT vals., opt. FROM eav_attribute_option_value AS vals INNER JOIN
eav_attribute_option AS opt ON opt.option_id=vals.option_id WHERE
(opt.attribute_id='191') AND (vals.value in ('ALESSANDRO
DELL'ACQUA'))
Try using double quotes.
String Literals in MySQL [ https://dev.mysql.com/doc/refman/5.0/en/string-literals.html ]
' single quote is reserved character in MySQL and there are several ways to include quote characters within a string:
A "'" inside a string quoted with "'" may be written as ""''".
A """ inside a string quoted with """ may be written as """".
Precede the quote character by an escape character (""\").
A "'" inside a string quoted with """ needs no special treatment and
need not be doubled or escaped. In the same way, """ inside a string
quoted with "'" needs no special treatment.
To avoid this use PreparedStatement in PHP http://www.w3schools.com/php/php_mysql_prepared_statements.asp
In your query is should be like 'ALESSANDRO DELL''ACQUA' instead of 'ALESSANDRO DELL'ACQUA'
Related
I'm looking for an easy solution to create a little function to merge two arrays with value concat (I'm using it to create html tag attribute):
$default["class"] = "red";
$new["class"] = "green";
$new["style"] = "display:block"
The result:
$res["class"] = "red green";
$res["style"] = "display: block";
and one more option:
if the $new is not an array, just concat with the $default["class"] (if this exist), and the other side: if the $default is a simple string, convert to array: $default["class"] = $default;
I created a function but would like to use an easier, shorter way for that:
function attrMerge( $default, $new="" ){
$res = array();
if(!is_array($default)) {
$res["class"] = $default;
}
else {
$res = $default;
}
if( $new !== "" ){
if(!is_array($new)) {
if(isset($res["class"])){
$res["class"].= " ".$new;
}
}
else {
foreach($new as $key=>$value) {
if( isset($res[$key]) ) {
$res[$key].= " ".$value;
}
else {
$res[$key] = $value;
}
}
}
}
return $res;
}
$a = attrMerge("red", array("class"=>"green", "style"=>"display: block;"));
I think this is the function that you need. I have initialised the css classes and styles as empty and in depends what you pass into the function then you get the relevant array
/**
* This function returns an array of classes and styles
*
* #param $default
* #param $new
* #return array
*/
function attrMerge($default=null, $new=nul)
{
$result = array();
$result['class'] = "";
$result['style'] = "";
// add default class if exists
if (!empty($default) && is_string($default)) {
// $default is string
$result['class'] = $default;
}
if (!empty($default)
&& is_array($default)
) {
if (array_key_exists('class', $default)
&& !empty($default['class'])
) {
// $default['class'] exists and it's not empty
$result['class'] = $default['class'];
}
if (array_key_exists('style', $default)
&& !empty($default['style'])
) {
// $default['style'] exists and it's not empty
$result['style'] = $default['style'];
}
}
// add additional classes OR styles
if (!empty($new)) {
if(!is_array($new)) {
$result['class'] = empty($result['class'])
? $new
: $result['class'] . " " . $new;
} else {
foreach ($new as $key => $value) {
if (isset($result[$key])) {
$result[$key] = empty($result[$key])
? $value
: $result[$key] . " " . $value;
} else {
$result[$key] = $value;
}
}
}
}
return $result;
}
A way I believe suits your need, hopefully it's as adaptable and effecient as you were expecting.
$array1 = array(
'class' => 'class1',
'style' => 'display: none;'
);
$array2 = array(
'class' => 'class2'
);
$arrayFinal = arrayMerge($array1, $array2);
var_dump($arrayFinal);
function arrayMerge($arr1, $arr2 = ''){
// Array of attributes to be concatenated //
$attrs = array('class');
if(is_array($arr2)){
foreach($attrs as $attr){
if(isset($arr1[$attr]) && isset($arr2[$attr])){
// Not using .= to allow for smart trim (meaning empty check etc isn't needed //
$arr1[$attr] = trim($arr1[$attr] . ' ' . $arr2[$attr]);
}
}
}else{
$arr1['class'] = trim($arr1['class'] . ' ' . $arr2);
}
return $arr1;
}
$def = ['class' => 'red'];
$new = ['class' => 'green', 'style' => 'style'];
function to_array($in) {
return is_array($in) ? $in : ['class' => $in];
}
$def = to_array($def);
$new = to_array($new);
$res = $def;
array_walk($new, function ($val, $key) use (&$res) {
$res[$key] = trim(#$res[$key] . ' ' . $val);
});
var_dump($res);
I am very new to php and MYSQL so this is probably a very simple thing for a lot of people but is taking me hours.
My developer created the below code which is used to parse a csv file into some MYSQL tables.
Once the data is parsed into the MYSQL table, I have a separate script which I use to create some search forms on the data. For example, users can select all data where column X is between -50 and +50.
I want to accomplish 2 things:
In instances where there is either a "NA" or blank in the csv file for a particular column, I want this NOT be recognized as 0 in the database, which is what is currently happening. For example, if I run a search where I select all values to be between -10 and 10 for column A and column A contains blanks or "NAs", then these blanks or "NAs" should not be recognized in the search output (and database) as 0s. However, they should show up in every search result. Regardless, in the search form, I do not want to see the "NAs". I am sure I am not the first problem to encounter this problem and that there is a best practices method for this.
I want to replace all instances of " in the csv file with a blank. I know I can use the "preg_replace" function for this but I don't know the best place to put it.
Thanks!
<?php
ini_set('max_execution_time', 0);
ini_set('display_errors', 'On');
ini_set('error_reporting', E_ALL & ~E_NOTICE);
$global_start = microtime(true);
include_once('db.php');
$full_path = #dirname(__FILE__) . '/';
$distinct_fields = array('g', 'i', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 'y', 'z', 'aa', 'ab', 'ac', 't', 'u', 'v');
if (isset($_POST['truncate'])) {
mysqli_query($mysqli, 'TRUNCATE TABLE odesk_nj_data');
mysqli_query($mysqli, 'TRUNCATE TABLE odesk_nj_catalog');
}
if (isset($_POST['filename']) && is_file($full_path . $_POST['filename'])) {
$separator = $_POST['separator'];
$handle = fopen($full_path . $_POST['filename'], "r");
$fields = array();
$i = 0;
$proccess_iteration = 0;
mysqli_autocommit($mysqli, false);
while (($data = fgetcsv($handle, 0, $separator)) !== FALSE) {
if ($i == 0) {
$fields = $data;
} elseif ($data[0] != '') {
$branch_id = GetBranchId($data[0]);
$qs = 'INSERT INTO odesk_nj_data SET branch_id=' . $branch_id;
foreach ($fields as $index => $field_name)
{
if (strtolower($field_name) != 'a' /*&& strtolower($field_name)!='ad'*/)
{
$tmp = explode(',', $data[$index]);
// if ($data[$index] == '' || $data[$index] == 'NA')
// {
// $value = -1000.99;
// }
// elseif (count($tmp) == 2 && is_numeric($tmp[0]) && is_numeric($tmp[1]))
if (count($tmp) == 2 && is_numeric($tmp[0]) && is_numeric($tmp[1]))
{
$value = implode('.', $tmp);
} else {
$value = $data[$index];
}
$qs .= ', `' . strtolower($field_name) . '`="' . $value . '"';
}
if (in_array(strtolower($field_name), $distinct_fields)) {
SaveToCatalog(strtolower($field_name), $value);
}
}
mysqli_query($mysqli, $qs);
}
$i++;
$proccess_iteration++;
if ($proccess_iteration > 300) {
mysqli_commit($mysqli);
$proccess_iteration = 0;
mysqli_autocommit($mysqli, false);
}
}
mysqli_commit($mysqli);
echo 'Upload Complete! Was uploaded ' . ($i - 1) . ' rows.';
exit;
}
function SaveToCatalog($FieldName, $Value)
{
global $mysqli;
static $data;
if (!isset($data[$FieldName])) {
$result = mysqli_query($mysqli, 'SELECT * FROM odesk_nj_catalog WHERE field="' . $FieldName . '" ');
while ($item = mysqli_fetch_assoc($result)) {
$data[$FieldName][base64_encode($item['field_value'])] = true;
}
}
if (!isset($data[$FieldName][base64_encode($Value)])) {
$result = mysqli_query($mysqli, 'SELECT * FROM odesk_nj_catalog WHERE field="' . $FieldName . '" AND field_value="' . mysqli_real_escape_string($mysqli, $Value) . '"');
$info = mysqli_fetch_assoc($result);
if (isset($info['id']) && $info['id'] > 0) {
$data[$FieldName][base64_encode($Value)] = true;
} else {
mysqli_commit($mysqli);
mysqli_autocommit($mysqli, true);
$qs = 'INSERT INTO odesk_nj_catalog SET field="' . $FieldName . '", field_value="' . $Value . '"';
mysqli_query($mysqli, $qs);
if (mysqli_insert_id($mysqli) > 0) {
$data[$FieldName][base64_encode($Value)] = true;
}
mysqli_autocommit($mysqli, false);
}
}
}
function GetBranchId($BranchName)
{
global $mysqli;
static $branches;
if (empty($companies)) {
$result = mysqli_query($mysqli, 'SELECT * FROM odesk_nj_branches ');
while ($item = mysqli_fetch_assoc($result)) {
$branches[$item['branch_name']] = $item['branch_id'];
}
}
if (!isset($branches[$BranchName])) {
$result = mysqli_query($mysqli, 'SELECT * FROM odesk_nj_branches WHERE branch_name="' . $BranchName . '"');
$company_info = mysqli_fetch_assoc($result);
if (isset($company_info['branch_id']) && $company_info['branch_id'] > 0) {
$branches[$BranchName] = $company_info['branch_id'];
} else {
mysqli_commit($mysqli);
mysqli_autocommit($mysqli, true);
$qs = 'INSERT INTO odesk_nj_branches SET branch_name="' . $BranchName . '"';
mysqli_query($mysqli, $qs);
$branches[$BranchName] = mysqli_insert_id($mysqli);
mysqli_autocommit($mysqli, false);
}
}
return $branches[$BranchName];
}
?>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form enctype="multipart/form-data" method="post" action="nj_load.php">
Filename to parse: <input type="text" name="filename" value="Table.csv"><br/>
CSV Separator: <input type="text" name="separator" value=","><br/>
Truncate Table before parsing: <input type="checkbox" name="truncate" checked=""><br/>
<input type="submit" value="Parse">
</form>
</body>
</html>
Use NULL instead of "NA", and then a numeric column. UPDATE table SET col1=NULL where col1='NA'
After import, UPDATE table SET col1=NULL where col1=''. Otherwise, i don't really know what the difference between '' and a blank is.
Below, there is my code for database backup.
$this->load->database();
$this->load->dbutil();
$backup =& $this->dbutil->backup();
$prefs = array(
'format' => 'txt',
'filename' => 'mybackup.sql', );
$path=$this->config->base_url()."database/";
$this->load->helper('file');
write_file($path, $backup);
$this->load->helper('download');
force_download('mybackup.gz', $backup);
It works fine when i use
$db['default']['dbdriver'] = 'mysql';
But it gives error with
$db['default']['dbdriver'] = 'mysqli';
error:Unsupported feature of the database platform you are using.
How it will work with "mysqli" i need support mysqli in my project.
This hapend to me, then i open file "system\database\drivers\mysqli\mysqli_utility.php" and change function "_backup" to this:
/**
* MySQLi Export
*
* #access private
* #param array Preferences
* #return mixed
*/
function _backup($params = array())
{
// Currently unsupported
//---return $this->db->display_error('db_unsuported_feature');
if (count($params) == 0)
{
return FALSE;
}
// Extract the prefs for simplicity
extract($params);
// Build the output
$output = '';
foreach ((array)$tables as $table)
{
// Is the table in the "ignore" list?
if (in_array($table, (array)$ignore, TRUE))
{
continue;
}
// Get the table schema
$query = $this->db->query("SHOW CREATE TABLE `".$this->db->database.'`.`'.$table.'`');
// No result means the table name was invalid
if ($query === FALSE)
{
continue;
}
// Write out the table schema
$output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline;
if ($add_drop == TRUE)
{
$output .= 'DROP TABLE IF EXISTS '.$table.';'.$newline.$newline;
}
$i = 0;
$result = $query->result_array();
foreach ($result[0] as $val)
{
if ($i++ % 2)
{
$output .= $val.';'.$newline.$newline;
}
}
// If inserts are not needed we're done...
if ($add_insert == FALSE)
{
continue;
}
// Grab all the data from the current table
$query = $this->db->query("SELECT * FROM $table");
if ($query->num_rows() == 0)
{
continue;
}
// Fetch the field names and determine if the field is an
// integer type. We use this info to decide whether to
// surround the data with quotes or not
$i = 0;
$field_str = '';
$is_int = array();
while ($field = mysqli_fetch_field($query->result_id))
{
// Most versions of MySQL store timestamp as a string
$is_int[$i] = (in_array(
//strtolower(mysqli_field_type($query->result_id, $i)),
strtolower($field->type),
array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),
TRUE)
) ? TRUE : FALSE;
// Create a string of field names
$field_str .= '`'.$field->name.'`, ';
$i++;
}
// Trim off the end comma
$field_str = preg_replace( "/, $/" , "" , $field_str);
// Build the insert string
foreach ($query->result_array() as $row)
{
$val_str = '';
$i = 0;
foreach ($row as $v)
{
// Is the value NULL?
if ($v === NULL)
{
$val_str .= 'NULL';
}
else
{
// Escape the data if it's not an integer
if ($is_int[$i] == FALSE)
{
$val_str .= $this->db->escape($v);
}
else
{
$val_str .= $v;
}
}
// Append a comma
$val_str .= ', ';
$i++;
}
// Remove the comma at the end of the string
$val_str = preg_replace( "/, $/" , "" , $val_str);
// Build the INSERT string
$output .= 'INSERT INTO '.$table.' ('.$field_str.') VALUES ('.$val_str.');'.$newline;
}
$output .= $newline.$newline;
}
return $output;
}
If you need what change....
change all "mysql_..." to "mysqli..."
and the line
strtolower(mysqli_field_type($query->result_id, $i)),
To this
strtolower($field->type),
And viola! thats WORKS great...
Here is an extension to the function to backup all databases of any size.
This code will remove the PHP memory limits on exporting databases by utilising the file system (cache folder) and SQL LIMITS.
I hope this is useful to someone.
Replacement for function _backup($params = array())
FILE: system/drivers/mysqli/mysqli_utility.php
/**
* MySQLi Export
*
* #access private
* #param array Preferences
* #return mixed
*/
function _backup_old($params = array())
{
// Currently unsupported
return $this->db->display_error('db_unsuported_feature');
}
/**
* MySQLi Export
*
* #access private
* #param array Preferences
* #return mixed
*/
function _backup($params = array())
{
// Currently unsupported
//---return $this->db->display_error('db_unsuported_feature');
if (count($params) == 0)
{
return FALSE;
}
// Extract the prefs for simplicity
extract($params);
// Build the output
$output = '';
foreach ((array)$tables as $table)
{
// Temp file to reduce change of OOM Killer
$tempfilepath = APPPATH . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
$tempfile = $tempfilepath . 'dbbkp_tmp_' . time() . '.sql';
// Is the table in the "ignore" list?
if (in_array($table, (array)$ignore, TRUE))
{
continue;
}
// Get the table schema
$query = $this->db->query("SHOW CREATE TABLE `".$this->db->database.'`.`'.$table.'`');
// No result means the table name was invalid
if ($query === FALSE)
{
continue;
}
// Write out the table schema
$output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline;
if ($add_drop == TRUE)
{
$output .= 'DROP TABLE IF EXISTS '.$table.';'.$newline.$newline;
}
$i = 0;
$result = $query->result_array();
foreach ($result[0] as $val)
{
if ($i++ % 2)
{
$output .= $val.';'.$newline.$newline;
}
}
// Write $output to the $filename file
file_put_contents( $filename, $output, LOCK_EX );
$output = '';
// If inserts are not needed we're done...
if ($add_insert == FALSE)
{
continue;
}
// Grab all the data from the current table
//$query = $this->db->query("SELECT * FROM $table"); // OLD
$countResult = $this->db->query("SELECT COUNT(*) AS `count` FROM " . $table . ";");
$countReturn = $countResult->result_array();
$totalCount = $countReturn[0]['count'];
//if ($query->num_rows() == 0) // OLD
if ($totalCount == 0)
{
continue;
}
// Chunk Vars
$chunkSize = 10000;
$from = 0;
$resultArray = array();
if (isset($chunk_size))
{
$chunkSize = $chunk_size;
}
// Write out the table schema
$output .= '#'.$newline.'# TABLE DATA FOR: '.$table.$newline.'#'.$newline.$newline;
// Write $output to the $filename file
file_put_contents( $filename, $output, FILE_APPEND | LOCK_EX );
// Fetch the field names and determine if the field is an
// integer type. We use this info to decide whether to
// surround the data with quotes or not
$query = $this->db->query("SELECT * FROM " . $table . " LIMIT 1;");
$i = 0;
$field_str = '';
$is_int = array();
while ($field = mysqli_fetch_field($query->result_id))
{
// Most versions of MySQL store timestamp as a string
$is_int[$i] = (in_array(
//strtolower(mysqli_field_type($query->result_id, $i)),
strtolower($field->type),
array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),
TRUE)
) ? TRUE : FALSE;
// Create a string of field names
$field_str .= '`'.$field->name.'`, ';
$i++;
}
// Trim off the end comma
$field_str = preg_replace( "/, $/" , "" , $field_str);
// Pull the data in chunks
while($from < $totalCount)
{
// empty $output
$output = '';
// Execute a limited query:
$dataChunkQuery = $this->db->query('SELECT * FROM ' . $table . ' LIMIT ' . $from . ', ' . $chunkSize . ';');
$dataChunkRows = $dataChunkQuery->result_array();
// Increase $from:
$from += $chunkSize;
// Build the insert string
//foreach ($query->result_array() as $row) // OLD
//var_dump($resultArray); die();
foreach ($dataChunkRows as $row)
{
$val_str = '';
$i = 0;
foreach ($row as $v)
{
// Is the value NULL?
if ($v === NULL)
{
$val_str .= 'NULL';
}
else
{
// Escape the data if it's not an integer
if ($is_int[$i] == FALSE)
{
$val_str .= $this->db->escape($v);
}
else
{
$val_str .= $v;
}
}
// Append a comma
$val_str .= ', ';
$i++;
}
// Remove the comma at the end of the string
$val_str = preg_replace( "/, $/" , "" , $val_str);
// Build the INSERT string
$output .= 'INSERT INTO '.$table.' ('.$field_str.') VALUES ('.$val_str.');'.$newline;
}
// Write $output to the $filename file
file_put_contents( $filename, $output, FILE_APPEND | LOCK_EX );
sleep(1); // used to help reduce the CPU load
}
}
if( file_exists($filename) ) {
return true;
} else {
return false;
}
}
CI Model built for DB Backups
FILE: models/databasebackup_model.php
<?php
/**
* Database Backup
* - Used to make backups of the database system
* #author Adan Rehtla <adan.rehtla#aamcommercial.com.au>
*/
class Databasebackup_model extends API_Model {
private $CI;
private $lpFilePath = APPPATH . 'cache/backup/';
// Tables to ignore when doing a backup
private $laIgnoreTables = array(
'ci_sessions',
'any_other_tables_to_ignore'
);
/**
* Constructor
* #author Adan Rehtla <adan.rehtla#aamcommercial.com.au>
*/
function __construct() {
parent::__construct();
$this->CI = &get_instance();
}
/**
* Check and empty the cache location for storing the backups during transit
* #author Adan Rehtla <adan.rehtla#aamcommercial.com.au>
* #return json Result
*/
public function check_cache() {
$arrRet = false;
if( ! file_exists( $this->lpFilePath ) ) {
$arrRet = mkdir( $this->lpFilePath );
$arrRet = true;
}
$files = glob( $this->lpFilePath . '*' ); // get all file names present in folder
foreach( $files as $file ){ // iterate files
if( is_file( $file ) ) unlink( $file ); // delete the file
}
return (object) $arrRet;
}
/**
* Build a list of tables to backup
* #author Adan Rehtla <adan.rehtla#aamcommercial.com.au>
* #return json Result
*/
public function find_tables() {
$arrRet = false;
if( $this->database('db_read') ) {
$this->db_read->_protect_identifiers = FALSE;
$this->db_read->start_cache();
$this->db_read->distinct();
$this->db_read->select("table_name");
$this->db_read->from("information_schema.columns");
$this->db_read->where("table_schema", $this->db->dbprefix . $this->db->database);
$this->db_read->stop_cache();
// Get List of all tables to backup
$laTableNameResult = $this->db_read->get()->result();
$this->db_read->flush_cache();
if( !empty($laTableNameResult) ) {
foreach($laTableNameResult as $loTableName) {
if( ! in_array( $loTableName->table_name, $this->laIgnoreTables ) ) {
$arrRet[] = $loTableName->table_name;
}
}
}
$this->db_read->_protect_identifiers = TRUE;
}
return (object) $arrRet;
}
/**
* Backup the database to Amazon S3
* #author Adan Rehtla <adan.rehtla#aamcommercial.com.au>
* #param interger $lpUserId Logged in User ID
* #return json Result
*/
public function backup() {
ini_set('max_execution_time', 3600); // 3600 seconds = 60 minutes
ini_set('memory_limit', '-1'); // unlimited memory
//error_reporting(E_ALL); // show errors
//ini_set('display_errors', 1); // display errors
$arrRet = array();
$lpBackupCount = 0;
$zipNumFiles = 0;
$zipStatus = 0;
if( $this->database('db_read') ) {
$this->db->save_queries = false;
$this->load->dbutil( $this->db_read, TRUE );
$laBackupTables = $this->find_tables();
if( !empty($laBackupTables) && $this->check_cache() ) {
foreach($laBackupTables as $lpTableName) {
$lpFilename = $this->lpFilePath . 'backup-' . $lpTableName . '-' . date('Ymd-His') . '.sql';
$prefs = array(
'tables' => $lpTableName,
'format' => 'sql',
'filename' => $lpFilename,
'add_drop' => TRUE,
'add_insert' => TRUE,
'newline' => "\n",
'foreign_key_checks' => TRUE,
'chunk_size' => 1000
);
if( !file_exists( $lpFilename ) ){
if( $this->dbutil->backup( $prefs ) ) {
$lpBackupCount++;
}
}
sleep(1); // used to help reduce the CPU load
//break; // used to debug and testing to only process the first database table
}
try {
// ZIP up all the individual GZIPs
$zip = new ZipArchive();
$zip_file = $this->lpFilePath . '-' . date('Ymd-His') . '.zip';
$zip_files = glob( $this->lpFilePath . 'backup-*' ); // get all file names present in folder starting with 'backup-'
if( $zip->open( $zip_file, ZIPARCHIVE::CREATE ) !== TRUE ) {
exit("cannot open <$zip_file>\n");
}
if( !empty($zip_files) ) {
foreach( $zip_files as $file_to_zip ) { // iterate files
$zip->addFile( $file_to_zip, basename( $file_to_zip ) );
}
}
$zipNumFiles = $zip->numFiles;
$zipStatus = $zip->status;
$zip->close();
} catch (Vi_exception $e) {
print( strip_tags( $e->errorMessage() ) );
}
// Upload the file to Amazon S3
// REMOVED AWS S3 UPLOAD CODE
// REMOVED AWS S3 UPLOAD CODE
// REMOVED AWS S3 UPLOAD CODE
// Clean up cache files
$this->check_cache();
}
$this->db->save_queries = true;
}
if( !empty($lpBackupCount) && !empty($zip) && !empty($zip_file) ) {
return (object) array( 'success'=>true, 'totalTables'=>$lpBackupCount, 'zipNumFiles'=>$zipNumFiles, 'zipStatus'=>$zipStatus, 'zipFile'=>$zip_file );
} else {
return (object) array( 'success'=>false );
}
}
}
USAGE:
$this->load->model('databasebackup_model');
$laResult = $this->databasebackup_model->backup();
Your mysqli driver does n't support this feature.
Refer this:
http://ellislab.com/forums/viewthread/194645/#979255
I have created a Database Abstraction Layer over PDO to refrain from creating multiple queries around my scripts which would be pretty hard to maintain.
My DBAL is not very broad; It takes care of simple tasks such as INSERTING, UPDATING and SELECTING (with or without joining). It does not cover more advanced stuff such as selecting from multiple tables etc.
The problem that raised with my DBAL is that it is confusing queries when there are more of the same type in one HTTP request. For example there are three select statements in my script, the first one works, the other two don't. I tried creating a flush method to clear the previously filled attributes by the query, but it's not working and I'm out of ideas. I'm not ready to get rid of my class and get back to writing queries all over - it's so easy to write them this way.
Anyway, this is how I do some queries with my class:
$insert_update_select = array(
'COLUMNS' => array(
'column_name1' => 'data_to_update_or_insert1',
'column_name2' => 'data_to_update_or_insert2'
),
'WHERE' => array('x > y', 'y < x'),
'ORDER' => array('ASC' => 'column_name1'),
'LIMIT' => array(0, 5),
);
// This query works with updating, inserting and selecting
$db = new db();
$db->insert('table_name', $insert_update_select);
$db->update('table_name', $insert_update_select);
$db->select('table_name', $insert_update_select);
Don't ask me how to join tables; I actually forgot how my own syntax works for that, haha. (Gotta try to remember)
Anyway, here is my class:
<?php
class db
{
private $db_type = 'mysql';
private $db_host = 'localhost';
private $db_user = 'root';
private $db_pass = '';
private $db_name = 'imgzer';
private $db;
private $db_connection = '';
private $insert_data = '';
private $update_data = '';
private $select_data = '';
private $condition_data = '';
private $order_data = '';
private $limit_data = '';
private $join_data = array();
private $query;
private $table;
private $return_data;
private $affected_rows;
private $return_id;
// Database tables
const USERS_TABLE = 'imgzer_users';
const CONFIG_TABLE = 'imgzer_config';
public function __construct()
{
$this->db_connection = "$this->db_type:host=$this->db_host;dbname=$this->db_name";
$this->db = new PDO($this->db_connection, $this->db_user, $this->db_pass);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
unset($this->db_pass);
}
public function open()
{
if ($this->db)
{
return true;
}
return false;
}
public function close()
{
if ($this->db->close())
{
return true;
}
return false;
}
private function build_array($type, $data, $join_data = array())
{
if (empty($data))
{
return;
}
$type = strtoupper($type);
$this->update_data = '';
$this->select_data = '';
$data_index = 0;
$data_length = sizeof($data);
$last_row = $data_length - 1;
switch ($type)
{
case 'INSERT':
if (!is_array($data))
{
return;
}
$this->insert_data = '(';
foreach ($data as $column => $value)
{
$this->insert_data .= $column . (($data_index != $last_row) ? ', ' : '');
$data_index++;
}
$data_index = 0;
$this->insert_data .= ') ';
$this->insert_data .= 'VALUES (';
foreach ($data as $column => $value)
{
$this->insert_data .= '?' . (($data_index != $last_row) ? ', ' : '');
$data_index++;
}
$this->insert_data .= ') ';
break;
case 'UPDATE':
$this->update_data = '';
foreach ($data as $column => $value)
{
$this->update_data .= $column . ' = ?' . (($data_index != $last_row) ? ', ' : '');
$data_index++;
}
break;
case 'SELECT':
if (empty($join_data))
{
return;
}
if (is_array($join_data))
{
$from_table = array_keys($join_data['FROM']);
$join_table = array_keys($join_data['TABLES']);
$this->select_data = implode(', ', array_flip($data)) . ' FROM ' ;
$this->select_data .= $from_table[0] . ' ' . $join_data['FROM'][$from_table[0]] . ' ';
for ($i = 0; $i < sizeof($this->join_data); $i++)
{
$this->select_data .= $this->get_join_type($join_data['JOIN']). ' ';
$this->select_data .= $join_table[$i] . ' ' . $join_data['TABLES'][$join_table[$i]];
$this->select_data .= $this->join_data[$i];
}
$this->select_data = rtrim($this->select_data, ' ');
}
else
{
if (!isset($data[0]))
{
$data = array_flip($data);
}
$this->select_data = implode(', ', $data) . ' FROM ' . $this->table . ' ';
}
break;
}
}
private function set_join($on)
{
if (empty($on))
{
return;
}
if (is_array($on))
{
for ($i = 0; $i < sizeof($on); $i++)
{
$on[$i] = ' ON (' . implode(' AND ', $on[$i]) . ') ';
}
}
$this->join_data = $on;
}
private function set_order($order)
{
if (empty($order))
{
return;
}
$this->order_data = ' ORDER BY ';
if (is_array($order))
{
$data_index = 0;
$data_size = sizeof($order) - 1;
foreach ($order as $order_type => $column)
{
if ($order_type != 'ASC' && $order_type != 'DESC')
{
throw new Exception('Order type in SQL has to be either ASC or DESC');
return;
}
$this->order_data .= $column . ' ' . $order_type . (($data_index != $data_size) ? ', ' : '');
$data_index++;
}
return;
}
$this->order_data .= $order;
}
private function set_limit($limit)
{
if (empty($limit))
{
return;
}
if (sizeof($limit) > 2)
{
return;
}
if (sizeof($limit) == 1)
{
$limit = array(0, $limit[0]);
}
if (is_array($limit))
{
$limit = implode(', ', $limit);
}
$this->limit_data = " LIMIT {$limit}";
}
private function set_where($condition)
{
if (empty($condition))
{
return;
}
if (is_array($condition))
{
$condition = implode(' AND ', $condition);
}
$this->condition_data = " WHERE $condition";
}
public function in_set($where_ary)
{
$where_str = implode(', ', $where_ary);
$where_str = substr($where_str, 0, -2);
$where_str = 'IN (' . $where_str . ')';
return $where_str;
}
/*
* Example usage:
* $insert_ary = array('col_1' => 'col_data_1', 'col_2' => 'col_data_2');
* $condition_ary = array('col_1 > 5', 'col_2 <> 10');
* $order_ary = array('ASC' => 'col_1', 'DESC' => 'col_2');
* $limit = array($start = 0, $limit = 5);
* $instance->insert('my_table', $insert_ary, $condition_ary, $order_ary, $limit);
*/
public function insert($table, $data, $return_id = false)
{
$data = $this->data_abstract($data);
// Prepare the arrays
$this->build_array('INSERT', $data['COLUMNS']);
$this->set_where($data['WHERE']);
$this->set_order($data['ORDER']);
$this->set_limit($data['LIMIT']);
$sql = 'INSERT INTO ' . $table . ' ';
$sql .= $this->insert_data;
$sql .= $this->condition_data;
$sql .= $this->order_data;
$sql .= $this->limit_data;
$this->query = $this->db->prepare($sql);
$param_index = 1;
foreach ($data['COLUMNS'] as $column => &$value)
{
$this->query->bindParam($param_index, $value);
$param_index++;
}
$this->query->execute();
if ($return_id)
{
$this->return_id = $this->query->last_insert_id();
}
else
{
$this->affected_rows = $this->query->rowCount();
}
}
public function update($table, $data, $return_id = false)
{
$data = $this->data_abstract($data);
// Prepare the arrays
$this->build_array('UPDATE', $data['COLUMNS']);
$this->set_where($data['WHERE']);
$this->set_order($data['ORDER']);
$this->set_limit($data['LIMIT']);
$sql = 'UPDATE ' . $table . ' SET ';
$sql .= $this->update_data;
$sql .= $this->condition_data;
$sql .= $this->order_data;
$sql .= $this->limit_data;
$this->query = $this->db->prepare($sql);
$param_index = 1;
foreach ($data['COLUMNS'] as $column => &$value)
{
$this->query->bindParam($param_index, $value);
$param_index++;
}
$this->query->execute();
if ($return_data)
{
$this->return_id = $this->query->last_insert_id();
}
else
{
$this->affected_rows = $this->query->rowCount();
}
}
/*
* Joining example:
* $join_data = array(
* 'TABLES' => array('table_2' => 't2', 'table_3' => 't3'),
* 'JOIN' => 'LEFT',
* 'ON' => array(
* array('colx > 15', 'coly < 20'),
* array('fieldx > 15', 'fieldy < 20')
* ),
*);
*/
public function select($table, $data, $join = false, $fetch_type = 'assoc')
{
$data = $this->data_abstract($data);
if ($join)
{
if (!is_array($table))
{
throw new Exception('Table has to be associated with a short index');
return;
}
$this->set_join($join['ON']);
$table = array_merge(array('FROM' => $table), $join);
}
// Globalize table name if not joins are used
$this->table = $table;
// Prepare the arrays
$this->build_array('SELECT', $data['COLUMNS'], $table);
$this->set_where($data['WHERE']);
$this->set_order($data['ORDER']);
$this->set_limit($data['LIMIT']);
$sql = 'SELECT ';
$sql .= $this->select_data;
$sql .= $this->condition_data;
$sql .= $this->order_data;
$sql .= $this->limit_data;
$this->query = $this->db->prepare($sql);
$result = $this->query->execute();
$fetch_type = ($fetch_type == 'assoc') ? PDO::FETCH_ASSOC : PDO::FETCH_NUM;
$fetched_data = $this->query->fetchAll($fetch_type);
$data_result = $fetched_data;
if (sizeof($fetched_data) == 1)
{
$data_result = $fetched_data[0];
}
$this->return_data = $data_result;
// Clear the result
//$this->query->closeCursor();
}
public function fetch()
{
return $this->return_data;
}
public function affected_rows()
{
return $this->affected_rows;
}
private function data_abstract($data)
{
$abstract_ary = array('COLUMNS' => '', 'WHERE' => '', 'ORDER' => '', 'LIMIT' => 0);
return array_merge($abstract_ary, $data);
}
private function get_join_type($type)
{
switch ($type)
{
default:
case 'LEFT':
return 'LEFT JOIN';
break;
case 'RIGHT':
return 'RIGHT JOIN';
break;
case 'INNER':
return 'INNER JOIN';
break;
case 'NORMAL':
case 'JOIN':
return 'JOIN';
break;
}
}
private function flush()
{
unset($this->query, $this->insert_data, $this->update_data, $this->select_data);
}
}
$db = new db();
?>
What's wrong with it (could be a lot) and how do I actually make it work efficiently?
Don't make it stateful.
Even without looking at the code I'll tell you what's the problem: get rid of $this->stmt variable.
For some reason, all the DBAL writers have strong inclination to such a variable... introducing state to their class and thus making it unusable.
All the method calls have to be atomic, each performing all the necessary operations and returning all the requested data. While saving nothing in the class variables. As simple as that. In such a rare case when PDOStatement object have to be used further - return this very object, don't save it inside. Otherwise just return the requested data.
I wold also advise to get rid of your whole DBAL, as it's written out of good intentions but I can tell for sure that implementation turns out to be less helpful but it actually makes your code worse in many aspects - readability, flexibility, maintainability. In pursue for the fictional usability, you are saving yourself only a word or two from SQL, but making whole application code unreliable.
You won't listen to me, though. Some experience in maintaining applications is required to see my point.
I'm trying to create a PHP script, which could draw a LineChart from MYSQL table.
Everything related with MYSQL works fine, but when I want to draw a LineChart using pChart, I'm getting error (Warning: Division by zero in ...\class\pDraw.class.php on line 3113). Please help me!
Here's the code:
<?php
include("class/pData.class.php");
include("class/pDraw.class.php");
include("class/pImage.class.php");
$filename = 'file.txt';
echo 'Status info:<br />';
$myData = new pData();
$db=mysql_connect("localhost","root","") or die("Failed to connect with database!");
echo '<br>* Connected to database successfully - OK<br />';
mysql_select_db("database", $db);
mysql_query("CREATE TABLE `measures` (
timestamp INT(10),
temperature INT(10),
humidity INT(10),
PRIMARY KEY (timestamp));");
echo "<br> * Table created successfully or it has been created earlier - OK<br />";
mysql_query("LOAD DATA INFILE '$filename' IGNORE INTO TABLE measures
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n' ")
or die("MySQL - Query Error - " . MySQL_Error());
echo "<br>* Data imported successfully - OK<br />";
$Requete = "SELECT * FROM `measures`";
$Result = mysql_query($Requete,$db);
while($row = mysql_fetch_array($Result))
{
$timestamp[] = $row["timestamp"];
$temperature[] = $row["temperature"];
$humidity[] = $row["humidity"];
}
$myData->addPoints($timestamp,"Timestamp");
$myData->addPoints($temperature,"Temperature");
$myData->addPoints($humidity,"Humidity");
$myData->setAbscissa("Timestamp");
$myData->setSerieOnAxis("Humidity", 1);
$myData->setXAxisName("Time");
$myData->setXAxisDisplay(AXIS_FORMAT_TIME,"H:i");
$myData->setAxisName(0,"Temperature");
$myData->setAxisUnit(0,"°C");
$myData->setAxisName(1,"Humidity");
$myData->setAxisUnit(0,"%");
$myPicture = new pImage(700,230,$myData);
$myPicture->drawLineChart();
?>
EDIT:
Here's the function containing line 3113 in pDraw.php
function scaleComputeY($Values,$Option="",$ReturnOnly0Height=FALSE)
{
$AxisID = isset($Option["AxisID"]) ? $Option["AxisID"] : 0;
$SerieName = isset($Option["SerieName"]) ? $Option["SerieName"] : NULL;
$Data = $this->DataSet->getData();
if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); }
if ( $SerieName != NULL ) { $AxisID = $Data["Series"][$SerieName]["Axis"]; }
if ( !is_array($Values) ) { $tmp = $Values; $Values = ""; $Values[0] = $tmp; }
$Result = "";
if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
{
$Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Data["Axis"][$AxisID]["Margin"]*2;
$ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"];
$Step = $Height / $ScaleHeight;
if ( $ReturnOnly0Height )
{ foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $Step * $Value; } } }
else
{ foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $this->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"] - ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); } } }
}
else
{
$Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Data["Axis"][$AxisID]["Margin"]*2;
$ScaleWidth = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"];
$Step = $Width / $ScaleWidth;
if ( $ReturnOnly0Height )
{ foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $Step * $Value; } } }
else
{ foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $this->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"] + ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); } } }
}
if ( count($Result) == 1 )
return($Result[0]);
else
return($Result);
}
You can fix it by changing this line:
$Step = $Width / $ScaleWidth;
to:
if ($ScaleWidth > 0) {
$Step = $Width / $ScaleWidth;
} else {
$Step = 1; // or change this to 0 if it doesn't work, I am not sure what this line does.
}