Update value NULL with php in mysql - php

I have this query:
UPDATE `terms`
SET id = '15',
taxonomy_id = '1',
parent_id = NULL,
level = 0,
position = 1,
active = '1',
time_created = '2012-05-24 09:31:12',
time_updated = '0000-00-00 00:00:00'
WHERE id = 15
And I want to set the parent_id to NULL with php, but how do I do this?
These are wrong:
$term->parent_id = 'NULL'; -> this is a string
$term->parent_id = NULL; -> this is empty
$term->parent_id = 0; -> this is an integer

there was a problem in my database class, that's why my parent_id value was always empty
this is how I fixed it:
old code:
public function set($data)
{
$this->query .= ' SET ';
if(is_object($data))
$data = get_object_vars($data);
if(is_array($data))
{
$l = count($data);
$t = 1;
foreach($data as $k => $v)
{
$this->query .= $k . ' = ' . ((is_string($v)) ? '\'' . $this->_escape($v) . '\'' : $this->_escape($v));
if($t < $l)
$this->query .= ',';
$t++;
}
}
else
{
$this->query .= $data;
}
return $this;
}
new code:
public function set($data)
{
$this->query .= ' SET ';
if(is_object($data))
$data = get_object_vars($data);
if(is_array($data))
{
$l = count($data);
$t = 1;
foreach($data as $k => $v)
{
$this->query .= $k . ' = ';
if(is_string($v))
{
$this->query .= '\'' . $this->_escape($v) . '\'';
} elseif (is_null($v)) {
$this->query .= 'NULL';
} else {
$this->query .= $this->_escape($v);
}
if($t < $l)
$this->query .= ',';
$t++;
}
}
else
{
$this->query .= $data;
}
return $this;
}

Query should be as :
some query editors requires NULL as null
UPDATE `terms` SET
id = '15',
taxonomy_id = '1',
parent_id = null,
level = 0,
position = 1,
active = '1',
time_created = '2012-05-24 09:31:12',
time_updated = '0000-00-00 00:00:00'
WHERE
id = 15

Related

yii2 override batchinsert from database class

I want to override batchinsert, because I want to add ON DUPLICATE KEY UPDATE
$result = Yii::$app->db->createCommand()->batchInsert('product', ['asin', 'title', 'image', 'url', 'price'], $results)->execute();
public function batchInsert($table, $columns, $rows)
{
if (empty($rows)) {
return '';
}
$schema = $this->db->getSchema();
if (($tableSchema = $schema->getTableSchema($table)) !== null) {
$columnSchemas = $tableSchema->columns;
} else {
$columnSchemas = [];
}
$values = [];
foreach ($rows as $row) {
$vs = [];
foreach ($row as $i => $value) {
if (isset($columns[$i], $columnSchemas[$columns[$i]]) && !is_array($value)) {
$value = $columnSchemas[$columns[$i]]->dbTypecast($value);
}
if (is_string($value)) {
$value = $schema->quoteValue($value);
} elseif ($value === false) {
$value = 0;
} elseif ($value === null) {
$value = 'NULL';
}
$vs[] = $value;
}
$values[] = '(' . implode(', ', $vs) . ')';
}
$query = 'INSERT INTO ' . $schema->quoteTableName($table);
$duplicate = ' ON DUPLICATE KEY UPDATE ';
$last = end($columns);
reset($columns);
foreach ($columns as $i => $name) {
$columns[$i] = $schema->quoteColumnName($name);
$duplicate .= $schema->quoteColumnName($name) . ' = VALUES(' . $schema->quoteColumnName($name) . ')';
if ($name <> $last) {
$duplicate .= ', ';
}
}
$query .= ' (' . implode(', ', $columns) . ') ';
$query .= ' VALUES ' . implode(', ', $values);
$query .= $duplicate;
return $query;
}
This is working but now I need to override yii\db\QueryBuilder
If found this: Yii::$app->db->commandClass = new common\models\Command();
and I can override the command class, but the code in yii\db\Schema should be updated too
public function createQueryBuilder()
{
return new \common\models\QueryBuilder($this->db);
}
Or I need to do something completely different, how can I fix this?
According to this discussion about non standard sql commands of devs you can do following (not tested):
class MyQueryBuilder extends yii\db\mysql\QueryBuilder
{
public function batchInsert($table, $columns, $rows)
{
$sql = parent::batchInsert($table, $columns, $rows);
$sql .= 'ON DUPLICATE KEY UPDATE';
return $sql;
}
}
or you can do this:
$db = Yii::$app->db;
$sql = $db->queryBuilder->batchInsert($table, $fields, $rows);
$db->createCommand($sql . ' ON DUPLICATE KEY UPDATE')->execute();
<?php
namespace common\models;
use yii\db\mysql\QueryBuilder as baseQueryBuilder;
class QueryBuilder extends baseQueryBuilder
{
public function batchInsert($table, $columns, $rows)
{
$sql = parent::batchInsert($table, $columns, $rows);
$sql .= ' ON DUPLICATE KEY UPDATE ';
$schema = $this->db->getSchema();
$last = end($columns);
reset($columns);
foreach ($columns as $i => $column)
{
$columns[$i] = $schema->quoteColumnName($column);
$sql .= $schema->quoteColumnName($column) . ' = VALUES(' . $schema->quoteColumnName($column) . ')';
if ($column <> $last) {
$sql .= ', ';
}
}
return $sql;
}
}
$db = Yii::$app->db;
$queryBuilder = new \common\models\QueryBuilder(Yii::$app->db);
$query = $queryBuilder->batchInsert('product', ['asin', 'title', 'image', 'url', 'price'], $results);
$db->createCommand($query)->execute();

