PDOStatement::execute() expects parameter 1 to be array, string given - php

I have this error:
PDOStatement::execute() expects parameter 1 to be array, string given
in C:\xampp\htdocs\Work\AppDarbNajah\App\Database.php on line 63
ArticleController code:
public function edit() {
$id = $_GET['ID'];
if(!empty($_POST) && (!empty($_FILES))){
$this->Article->update($id, [
'ref' => $_POST['ref'],
'desig' => $_POST['desig'],
'category_id' => $_POST['category_id'],
'tva' => $_POST['tva'],
'unit_id' => $_POST['unit_id'],
'Supplier_id' => $_POST['box-infos-id'],
'thumb' => $_FILES['thumb']['name'],
'created_by' => 2855,
'updated_by' => 2855
]);
}
$categories = $this->Category->extract('ID', 'category');
$units = $this->Unit->extract('ID', 'unit');
$tva = $this->Tva->extract('ID', 'tva (%)');
$article = $this->Article->find($id);
var_dump($article);
$form = new BootstrapForm($article);
$this->render('articles/edit',compact('form', 'categories', 'units', 'tva'));
}
Line 63 is:
'ref' => $_POST['ref']
I didn't write all code I wrote only the function that has error
update function code:
public function update($id, $fields){
$sql_pairs = [];
$attributes = [];
foreach ($fields as $k =>$v){
$sql_pairs[] = "$k = ?";
$attributes[] = $v;
}
$attributes = [];
$sql_parts = implode(', ', $sql_pairs);
$this->query("UPDATE INTO {$this->table} SET $sql_parts WHERE ID = ?", $attributes);
}

the problem was i should use array [$id] in find function as the following:
public function find($id){
return $this->query("SELECT * FROM {$this->table} WHERE ID = ?", [$id], true);
}

I am not sure about library you use to create your model but your function is weird.
public function update($id, $fields){
$sql_pairs = [];
$attributes = [];
// this bring an idea that you create list of fields to update #ref1
foreach ($fields as $k =>$v){
$sql_pairs[] = "$k = ?";
// here you add new value for next field to attributes #ref2
$attributes[] = $v;
}
// here you reset all values collected (#ref2) #ref3
// $attributes = []; //so let remove it
// but instead we need to add ID value to our query
$attributes[] = $id;
$sql_parts = implode(', ', $sql_pairs);
// UPDATE for MySQL should be something like :
// UPDATE my_table SET col1="newval1", col2="newval2" WHERE ID = 1
// lets try to get that format
$this->query("UPDATE {$this->table} SET $sql_parts WHERE ID = ?", $attributes);
}
Hope now it will work better....

Related

Yii2 merge arrays

I need merge arrays for json API. I have 3 requests:
$data['winners'] = Winners::find()->limit(8)->all();
$user = User::findIdentity($value->user_id);
$product = Products::find()->localized($lang)->where(['coupon' => $value->coupon])->one();
I need foreach all $data['winners'], get User with id from $data['winners'], and get Product from $data['winners']. After i need merge in 1 json all my data.
I try like this:
$data['winners'] = Winners::find()->limit(8)->all();
foreach ($data['winners'] as $value){
$user = User::findIdentity($value->user_id);
$product = Products::find()->localized($lang)->where(['coupon' => $value->coupon])->one();
$result = ArrayHelper::merge($product, $user);
}
There is an even more elegant solution in PHP:
$winners = Winners::find()->limit(8)->all();
foreach ($winners as $value){
$user = User::findIdentity($value->user_id);
$product = Products::find()->localized($lang)
->where(['coupon' => $value->coupon])->one();
$data[] = [
'image'=> $product->prize_image,
'user' => $user->firstname.' '.$user->lastname,
'title' => $product->win_title,
];
}
return $data;
The PHP array operator [] in $data[] adds an array element at the end of the $data array.
If i understand correctly you question you need an array with all the $data[winners] istances and foreach instance merge the related Produce and User
then you could use
$result[] = array_merge($value, $product, $user);
.
$data['winners'] = Winners::find()->limit(8)->all();
foreach ($data['winners'] as $value){
$user = User::findIdentity($value->user_id);
$product = Products::find()->localized($lang)->where(['coupon' => $value->coupon])->one();
$result[] = array_merge($value, $product, $user);
}
I found solution:
$winners = Winners::find()->limit(8)->all();
$i = 0;
foreach ($winners as $value){
$user = User::findIdentity($value->user_id);
$product = Products::find()->localized($lang)->where(['coupon' => $value->coupon])->one();
$data[$i]['image'] = $product->prize_image;
$data[$i]['user'] = $user->firstname.' '.$user->lastname;
$data[$i]['title'] = $product->win_title;
$i++;
}
return $data;

