PDOStatement->bindParam doesn't work - php

I have some trouble with $query->bindParam. It doesn't change placeholders into values.
$options is an array:
$options['where'] = [
'id' => [ 1, 2, 3 ],
'title' => [ 'some', 'title' ]
];
$fields = '*';
$where_clauses = []; /* define empty error which could be filled with where clauses */
/* if it is a separte blog, only posts posted by it's admin should be got */
if ( Main::$current_blog_id !== 1 )
$where_clauses[] = '`author_id` IN(' . $this->blog->admin_id . ')';
/* if options have been passed */
if ( ! empty( $options ) ) {
/* if there are "where" options */
if ( ! empty( $options['where'] ) ) {
$placeholder_number = 1; /* define placeholder number */
$placeholders = []; /* create array with placeholders 'placeholder_number' => 'value' */
foreach ( $options['where'] as $field_name => $values ) {
$field_values = []; /* values that will be used to create "IN" statement */
/* fill $fild_values array with values */
foreach ( $values as $value ) {
$placeholder = ':' . $placeholder_number; /* create placeholder */
$field_values[] = $placeholder; /* add placeholder to field values */
$placeholders[ $placeholder ] = $value; /* add placeholer with it's value to common placeholders array */
$placeholder_number++; /* increase placeholder number */
}
/* turn $fields_values array into string */
$field_values = implode( ', ', $field_values );
/* create clause and put it into $where_clauses */
$where_clauses[] = '`' . $field_name . '` IN(' . $field_values . ')';
}
}
}
/* if where statement is empty */
$where_clauses =
! empty( $where_clauses ) ?
implode( ' AND ', $where_clauses ) :
1;
$query = Main::$data_base->pdo->prepare(
'SELECT ' . $fields . ' ' .
'FROM `posts` ' .
'WHERE ' . $where_clauses . ' ' .
'LIMIT ' . $posts_quantity . ';'
);
/* if there are placeholders in the query */
if ( ! empty( $placeholders ) ) {
foreach ( $placeholders as $placeholder => $value )
$query->bindParam( $placeholder, $value, PDO::PARAM_STR );
}
$query->execute();
$posts = $query->fetchAll( PDO::FETCH_ASSOC );
var_dump( $query );
return
! empty( $posts ) ?
$posts :
[];
After all of this my printed query looks like:
SELECT * FROM `posts` WHERE `id` IN(:1, :2, :3) AND `title` IN(:4, :5) LIMIT 15;

You need to define the binds like...
Array ( ':1' => 1, ':2' => 2, ':3' => 3, ':4' => 'some', ':5' => 'title' )
Also your select is incorrect...
"SELECT * FROM posts WHERE id IN(:1, :2, :3) AND title IN(:4, :5) LIMIT 15;"
You have to put AND and not && in there.

PDOStatement::bindParam doesn't modify the query string that you passed to PDO::prepare. It replaces the placeholders with the value of the variable that you bound to it in the moment you execute the statement and the query is sent to the SQL server.
This should be what you want:
$query = "SELECT * FROM posts WHERE id IN (:1, :2, :3) AND title IN (:4, :5) LIMIT 15;";
$statement = $db->prepare($query); // $db contains the connection to the database
$placeholders = array(':1' => 1, ':2' => 2, ':3' => 3, ':4' => 'some', ':5' => 'title');
foreach ($placeholders as $placeholder => $value) {
$statement->bindValue($placeholder, $value, PDO::PARAM_STR);
}
$statement->execute();
Note that I use PDOStatement::bindValue and that I modified your SQL query string (and instead of &&).
You could also do this:
$query = "SELECT * FROM posts WHERE id IN (:1, :2, :3) AND title IN (:4, :5) LIMIT 15;";
$statement = $db->prepare($query);
$placeholders = array(':1' => 1, ':2' => 2, ':3' => 3, ':4' => 'some', ':5' => 'title');
$statement->execute($placeholders);
Read about PDOStatement::execute in the docs.

Related

Laravel9 Query using search is using all rows in table after filtering