Returning JSON from a PHP function

I want to transform this PHP function.. that should return JSON data.
<?php
$query = 'SELECT * FROM `' . mix_player::table() . '` a';
if (isset($_GET['cat']) || isset($_GET['order']))
if (isset($_GET['cat'])) {
$query .= ' INNER JOIN `' . mix_player::table_cat_rel() . '` b '
. "ON (a.`id` = b.`idtrack`) WHERE `idcat` = '" . $wpdb->escape($_GET['cat']) . "'";
$random = $wpdb->get_var('SELECT `random`, `order` FROM `' . mix_player::table_categories() . "` WHERE `id` = '"
. $wpdb->escape($_GET['cat']) . "'");
if (!$random)
$order = $wpdb->get_var(NULL, 1);
}
if (isset($_GET['order']))
$order = $_GET['order'];
if ($order != '') {
if (isset($_GET['cat']))
$query .= ' AND ';
else
$query .= ' WHERE ';
$tracks = mix_player::order_list($query, $order);
}
} else {
$random = '0';
}
$query .= ' ORDER BY `id` ASC';
if (isset($tracks) || ($tracks = $wpdb->get_results($query, ARRAY_A))) {
// option "shuffle = true" not always working into mix. Do it our own way...
if ($random == 1) { // shuffle tracks?
list($usec, $sec) = explode(' ', microtime());
mt_srand((float) $sec + ((float) $usec * 100000));
$nrows = count($tracks);
for ($i = 0; $i < $nrows; $i++) {
$j = mt_rand(0, $nrows - 1); // pick j at random
$row = $tracks[$i]; // swap i, j
$tracks[$i] = $tracks[$j];
$tracks[$j] = $row;
}
}
foreach ($tracks as $row) {
$artist = (mix_player::entities($row['artist']));
echo ($artist);
$title = (mix_player::entities($row['title']));
echo ($title);
$url =(xspf_player::entities($row['url']));
echo ($url);
}
}
?>
to display like this json file :
{"title":"title", "artist":"artist","media":"url media.mp3","color":"#56B0E8" },
Can you help me?
Thanks in advance.
You can simply create an array and populate it with your desired values, then return it as JSON:
function tracks2json( $tracks )
{
$retval = array();
foreach( $tracks as $row )
{
$array = array();
$array['artist'] = mix_player::entities($row['artist']);
$array['title'] = mix_player::entities($row['title']);
$array['media'] = 'url '.xspf_player::entities($row['url']);
$array['color'] = '#56B0E8';
$retval[] = $array;
}
return json_encode( $retval );
}
if( isset($tracks) || ($tracks = $wpdb->get_results($query, ARRAY_A)) )
{
// Your MySQL routine here
$json = tracks2json( $tracks );
}
echo json_encode(array("title"=>$title,"artist"=>$artist,"url"=>$url));