laravel - unable to get data outside foreach

dump($data) outside the foreach loop gives me only 1 data where as dump($data) inside the foreach shows all arrays of rows of data . How can i get all rows of data outside the foreach too?
$skillId = $request->skillId;
if (CourseFiles::where('skillId', $skillId)->exists()) {
$courseId = CourseFiles::where('skillId', $skillId)->get(['courseId']);
foreach ($courseId as $row) {
$id = Course::find($row);
$data = [];
$data['courseDisplayName'] = $id[0]['courseDisplayName'];
$data['courseInfo'] = $id[0]['courseUniqueName'];
$data['paidStatus'] = $id[0]['paid_status'];
$data['coursePatternsId'] = $id[0]['course_patterns_id'];
$fileId = CourseFiles::where('skillId', $skillId)->get(['fileId']);
$id = Uploads::find($fileId);
$data['filePath'] = $id[0]['FilePath'];
$contentTypeID = $id[0]['FileType'];
$id = ContentTypes::find($contentTypeID);
$data['file_height'] = $id[0]['height'];
$data['file_width'] = $id[0]['width'];
dump($data);
}
//dump($data);
if ($data) {
return response()->json([
'message' => 'Fetched Data successfully',
'data' => $data,
'statusCode' => 200,
'status' => 'success'
], 200);
}
}
EDIT:
$response[]=$data;
$response->paginate(5);
Error: Call to a member function paginate() on array
In Controller add new function for it
$data = $this->paginate($myArray);
After that crate that function for pagination
public function paginate($items, $perPage = 5, $page = null, $options = [])
{
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
$items = $items instanceof Collection ? $items : Collection::make($items);
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}
return that $data in response
just do like this,
$output = array();
foreach ($courseId as $key => $row) {
$id = Course::find($row);
$fileId = CourseFiles::where('skillId', $skillId)->get(['fileId']);
$idtwo = Uploads::find($fileId);
$idthree = ContentTypes::find($idtwo[0]['FileType']);
//your data want to push to array
$output[$key] = array(
'courseDisplayName' => $id[0]['courseDisplayName'];
'courseInfo' => $id[0]['courseUniqueName'];
'paidStatus' => $id[0]['paid_status'];
'coursePatternsId' => $id[0]['course_patterns_id'];
'filePath' => $idtwo[0]['FilePath'];
'file_height' => $idthree[0]['height'];
'file_width' => $idthree[0]['width'];
);
}
dd($output);

Yii2 multiple models loop save error