I have a table which filters by the logged in user and the table has a search bar, however when i use the search it's ignoring the user and filtering all the records. My code as follows:
/**
* #param Request $request
* #return array
*/
public static function getDesktopJson(Request $request): array
{
$sortColumns = array(
0 => 'number',
1 => 'clients.title',
2 => 'jobs.title',
3 => 'time',
4 => 'proof_deadline',
5 => 'artwork_deadline',
6 => 'final_deadline',
7 => 'eclipse-contact',
8 => 'progress',
9 => 'actions',
);
try {
$query = Job::select( 'jobs.*' )
->whereHas( 'jobUserItems', fn( $qry ) => $qry->where( 'user_id', auth()->id() ) )
->where( 'is_active', 1 )
->where( 'is_complete', 0 );
$searchFields = ['clients.title', 'jobs.title', 'number'];
$with = ['client'];
[$query, $json] = getDataSourceQuery( $query, $request, $with, $sortColumns, $searchFields );
$jobs = $query->get();
} catch ( RecordsNotFoundException $e ) {
$jobs = [];
}
foreach ($jobs as $job) {
$json['data'][] = [
'#' . sprintf( '%07d', $job->number ) . '',
$job->client->title,
$job->title,
$job->getTimeChart( auth()->user()->work_group ),
$job->proof_deadline,
$job->artwork_deadline,
$job->final_deadline,
$job->getEclipseContact(),
$job->getJobStateValue( false ),
'' . config( 'ecl.EDIT' ) . ''
];
}
return $json;
}
the getDataSourceQuery function is in a helpers.php file (it is shared with other tables)
/**
* #param Builder|HasManyThrough $query
* #param Request $request
* #param array $with
* #param array $sortColumns
* #param array $searchFields
* #return array
*/
function getDataSourceQuery(Builder|HasManyThrough $query,
Request $request,
array $with,
array $sortColumns,
array $searchFields
) :array
{
$total = $query->count();
$search = $request->query('search', array('value' => '', 'regex' => false));
$draw = $request->query('draw', 0);
$start = $request->query('start', 0);
$length = $request->query('length', 25);
$order = $request->query('order', [['column' => 0, 'dir' => 'asc']]);
$column = $sortColumns[$order[0]['column']];
$dir = $order[0]['dir'];
$filter = $search['value'];
if ( !in_array($column, $searchFields, true) || empty( $filter ) ) {
addJoin($column, $query);
}
if (!empty($filter)) {
foreach ( $searchFields as $index => $field ) {
addJoin( $field, $query );
if ( $index === 0 ) {
$query->where($field, 'like', '%' . $filter . '%');
} else {
$query->orWhere($field, 'like', '%' . $filter . '%');
}
}
}
$qry = $query->toSql();
$count = $query->count();
$query->orderBy($column, $dir)
->with( $with )
->take($length)
->skip($start);
// $qry = $query->toSql();
// $bindings = $query->getBindings();
$json = array(
'draw' => $draw,
'recordsTotal' => $total,
'recordsFiltered' => $count,
'data' => [],
);
return [$query, $json];
}
and the addJoin function in the helpers.php file is:
/**
* #param mixed $column
* #param HasManyThrough|Builder $query
* #return void
*/
function addJoin(mixed $column, HasManyThrough|Builder $query): void
{
if (str_contains($column, '.')) {
$boom = explode('.', $column);
$table = $query->getModel()->getTable();
if ( $boom[0] !== $table ) {
if ($boom[0] === 'invoices' || $boom[0] === 'jobs') {
$iid = 'number';
} else {
$iid = 'id';
}
if ($table === 'jobs' || $table === 'invoices' || $table === 'subscriptions') {
$id = 'client_id';
} else {
$id = 'id';
}
$query->join($boom[0], $table . '.' . $id, '=', $boom[0] . '.' . $iid);
}
}
}
If the search is unused the correct number of rows are returned (say this is 15) as soon as I enter a search term in the search bar it uses all 1000+ records.
I'm using datatables.net (https://datatables.net/manual/index) for the table.
thanks

How to insert 3 php Array values as 3 MYSQL Columns