PHP PDO - Update with bindValue (set and where parametes are same)

This is a bit confusing for me, so I will try to explain it the best I can.
I am running update but nothing is happens.
This is the query which I get:
"UPDATE users SET name = :name, surname = :surname WHERE name = :name AND surname = :surname"
I start the query like this:
$data = ['name' => 'Sasha', 'surname' => 'M'];
$user = $users->where(['name' => 'TestName', 'surname' => 'TestSurname'])->update($data);
This is the update function:
public function update($data)
{
$fields = explode(',', $this->prepareFields($data));
$values = explode(',', $this->prepareValues($data));
$i = 0;
$count = count($fields);
$query = "UPDATE {$this->_tablename} SET ";
for($i; $i < $count; $i++):
$query .= $fields[$i] . " = " . $values[$i] . ',';
endfor;
$query = rtrim($query, ',');
$query .= " WHERE " . rtrim($this->_dbWhere, ' AND ');
$this->query($query);
$this->bindData($data);
$this->_dbBind = call_user_func_array('array_merge', $this->_dbBind);
$this->bindData($this->_dbBind);
$this->execute();
return $this->lastInsertId();
}
Where function:
public function where($field, $value = null)
{
if(!is_array($field)):
$this->_dbWhere .= $field . ' = :' . $field . ' AND ';
$this->_dbBind[] = [$field => $value];
else:
foreach($field as $key => $value):
$this->_dbWhere .= $key . ' = :' . $key . ' AND ';
$this->_dbBind[] = [$key => $value];
endforeach;
endif;
return $this;
}
Bind data function:
public function bindData($data)
{
foreach ($data as $key => $value) :
$this->bind(':' . $key, $value);
endforeach;
}
public function bind($param, $value, $type = null){
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = \PDO::PARAM_INT;
break;
case is_bool($value):
$type = \PDO::PARAM_BOOL;
break;
case is_null($value):
$type = \PDO::PARAM_NULL;
break;
default:
$type = \PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
Prepare fields and prepare values:
public function prepareFields($data)
{
return $fields = implode(', ', array_keys($data));
}
public function prepareValues($data)
{
$values = implode(', :', array_keys($data));
return ':' . $values;
}
Query function:
public function query($query){
$this->stmt = $this->handler->prepare($query);
}
The crux of this is that you use the same placeholder :fieldname in the WHERE clause and in the SET portion of the statement. You do need to correct other small issues raised here, but a simple solution is to make this change in the where() function:
if(!is_array($field)):
// make up a placeholder name distinct from the one used in SET clause
$field_placeholder = ":where_".$field
$this->_dbWhere .= $field . ' = ' . $field_placeholder . ' AND ';
$this->_dbBind[] = [$field_placeholder => $value];
else:

PHP Dynamically create SQL query with AND condition

I am trying to write some PHP that fits in to a larger method so that I can dynamically create a MySQL query.
I haven't included the code to the larger method that contains this code because I think the logic of this bit is self-contained.
So, I have a multi-dimensional array:
$where=array(array('username', 'pid', 'name'), array('=','<=', '='), array('alex',2,'james'));
which when I print_r() shows this structure:
Array
(
[0] => Array
(
[0] => username
[1] => pid
[2] => name
)
[1] => Array
(
[0] => =
[1] => <=
[2] => =
)
[2] => Array
(
[0] => alex
[1] => 2
[2] => james
)
)
What I would like to do if use the first value in each second level array to build up the start of the query such as
SELECT * FROM table WHERE username = alex
and then use the other values to build up the query such as (depending upon the number of items in the arrays)
SELECT * FROM table WHERE username = alex AND pid <= 2 AND name = james
Below is the code I have written
if (is_array($where[0])){
$i=0;
$field = $where[0][$i];
$operator = $where[1][$i];
$value= $where[2][$i];
$sql= "SELECT * FROM table WHERE {$field} {$operator} {$value}";
while($i=0 ) {
print $sql;
$i++;
}
while($i>0 AND $i< sizeof($where[0]))
$field = $where[0][$i];
$operator = $where[1][$i];
$value= $where[2][$i];
print $sql .= " AND {$field} {$operator} {$value}";
$i++;
}
However this prints out just one query
SELECT * FROM table WHERE username = alex AND username = alex
I am using PDO so in reality {$value} is replaced by ? and bound elsewhere in the method. I've just shown it here in full.
$sql = 'SELECT * FROM table WHERE';
for($i = 0; $i < count($where[0]); $i++){
$sql .= " {$where[0][$i]} {$where[1][$i]} {$where[2][$i]} AND";
}
$sql = substr($sql, 0, strlen($sql) - 4);
I personally would however save your statements like this:
$array = array('username = alex', 'pid <= 2');
If you needed the different parts of the statements, you could just do
explode(' ', $array[num]);
$companyFilter = "";
$auth = getFormulaAuth();
$companyFilter = "AND company_id = {$auth['company_id']} ";
$arguments = func_get_args();
if ($WhereFilterName_xxx) {
} else {
$db = new Database();
$this_get_table_form = getFormulaFormDetails($FormName);
$tbfields_data = Formula::getTBFields($this_get_table_form["id"], $db);
$q_string = "SELECT * FROM `" . $this_get_table_form["form_table_name"] . "`";
$valid_param_check = count($arguments) - 2;
$cache_key = "*";
if ($valid_param_check >= 1 && $valid_param_check % 3 == 0) {
$found_indexes = array();
$q_string_where = " WHERE ";
$search = " (NOT EXISTS(SELECT * FROM tbtrash_bin WHERE record_id = " . $this_get_table_form["form_table_name"] . ".id
AND form_id = " . $this_get_table_form["id"] . "
AND table_name='" . $this_get_table_form["form_table_name"] . "')) AND ";
$q_string_where .= $search;
for ($i = 2; $i < count($arguments); $i+=3) {
$field_key = $arguments[$i];
$operator = $arguments[$i + 1];
$value = $arguments[$i + 2];
if ($i > 2) {
$q_string_where .= " AND ";
}
$q_string_where .= " `" . $field_key . "` " . $operator;
if (($tbfields_data["" . $field_key]["field_input_type"] == "Number" || $tbfields_data["" . $field_key]["field_input_type"] == "Currency") || strtoupper($operator) == "IN") {
$q_string_where .= " " . $value . " ";
} else {
$q_string_where .= " '" . $value . "' ";
}
$q_string_orderby .= $q_string_where;
$sort_by = isset($_GET['s']) ? $_GET['s'] : false;
switch ($sort_by) {
case $tbfields_data;
break;
default:
$sort_by = 'DateCreated';
}
$q_string_orderby .= ' ORDER BY '.$sort_by.' ';
$direction = isset($_GET['d']) ? $_GET['d'] : false;
if ($direction != 'ASC' && $direction != 'DESC')
$direction = 'DESC';
$q_string_orderby .= $direction;
$res = $db->query($q_string_orderby);
$results = array();
if ($res) {
while ($r = mysql_fetch_assoc($res)) {
$results[] = $r;
}
}
$cache_key.="::" . $field_key . "::" . $operator . "::" . $value . "::" . $q_string_orderby;
}
$q_string .= $q_string_orderby;
}
$this_record = Formula::getLookupValue("formula_lookup_where_array", $this_get_table_form, $q_string, $cache_key);
array_push($GLOBALS['formula_executed_data_collector']['collected_form_id'], array(
"form_id" => $this_get_table_form['id'],
"where" => $q_string_where,
"function_name" => "Total",
"whole_query" => $q_string
));
$rslt = array_values(array_map(function($a) use($ReturnField) {
if (gettype($ReturnField) == "array") {
$array_collector = array();
foreach ($ReturnField as $key => $value) {
$array_collector[$value] = $a[$value];
}
return $array_collector;
} else if ($ReturnField == "*") {
return $a;
} else {
return $a[$ReturnField];
}
}, $this_record));
return $rslt;
}
}