I've a table in which I have to save multiple data, in my controller I've implemented this action:
public function actionUpdateOrder($id){
/*DA TESTARE*/
//$result = 0;
$result = true;
$s = new Session;
$model = new SlidersImages();
if ($new_order = Yii::$app->request->post('order')) {
//$s['us_model'] = 0;
foreach ($new_order as $key => $value) {
if ($model::find()->where(['slider_id' => $id, 'image_id' => $key])->all()) {
$s['image_'.$key] = $model;
$model->display_order = $value;
//$result = ($t = $model->update()) ? $result + $t : $result;
$result = $model->save() && $result;
}
}
}
return $result;
}
The data received are right but not the result, the only thing that the action do is to add new table row with slider_id and image_id equal to NULL, why the model doesn't save correctly?
Thanks
The thing is when you call
$model::find()->where(['slider_id' => $id, 'image_id' => $key])->all()
you don't change the $model object itself. Essentially you are calling:
SlidersImages::find()->where(['slider_id' => $id, 'image_id' => $key])->all()
So, later when you call $model->save() you are saving a $model object with empty attributes (you only changed display_order)
My advise here: try to assign the result of the ->all() call to the new var and then work with it:
public function actionUpdateOrder($id){
/*DA TESTARE*/
//$result = 0;
$result = true;
$s = new Session;
if ($new_order = Yii::$app->request->post('order')) {
//$s['us_model'] = 0;
foreach ($new_order as $key => $value) {
$models = SliderImages::find()->where(['slider_id' => $id, 'image_id' => $key])->all();
if (count($models)) {
// loop through $models and update them
}
}
}
return $result;

Build a single multiple insert query from an array in PHP

I have an array that looks like this
$users = array(
array('name'=>'aaa','age'=>2),
array('name'=>'bbb','age'=>9),
array('name'=>'ccc','age'=>7)
);
I would like to create a function that will accept an array like above, creates a clause for a single query-multiple insert, prepares an array of variable that I can bind with PDO.
example output:
$clause = INSERT INTO tablename (`name`,`age`)
VALUES (:name_0,:age_0),(:name_1,:age_1),(:name_2,:age_2);
Then another set of array corresponding to the values above:
$params => Array
(
[name_0] => aaa
[age_0] => 2
[name_1] => bbb
[age_1] => 9
[name_2] => ccc
[age_2] => 7
);
So that the can execute it like so:
$prepared = $connection->prepare($clause);
$prepared->execute($params);
Is it possible to achieve this in a single function?
Yes that very possible, I did exactly the same thing for my custom query builder class:
function INSERT_MULTIPLE_QUERY($ARRS = array()){
$raw_cols = '(`';
// PREPARE THE COLUMNS
foreach($ARRS[0] as $key1 => $value):
$raw_cols .= $key1.'`,`';
endforeach;
$final_cols = rtrim($raw_cols,'`,`') . '`)';
$ctr1=0; $raw_vals='';
// PREPARE THE VALUES
foreach($ARRS as $ARR_VALUE):
$raw_vals .= '(';
foreach($ARR_VALUE as $key => $value): $raw_vals .= ':'.$key.'_'.$ctr1.','; endforeach;
$raw_vals = rtrim($raw_vals,',');
$raw_vals .= '),';
$ctr1++;
endforeach;
$final_vals = rtrim($raw_vals,',');
$ctr2 = 0; $param = array();
// PREPARE THE PARAMETERS
foreach($ARRS as $ARR_PARAM):
foreach($ARR_PARAM as $key_param => $value_param):$param[$key_param.'_'.$ctr2] = $value_param; endforeach;
$ctr2++;
endforeach;
// PREPARE THE CLAUSE
$clause = 'INSERT INTO tablename ' . $final_cols . ' VALUES ' . $final_vals;
// RETURN THE CLAUSE AND THE PARAMETERS
$return['clause'] = $clause;
$return['param'] = $param;
return $return;
}
Now to use this function:
$query = INSERT_MULTIPLE_QUERY($users);
// $users is your example array above
Then:
$prepared = $connection->prepare($query['clause']);
$prepared->execute($query['param']);
You can do it in a OOP style by creating a QueryBuilder and PDOStatementDecorator like below:
class QueryBuilder
{
const BUILD_TYPE_INSERT_MULTIPLE = 'INSERT_MULTIPLE';
protected $table;
protected $values;
protected $buildType;
public function __construct($table)
{
$this->table = $table;
}
public static function onTable($table)
{
return new self($table);
}
public function insertMultiple(Array $values = array())
{
$this->values = $values;
$this->buildType = self::BUILD_TYPE_INSERT_MULTIPLE;
return $this;
}
public function build()
{
switch ($this->buildType) {
case self::BUILD_TYPE_INSERT_MULTIPLE:
return $this->buildInsertMultiple();
}
}
protected function buildInsertMultiple()
{
$fields = array_keys($this->values[0]);
$query = "INSERT INTO {$this->table} (" . implode(',', $fields) . ") VALUES ";
$values = array();
for ($i = 0; $i < count($fields); $i++) {
$values[] = '(' . implode(', ', array_map(function($field) use ($i) {
return ':' . $field . $i;
}, $fields)) . ')';
}
$query .= implode(', ', $values);
return $query;
}
}
class PDOStatementDecorator
{
protected $pdoStatement;
public function __construct(PDOStatement $pdoStatement)
{
$this->pdoStatement = $pdoStatement;
}
public function executeMultiple(Array $bindsGroup = array())
{
$binds = array();
for ($i = 0; $i < count($bindsGroup); $i++) {
foreach ($bindsGroup[$i] as $key => $value) {
$binds[$key . $i] = $value;
}
}
return $this->execute($binds);
}
public function execute(Array $inputParemeters)
{
return $this->pdoStatement->execute($inputParemeters);
}
public function fetch($fetchStyle = null, $cursorOrientation = 'PDO::FETCH_ORI_NEXT', $cursorOffset = 0)
{
return $this->pdoStatement->fetch($fetchStyle, $cursorOrientation, $cursorOffset);
}
/**
* TODO
* Implement all public PDOStatement methods
*/
}
The query builder can be enhanced to be able to build queries for update/delete statements.
Now the usage would be very simple:
$users = array(
array('name' => 'aaa', 'age' => 2),
array('name' => 'bbb', 'age' => 9),
array('name' => 'ccc', 'age' => 7),
);
$query = QueryBuilder::onTable('users')->insertMultiple($users)->build();
$stmt = new PDOStatementDecorator($pdo->prepare($query));
$stmt->executeMultiple($users);
This function require Table Name, your original array, and an optional parameter that is used as default value, only if one field is not present in all array rows:
function buildQuery( $table, $array, $default='NULL' )
{
/* Retrieve complete field names list: */
$fields = array();
foreach( $array as $row ) $fields = array_merge( $fields, array_keys( $row ) );
$fields = array_unique( $fields );
/* Analize each array row, then update parameters and values chunks: */
$values = $params = array();
foreach( $array as $key => $row )
{
$line = array();
foreach( $fields as $field )
{
if( !isset( $row[$field] ) )
{ $line[] = $default; }
else
{
$line[] = ":{$field}_{$key}";
$params["{$field}_{$key}"] = $row[$field];
}
}
$values[] = '('.implode(',',$line).')';
}
/* Compone MySQL query: */
$clause = sprintf
(
"INSERT INTO `%s` (`%s`) VALUES %s;",
$table,
implode( '`,`', $fields ),
implode( ',', $values )
);
/* Return array[ clause, params ]: */
return compact( 'clause', 'params' );
}
Calling it in this way:
$query = buildQuery( 'mytable', $users );
$query will contain this:
Array
(
[clause] => INSERT INTO `mytable` (`name`,`age`) VALUES (:name_0,:age_0),(:name_1,:age_1),(:name_2,:age_2);
[params] => Array
(
[name_0] => aaa
[age_0] => 2
[name_1] => bbb
[age_1] => 9
[name_2] => ccc
[age_2] => 7
)
)
eval.in demo

Using foreach in codeigniter view to generate select options

I ma using codeigniter to generate some html options,but i only get one result,first result from the table.
This is my controller
public function edit_event($id = 0){
$id = $this->uri->segment(3);
$current_id = $this->ion_auth->get_user_id();
$data['data'] = $this->as->the_event_edit($id);
$data['groups'] = $this->as->the_groups_list($current_id);
$this->load->view('editevent',$data);
}
This is my model
public function the_groups_list($current_id){
$query = $this->db->get_where('all_groups', array('group_owner' => $current_id));
foreach ($query->result() as $row)
{
$data = array(
'group_title' => $row->group_title,
'group_name' => $row->group_name,
'group_owner' => $row->group_owner
);
return $data;
}
}
This is the other model
public function as_event_edit($id){
$query = $this->db->get_where('all_scheduled_messages', array('id' => $id));
foreach ($query->result() as $row)
{
$data = array(
'as_title' => $row->as_title,
'as_event_name' => $row->as_event_name,
'as_owner' => $row->as_owner,
'as_type' => $row->as_type,
'as_target_dataset' => $row->as_target_dataset,
'as_timestamp' => $row->as_timestamp,
'as_time' => $row->as_time,
'as_day' => $row->as_day
);
return $data;
}
}
I am then using $groups['group_title'] in view and only the first group title gets displayed even though i have like 4 group titles from the other rows.
How can i return and pass an array that i can then to the view so as to use foreach to iterate and display the group titles?.
In your model you're not creating a multi-dimensional array. You need to add keys either using a counter:
$data = array();
$i=0;
foreach ($query->result() as $row){
$data[$i]['as_title'] = $row->as_title;
$data[$i]['as_event_name'] = $row->as_event_name;
$data[$i]['as_owner'] = $row->as_owner;
$data[$i]['as_type'] = $row->as_type;
$data[$i]['as_target_dataset'] = $row->as_target_dataset;
$data[$i]['as_timestamp'] = $row->as_timestamp;
$data[$i]['as_time'] = $row->as_time;
$data[$i]['as_day'] = $row->as_day;
$i++;
);
return $data;
or use the key of the incoming array
$data = array();
foreach ($query->result() as $id => $row){
$data[$id]['as_title'] = $row->as_title;
$data[$id]['as_event_name'] = $row->as_event_name;
$data[$id]['as_owner'] = $row->as_owner;
$data[$id]['as_type'] = $row->as_type;
$data[$id]['as_target_dataset'] = $row->as_target_dataset;
$data[$id]['as_timestamp'] = $row->as_timestamp;
$data[$id]['as_time'] = $row->as_time;
$data[$id]['as_day'] = $row->as_day;
);
return $data;
Change the model from $data = to $data[] = to insert each row and not only one.
In your view loop over the groups, like so:
foreach ($data as $group) {
echo "Title" . $groups['group_title'];
}
RTM: Adding Dynamic Data to the View
In the controller: rename your $data['data'] to $data['event']
$data['event'] = $this->as->the_event_edit($id);
$data['groups'] = $this->as->the_groups_list($current_id);
$this->load->view('editevent',$data);
In your view:
foreach ($event as $items) {
var_dump($items);
}
foreach ($groups as $group) {
var_dump($group);
}

Categories