I need to insert array values in php as Columns in a MYSQL table.
$new_user = array(
"Nom" => $_POST['Nom'],
"EmailID" => $_POST['EmailID'],
"localité" => $_POST['localité']
);
$table = "memfis";
$columnNames = implode(", ", array_keys($new_user));
$columnPlaceholders = "'" . implode("', '", array_keys($new_user)) . "'";
$sqld = "INSERT INTO $table ($columnNames) VALUES ($columnPlaceholders);";
var_dump($sqld); exit;
$stmt = $pdo->prepare($sqld);
foreach ($columnNames as $name) {
$placeholder = "'" . $name;
$stmt->bindParam($placeholder, $new_user[$name]);
}
$connection->execute($sqld);
echo "New record created successfully";
It should have displayed " New row added succesfully " and the row should have been added in the table.
I tested the following with the original field names - specifically making note of the acute accent on the e and it failed - when I removed the accent and replaced with a standard letter e it worked fine
<?php
/* PDO dbo */
$dbport = 3306;
$dbhost = 'localhost';
$dbuser = 'root';
$dbpwd = 'xxx';
$dbname = 'xxx';
$options=array(
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL,
PDO::ATTR_PERSISTENT => false,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8mb4\' COLLATE \'utf8mb4_general_ci\', ##sql_mode = STRICT_ALL_TABLES, ##foreign_key_checks = 1'
);
$dsn = 'mysql:host='.$dbhost.';port='.$dbport.';dbname='.$dbname.';charset=UTF8';
$db = new PDO( $dsn, $dbuser, $dbpwd, $options );
/* Emulate POST form submission */
$_POST=[
'Nom' => 'fred flintstone',
'EmailID' => 'fred#bedrock.com',
'localite' => 'Bedrock'
];
$table='memfis';
/* prepare field names */
$fields = sprintf( '`%s`', implode( '`,`', array_keys( $_POST ) ) );
/* placeholder arrays */
$args = [];
$vals = [];
/* create placeholder variable names */
foreach( $_POST as $field => $value ) {
$args[]=sprintf( ':%s', strtolower( $field ) );
$vals[ sprintf( ':%s', strtolower( $field ) ) ]=$value;
}
/* create the sql statement */
$sql=sprintf(
'insert into `%s` ( %s ) values ( %s );',
$table,
$fields,
implode( ', ', $args )
);
$stmt = $db->prepare( $sql );
if( $stmt ){
# debug info
printf("<pre>%s\n%s</pre>", $sql, print_r( $vals, true ) );
# execute the statement
$res=$stmt->execute( $vals );
# did it or did it not work?
if( $res ){
echo "OK!";
} else {
echo "Bogus!";
}
}
?>
The resultant output to screen of the above is:
insert into `memfis` ( `Nom`,`EmailID`,`localite` ) values ( :nom, :emailid, :localite );
Array
(
[:nom] => fred flintstone
[:emailid] => fred#bedrock.com
[:localite] => Bedrock
)
OK!
When using the original fieldname localité the following error occurs:
Warning: PDOStatement::execute() [pdostatement.execute.html]:
SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
in .....

How to combine single row with array of data in prepared statements

I have two table ad_post and ad_img . One ad_post row has many images in ad_img. I am trying to execute 2 queries together and than combine at the end. but
table:ad_images
colums (img_id, ad_id, img_name)
table : ad_post
colums(id, user_id, title, price, cat, condit, description, vid)
Relationship
ad_post (1)------>(many)ad_images
public function read_ads()
{
$this;
$this->sql = 'SELECT ad_post.id,ad_post.user_id,ad_post.title,ad_post.price,
sub_cat.s_cat_name,ad_post.condit,ad_post.description,ad_post.vid FROM ad_post,sub_cat
where sub_cat.id=ad_post.cat';
$sql1 = 'SELECT `img_id`,`img_name` FROM `ad_images` WHERE ad_id=?';
$stmt = $this->con->prepare ( $this->sql );
$stmt1 = $this->con->prepare ( $sql1 );
if ($stmt === false) {
trigger_error ( 'Wrong SQL: ' . $sql . ' Error: ' . $conn->error, E_USER_ERROR );
}
// STMT
$stmt->execute ();
$stmt->store_result ();
$stmt->bind_result ( $id, $uId, $title, $price, $cat, $usage, $desc, $vid );
// STMT1
// $ad =AdPost::__getAll('','','','','','','','');
// $ad = Array();
$img = Array ();
$count = 0;
$count = 0;
$ads_img = Array ();
$a_img = Array ();
while ( $stmt->fetch () != NULL ) {
$stmt1->bind_param ( 'i', $id );
$stmt1->execute ();
$stmt1->store_result ();
$stmt1->bind_result ( $img_id, $img_name );
while ( $stmt1->fetch () != NULL ) {
echo $img_id;
$a_img = Array (
'img_id' => $img_id,
'img_name' => $img_name
);
try {
$ads_img [$count] = $a_img;
} catch ( Exception $exc ) {
echo $exc->getTraceAsString ();
}
}
$count ++;
$ad_set = Array (
'id' => $id,
'uid' => $uId,
'title' => $title,
'price' => $price,
'cat' => $cat,
'usage' => $usage,
'desc' => $desc,
'img_name' => $a_img
);
try {
$ads [$count] = $ad_set;
} catch ( Exception $exc ) {
echo $exc->getTraceAsString ();
}
$count ++;
}
$stmt->free_result ();
$stmt->close ();
return $ads;
}
I have got the ids of ads now i want to save imgs in array of $ad_set
The values of image array are returning null