Read Excel file in array or get adyacent columns values with PHPExcel

I have a Excel file with content like the showed in the image:
As you may see there is basically three columns (could be four or more) which represents categories and subcategories. I need to read this Excel file for then write some SQL sentences like for example:
INSERT INTO `category` (name, parent, status, modified) VALUES('Electronica', NULL, 1, NOW());
INSERT INTO `category` (name, parent, status, modified) VALUES('Celulares y Telefonos', 1, 1, NOW());
INSERT INTO `category` (name, parent, status, modified) VALUES('Accesorios para celulares', 2, 1, NOW());
I know how to read the file using PHPExcel_IO but don't know how to get the parent > childrens relationship in order to build the proper SQL sentences, any help or advice?
UPDATE
This is what I have done so far. First here is the complete source if yours have any problems please feel free to contact me in order to send the file (I do this because the Array is to large and services like pastie.org doesn't allow to publish it and here will ugly the post).
I created this function to read the array data:
function print_r_reverse($in) {
$lines = explode("\n", trim($in));
if (trim($lines[0]) != 'Array') {
return $in;
} else {
if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
$spaces = $match[1];
$spaces_length = strlen($spaces);
$lines_total = count($lines);
for ($i = 0; $i < $lines_total; $i++) {
if (substr($lines[$i], 0, $spaces_length) == $spaces) {
$lines[$i] = substr($lines[$i], $spaces_length);
}
}
}
array_shift($lines); // Array
array_shift($lines); // (
array_pop($lines); // )
$in = implode("\n", $lines);
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($in);
foreach ($matches as $match) {
$key = $match[1][0];
$start = $match[0][1] + strlen($match[0][0]);
$pos[$key] = array($start, $in_length);
if ($previous_key != '')
$pos[$previous_key][1] = $match[0][1] - 1;
$previous_key = $key;
}
$ret = array();
foreach ($pos as $key => $where) {
$ret[$key] = print_r_reverse(substr($in, $where[0], $where[1] - $where[0]));
}
return $ret;
}
}
And this is the code I have created to read the array values and write the SQL sentences:
$result = print_r_reverse($arrayData);
class RPMQGen {
var $array_to = "";
var $count = 1;
var $last_count_parent = -1;
var $t_name = "";
function RPMQGen($tableName, $array) {
$this->t_name = $tableName;
$this->array_to = $array;
}
function walk_children($value) {
$query = "";
$key_result = 0;
$index_count = 0;
foreach ($value as $key => $val)
if (strlen($val) > 1) {
$index_count++;
$key_result = $key;
};
if ($index_count > 1) {
foreach ($value as $key => $val) {
if (strlen($val) > 1) {
$query = $query . "INSERT INTO `" . $this->t_name . "` (`id`, `name`, `parent`, `deletedAt`) VALUES (" . $this->count . ",`" . $val . "`, " . ($key + 1) . ", 1, NULL); <br>";
$this->count++;
}
}
$this->last_count_parent = $this->count;
} else
if ($index_count == 1) {
$query = $query . "INSERT INTO `" . $this->t_name . "` (`id`, `name`, `parent`, `deletedAt`) VALUES (" . $this->count . ",`" . ($value[$key_result]) . "`, " . ($this->last_count_parent - 1) . ", 1, NULL); <br>";
$this->count++;
}
return $query;
}
function get_queries() {
$this->count = 2;
$query = "INSERT INTO `" . $this->t_name . "` (`id`, `name`, `parent`, `deletedAt`) VALUES (1,`root`, NULL, NULL); <br>";
foreach ($this->array_to as $key => $value) {
$query = $query . "INSERT INTO `" . $this->t_name . "` (`id`, `name`, `parent`, `deletedAt`) VALUES (" . $this->count . ",`" . $key . "`, 0, NULL); <br>";
$this->count++;
foreach ($value as $key => $value2) {
$query = $query . $this->walk_children($value2);
}
}
print($query);
}
}
$qgen = new RPMQGen('category', $result);
$qgen->get_queries();
But parent > children relations aren't right and I can't find the cause
Make 4 loops, one for each column. If the value is not empty, it means that the product is part of that column category. Not that hard really.

Categories