public function update($id, $table, $data, $exclude = array()){
$query = "UPDATE $table SET";
$fields = $values = array();
if( !is_array($exclude) ) $exclude = array($exclude);
foreach( array_keys($data) as $key ) {
if( !in_array($key, $exclude) ) {
$fields[] = "`$key`";
$values[] = "'" . $this->db->real_escape_string($data[$key]) . "'";
}
$fields = implode(" ", $fields);
$values = implode(" ", $values);
$query .= $fields . "=" . $values . ",";
}
$query = $query . "WHERE id = '".$id."' ";
if(!$this->db->query($query)){
echo "Something wrong with query ";
}
else{
echo "successfully updated";
}
}
Got error
Fatal error: [] operator not supported for strings
Tweaked code from add function which worked. Wanted to have fields and values updated dynamically without using variables, i.e. $_POST['address'].
$query .= $fields . "=" . $values . ", ";
seem not to be working. Not sure what cause the error: Fatal error: [] operator not supported for strings. How to insert field = value in sql query?
Use like this
if( !is_array($exclude) ) $exclude = array($exclude);
foreach( array_keys($data) as $key ) {
if( !in_array($key, $exclude) ) {
$query .= $key . "='" . $data[$key] . "' ,";
}
}
$query = substr($query,0,strlen($query)-1);
$query = $query . " WHERE id = '".$id."' ";
Look at the foreach loop!!!
foreach( array_keys($data) as $key ) {
if( !in_array($key, $exclude) ) {
$fields[] = "`$key`";
$values[] = "'" . $this->db->real_escape_string($data[$key]) . "'";
}
$fields = implode(" ", $fields); // Mistake done here
$values = implode(" ", $values); // Mistake done here
$query .= $fields . "=" . $values . ",";
}
Change your those two line and the next line outside the loop. May be this solve your problem.
foreach( array_keys($data) as $key ) {
if( !in_array($key, $exclude) ) {
$fields[] = "`$key`";
$values[] = "'" . $this->db->real_escape_string($data[$key]) . "'";
}
}
$fields = implode(" ", $fields);
$values = implode(" ", $values);
$query .= $fields . "=" . $values . ",";
Follow my code. Where no need implementation implode() function. I have changed your function code. try it.
public function update($id, $table, $data, $exclude = array()){
$query = "UPDATE $table SET";
$fields = $values = array();
if( !is_array($exclude) ) $exclude = array($exclude);
foreach( array_keys($data) as $key ) {
if( !in_array($key, $exclude) ) {
$queryArr[] = $key . "='" . $this->db->real_escape_string($data[$key]);
}
}
$query = implode(" ,", $queryArr);
$query = $query . "WHERE id = '".$id."' ";
if(!$this->db->query($query)){
echo "Something wrong with query ";
}
else{
echo "successfully updated";
}
}
Related
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();
how to add comma in query for next item? Add more details to the question.
// Indented the codes to make it more readable
$participants = [602, 600];
$query = array();
$query[] = 'INSERT INTO ' .
$db->nameQuote( '#__social_conversations_participants' );
$query[] = '(' . $db->nameQuote( 'conversation_id' ) .',' .
$db->nameQuote( 'user_id' ) . ',' . $db->nameQuote( 'state' ) . ')';
$query[] = 'VALUES';
foreach( $participants as $userId ){
$query[] = '(' . $db->Quote( $conversationId ) . ',' .
$db->Quote( $userId ) . ',' . $db->Quote( 1 ) . ')';
//this is not working because next() in this case always return
false
// Indented the codes to make it more readable
if( next( $participants ) !== false ){
$query[] = ',';
}
}
// Glue query back.
$query = implode( ' ' , $query );
var_dump($query);exit;
Found solution from here: PHP: Insert separated comma string value with as multiple array value Into MySql
<?php
$myString = "Red,Blue,Black";// incoming string comma names
$myArray = explode(',', $myString);
print_r($myArray);
$sql = "INSERT INTO `cat_interest`(`id`,`categories`) VALUES";
foreach($myArray as $value){
$sql .= " (1, '{$value}'),";
}
echo rtrim($sql, ',');
how i can make a insert using this fuctions
I m learning php, as using this functions (mysqli abstract) but after update wont work any more.
/** insert data array */
public function insert(array $arr)
{
if ($arr)
{
$q = $this->make_insert_query($arr);
$return = $this->modifying_query($q);
$this->autoreset();
return $return;
}
else
{
$this->autoreset();
return false;
}
}
complement
/** insert query constructor */
protected function make_insert_query($data)
{
$this->get_table_info();
$this->set_field_types();
if (!is_array(reset($data)))
{
$data = array($data);
}
$keys = array();
$values = array();
$keys_set = false;
foreach ($data as $data_key => $data_item)
{
$values[$data_key] = array();
$fdata = $this->parse_field_names($data);
foreach ($fdata as $key => $val)
{
if (!$keys_set)
{
if (isset($this->field_type[$key]))
{
$keys[] = '`' . $val['table'] . '`.`' . $val['field'] . '`';
}
else
{
$keys[] = '`' . $val['field'] . '`';
}
}
$values[$data_key][] = $this->escape($val['value'], $this->is_noquotes($key), $this->field_type($key), $this->is_null($key),
$this->is_bit($key));
}
$keys_set = true;
$values[$data_key] = '(' . implode(',', $values[$data_key]) . ')';
}
$ignore = $this->ignore ? ' IGNORE' : '';
$delayed = $this->delayed ? ' DELAYED' : '';
$query = 'INSERT' . $ignore . $delayed . ' INTO `' . $this->table . '` (' . implode(',', $keys) . ') VALUES ' . implode(',',
$values);
return $query;
}
before update this class i used to insert data like this
$db = Sdba::table('users');
$data = array('name'=>'adam');
$db->insert($data);
this method of insert dont works on new class.
if i try like this i got empty columns and empty values.
thanks for any help
complete class download http://goo.gl/GK3s4E
Try using set instead of insert:
$users = Sdba::table('users');
$user['name'] = 'Alvaro';
$users->set($user);
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:
I'm using var_export to dump output to logs when errors occur. However since the result is in pure text, I don't get a chance to push it through some sort of library like krumo so I can interactively explores the output.
What methods do people have to deal with making var_export text more readable?
Here is my function, it works well for multidimensional arrays:
function VE($varname, $varval, $short_syntax=true, $tag = ' ', $comma='', $end_line="\r\n") {
$res = '';
if($short_syntax){
$begin_array = '[';
$end_array = ']';
} else {
$begin_array = 'array(';
$end_array = ')';
}
$arr = explode('/',$varname);
$dim =count($arr)-1;
$lastKey = end($arr);
if (! is_array($varval)){
if( is_string($varval)) $varval = "'$varval'";
$res .= str_repeat($tag,$dim) . $lastKey . ' => ' . $varval . $comma . $end_line;
}else{
$res .= str_repeat($tag,$dim) . $lastKey . ' => ' . $begin_array . $end_line;
$count_varval = 0;
$dim_varval = count($varval);
foreach ($varval as $key => $val){
$count_varval++;
if($count_varval<$dim_varval) $commma=','; else $commma='';
if( is_string($key)) $key = "'$key'";
$res .= VE ($varname . "/" . $key , $val, $short_syntax, $tag, $commma);
}
$res .= str_repeat($tag,$dim) . $end_array . $comma . $end_line;
}
return $res;
}
$bigarray = array(); // your array
$bb = VE ('$bigarray', $bigarray);
echo "<pre>$bb</pre>";
I hope it helps ;)