How can I fix this query to return only items with a certain value in its subarray?

I'm trying to modify a voting script(Thumbsup) I need this query to only return only array items that have their 'cat' => '1' in the subarray (proper term?)
<?php $items = ThumbsUp::items()->get() ?>
Here's an example of the live generated array from my database
array (
0 =>
array (
'id' => 1,
'name' => 'a',
'cat' => '1',
),
1 =>
array (
'id' => 2,
'name' => 'b',
'cat' => '2',
),
2 =>
array (
'id' => 3,
'name' => 'c',
'cat' => '2',
),
)
Is this possible by just modifying the query?
edit: heres function get()
public function get()
{
// Start building the query
$sql = 'SELECT id, name, url, cat, closed, date, votes_up, votes_down, ';
$sql .= 'votes_up - votes_down AS votes_balance, ';
$sql .= 'votes_up + votes_down AS votes_total, ';
$sql .= 'votes_up / (votes_up + votes_down) * 100 AS votes_pct_up, ';
$sql .= 'votes_down / (votes_up + votes_down) * 100 AS votes_pct_down ';
$sql .= 'FROM '.ThumbsUp::config('database_table_prefix').'items ';
// Select only either open or closed items
if ($this->closed !== NULL)
{
$where[] = 'closed = '.(int) $this->closed;
}
// Select only either open or closed items
if ($this->name !== NULL)
{
// Note: substr() is used to chop off the wrapping quotes
$where[] = 'name LIKE "%'.substr(ThumbsUp::db()->quote($this->name), 1, -1).'%"';
}
// Append all query conditions if any
if ( ! empty($where))
{
$sql .= ' WHERE '.implode(' AND ', $where);
}
// We need to order the results
if ($this->orderby)
{
$sql .= ' ORDER BY '.$this->orderby;
}
else
{
// Default order
$sql .= ' ORDER BY name ';
}
// A limit has been set
if ($this->limit)
{
$sql .= ' LIMIT '.(int) $this->limit;
}
// Wrap this in an try/catch block just in case something goes wrong
try
{
// Execute the query
$sth = ThumbsUp::db()->prepare($sql);
$sth->execute(array($this->name));
}
catch (PDOException $e)
{
// Rethrow the exception in debug mode
if (ThumbsUp::config('debug'))
throw $e;
// Otherwise, fail silently and just return an empty item array
return array();
}
// Initialize the items array that will be returned
$items = array();
// Fetch all results
while ($row = $sth->fetch(PDO::FETCH_OBJ))
{
// Return an item_id => item_name array
$items[] = array(
'id' => (int) $row->id,
'name' => $row->name,
'url' => $row->url,
'cat' => $row->cat,
'closed' => (bool) $row->closed,
'date' => (int) $row->date,
'votes_up' => (int) $row->votes_up,
'votes_down' => (int) $row->votes_down,
'votes_pct_up' => (float) $row->votes_pct_up,
'votes_pct_down' => (float) $row->votes_pct_down,
'votes_balance' => (int) $row->votes_balance,
'votes_total' => (int) $row->votes_total,
);
}
return $items;
}
thanks.
You can easily modify "get()" to add the desired functionality:
public function get($cat = null)
{
$where = array();
if ($cat !== null) {
$where[] = 'cat = '. (int) $cat;
}
// ... original code ...
}
Usage:
$items = ThumbsUp::items()->get(1);

Modifying MySQL Where Statement Based on Array

Using an array like this:
$data = array
(
'host' => 1,
'country' => 'fr',
)
I would like to create a MySQL query that uses the values of the array to form its WHERE clause like:
SELECT *
FROM table
WHERE host = 1 and country = 'fr'
How can I generate this query string to use with MySQL?
Try this
$where = '';
foreach( $data as $k => $v ) {
if( !empty( $where ) )
$where .= ' AND ';
$where .= sprintf( "`%s` = '%s'", mysql_real_escape_string( $k ), mysql_real_escape_string( $v ) );
}
mysql_query( "SELECT * FROM `table` WHERE $where" );
Please please please don't build SQL statements with embedded data. Look here: http://bobby-tables.com/php.html

Categories