I can't get SQLite LIKE search to work with PDO. This works fine with
MySQL and MariaDB but I can't get this to work with SQLite3.
I have also tried with different examples from internet.
I'm using sqlite3 version 3.35.3 and version PHP 8.0.3 on Linux 5.9.
echo '<pre>';
$createTable = <<<EOT
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
INSERT INTO users(name) VALUES
('alpha'),
('beta'),
('gamma'),
('theta');
EOT;
if (!file_exists(__DIR__ . '/test.db'))
{
echo "#CREATING DB# <br>";
$pdo = new \PDO('sqlite:' . __DIR__ . '/test.db');
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->exec($createTable);
$term = 'et';
$sql = " SELECT * FROM users WHERE name LIKE :term ";
$stmt = $pdo->prepare($sql);
$prepare = [
'term' => "'%". $term ."%'"
];
echo getPdoCompiledSqlString($sql, $prepare) . '<br>';
if($stmt)
{
$stmt->execute($prepare);
//$stmt->debugDumpParams();
debugPdo($stmt);
echo "#FETCHALL# <br>";
print_r( $stmt->fetchAll() );
}
}
else
{
echo "#DELETING DB#";
unlink(__DIR__ . '/test.db');
}
function getPdoCompiledSqlString($sql, $params){
echo "#SQL STRING# <br>";
$keys = [];
foreach ($params as $key => $value){ if (is_string($key)) {$keys[] = '/:'.$key.'/';} else {$keys[] = '/[?]/';}}
return preg_replace($keys, $params, $sql, 1, $count);
}
function debugPdo(&$stmt){
echo "#DEBUG PDO OBJ# <br>";
$stmt->debugDumpParams();
}
echo '<pre>';
You don't need to quote the parameter :
'term' => "%". $term ."%"
Instead of
'term' => "'%". $term ."%'"
Because the parameter will automatically be quoted during execute()
$term = 'et';
$sql = " SELECT * FROM users WHERE name LIKE :term ";
$stmt = $pdo->prepare($sql);
$prepare = [
'term' => "%". $term ."%" //only the search string: `%et%`
];
$stmt->execute($prepare);
print_r($stmt->fetchAll());
Output:
Array
(
[0] => Array
(
[id] => 2
[0] => 2
[name] => beta
[1] => beta
)
[1] => Array
(
[id] => 4
[0] => 4
[name] => theta
[1] => theta
)
)
Related
I am using SQLite3 and PHP, and try to write a generic function to execute my queries.
For this I would like to retrieve the name of the parameters from variables in the bindParam.
But it doesn't seem to work. Here is a code showing the unexpected behavior:
<?php
header("Content-Type: text/plain");
$db = new SQLite3(':memory:');
$db->exec("create table mytable (lsid integer primary key autoincrement, usid TEXT, source TEXT)");
$myid = 'agoodid';
$mydatasources = array('home', 'news');
foreach($mydatasources as $datasource) {
$params[] = array(':datasource' => $datasource, ':usid' => $myid);
}
echo "here are the inputs : " .PHP_EOL;
print_r($params);
$querystring = 'insert into mytable (source, usid) values (:datasource, :usid)' ;
echo " I prepare the query '$querystring'" . PHP_EOL;
$query = $db->prepare($querystring);
foreach($params as $set) {
foreach($set as $key => $value) {
echo " Setting $key = $value." . PHP_EOL;
$query->bindParam($key, $value, SQLITE3_TEXT);
}
echo " I execute the query" . PHP_EOL;
$queryres[] = $query->execute();
$query->reset();
}
$results = $db->query('select * from mytable');
echo "and here is what I get : " . PHP_EOL;
while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
print_r($row);
}
?>
And here is the final result :
Array
(
[lsid] => 1
[usid] => agoodid
[source] => agoodid
)
Array
(
[lsid] => 2
[usid] => agoodid
[source] => agoodid
)
All the parameters seem to be bound with the value of the last bound parameter.
The expected result is:
Array
(
[lsid] => 1
[usid] => agoodid
[source] => home
)
Array
(
[lsid] => 2
[usid] => agoodid
[source] => news
)
How to do this? As a reminder: the aim is to not hard code the name of the parameter in bindParam.
I got the binParam function wholy wrong. it is attaching to the given parameter in the sql query a reference to the given variable in php.
I have to use bindValue instead.
This question already has answers here:
Create flat array of individual values from rows of comma-separated values fetched from a database table
(5 answers)
Closed 6 months ago.
I know that there are a lot of similar threads on Stack Overflow, but none of them works in my case.
My goal is to get the unique show genres from the database. They are stored (1,2,3 or more) comma separated in the show_genres column.
$link = mysqli_connect('127.0.0.1', 'root', 'pw', 'db');
$query = "SELECT show_genres FROM tv_shows";
$result = mysqli_query($link, $query);
foreach ($result as $value) {
$sh_genres = $value['show_genres'];
$sh_genres_array = array_map('trim', explode(',',$sh_genres));
// $doesnt_work = call_user_func_array("array_merge",
$sh_genres_array); // doesn't work for me
echo '<pre>' . var_export($sh_genres_array, true) . '</pre>';
}
My result is as follows:
array (
0 => 'Drama',
1 => 'Action',
2 => 'Crime',
)
array (
0 => 'Drama',
1 => 'Crime',
)
array (
0 => 'Drama',
1 => 'Thriller',
)
array (
0 => 'DIY',
)
array (
0 => 'Drama',
1 => 'Mystery',
2 => 'Supernatural',
)
However, I need just one array which contains the unique values, such as:
array (
0 => 'Drama',
1 => 'Mystery',
2 => 'Supernatural',
4 => 'Thriller',
5 => 'DIY',
6 => 'Crime',
7 => 'etc...'
)
If I try to create some array before the foreach loop and then store the data into it, such approach doesn't give a result as well.
Perhaps, there is a more simple solution by the means of SQL!?!?
Please try this code
In SQL
$query = "SELECT show_genres FROM tv_shows GROUP BY show_genres";
In PHP
$newArray = array();
foreach ($result as $value) {
$sh_genres = $value['show_genres'];
$sh_genres_array = array_map('trim', explode(',',$sh_genres));
$newArray = array_merge($newArray , $sh_genres_array );
}
$newUniqueArray = array_unique($newArray);
try using this code
$link = mysqli_connect('127.0.0.1', 'root', 'pw', 'db');
$query = "SELECT show_genres FROM tv_shows";
$result = mysqli_query($link, $query);
$sh_genres_array = [];
foreach ($result as $value) {
$sh_genres = $value['show_genres'];
$sh_genres_array = array_merge(
$sh_genres_array ,
array_map('trim', explode(',',$sh_genres))
);
}
echo '<pre>' . var_export(array_unique($sh_genres_array), true) . '</pre>';
Update
Please consider normalizing your database
Not sure but try this.
$genre_arr = RecursiveIteratorIterator(new RecursiveArrayIterator($sh_genres_array));
$unique_genre = array_unique($genre_arr);
Learning PHP and creating associative arrays.
Trying to create associative array that describes an activity. An activity for this example is 354 and 355.
This is my current code:
$query = $db->prepare('SELECT item_id FROM kh_program_item_info WHERE '. $where);
$query->execute();
if($query->rowCount() > 0){
while($john = $query->fetch(PDO::FETCH_OBJ)){
$key1 = $john->item_id;
$report-> $key1= array();
}
foreach ($report as $key=>$johnval) {
$where = 'item_id = ' . $key;
$query = $db->prepare('SELECT activity_desc, DATE_FORMAT(activity_date,"%d/%m/%Y") AS activityDate FROM kh_program_items WHERE '. $where);
$query->execute();
$results = $query->fetch(PDO::FETCH_OBJ);
$report->$key = $results;
echo '<pre>';
echo print_r($report);
echo '</pre>';
}
} else {
echo '<p>there are no activities</p>';
}
this will yield results.
stdClass Object
(
[354] => stdClass Object
(
[activity_desc] => <p>Send Activity</p>
[activityDate] => 08/11/2016
)
[355] => stdClass Object
(
[activity_desc] => <p>Send Activity 2</p>
[activityDate] => 11/11/2016
)
)
I am now trying to add more information for 354 and 355.
I have revisited the code and here is new code:
$query = $db->prepare('SELECT item_id FROM kh_program_item_info WHERE '. $where);
$query->execute();
if($query->rowCount() > 0){
while($john = $query->fetch(PDO::FETCH_OBJ)){
$key1 = $john->item_id;
$report-> $key1= array();
}
foreach ($report as $key=>$johnval) {
$where = 'item_id = ' . $key;
$query = $db->prepare('SELECT activity_desc, DATE_FORMAT(activity_date,"%d/%m/%Y") AS activityDate FROM kh_program_items WHERE '. $where);
$query->execute();
$results = $query->fetch(PDO::FETCH_OBJ);
$report->$key = $results;
$query = $db->prepare('SELECT info_value FROM kh_program_item_info WHERE '. $where .' AND info_type="program_category"');
$query->execute();
$info_value = $query->fetch(PDO::FETCH_OBJ);
$where = 'category_id = ' . $info_value->info_value;
$query = $db->prepare('SELECT category_name FROM kh_program_categories WHERE '. $where);
$query->execute();
$actcategories = $query->fetch(PDO::FETCH_OBJ);
$report->$key = $actcategories;
echo '<pre>';
echo print_r($report);
echo '</pre>';
}
} else {
echo '<p>there are no activities</p>';
}
this will obviously overwrite what I have created and yield the following results:
stdClass Object
(
[354] => stdClass Object
(
[category_name] => Parent Input
)
[355] => stdClass Object
(
[category_name] => Children's Menu
)
)
The problem is $myactivity->$key = $actcategories;.
How do I append to the end without overwriting information?
I need to yield this result
stdClass Object
(
[354] => stdClass Object
(
[activity_desc] => <p>Send Activity</p>
[activityDate] => 08/11/2016
[category_name] => Parent Input
)
[355] => stdClass Object
(
[activity_desc] => <p>Send Activity 2</p>
[activityDate] => 11/11/2016
[category_name] => Children's Menu
)
)
Thanks in advance.
You'll need to build your array first and then, send it to the object.
i.e. :
foreach ($report as $key=>$johnval) {
$where = 'item_id = ' . $key;
$query = $db->prepare('SELECT activity_desc, DATE_FORMAT(activity_date,"%d/%m/%Y") AS activityDate FROM kh_program_items WHERE '. $where);
$query->execute();
// build first array
$result_first_query = $query->fetch(PDO::FETCH_OBJ);
$query = $db->prepare('SELECT info_value FROM kh_program_item_info WHERE '. $where .' AND info_type="program_category"');
$query->execute();
$info_value = $query->fetch(PDO::FETCH_OBJ);
$where = 'category_id = ' . $info_value->info_value;
$query = $db->prepare('SELECT category_name FROM kh_program_categories WHERE '. $where);
$query->execute();
// build second array
$result_second_query = $query->fetch(PDO::FETCH_OBJ);
// put them together in $report->$key
$report->$key = $result_first_query + $result_second_query;
echo '<pre>';
print_r($report);
echo '</pre>';
}
Hope it helps.
I did manage to push after i used fetch_assoc.
I guess it was just format it didnt like but thank you.
I'm storing a JSON array in a mysql TEXT field using PDO. (encoded with json_encode())
Once I get the data, if I do json_decode the result is NULL.
It seems that PDO is replacing every " with ".
I have already use PDO and JSON together multiple times, but this is the first time I got this problem so I don't understand what's happening.
I'm on PHP 5.4.4
Also, the JSON is sent with AJAX for your information
Thanks if you can help.
Example of JSON in the table :
{"type_voie":"BD","indice_repetition":"T","num_voie":"121","nom_voie":"NOM_RUE","infos_voie":"NOM_RUE2","distribution_speciale":"BP789","cp":"34000","ville":"MONTPELLIER","bureau_distributeur":""}
What i really see with var_dump :
{"type_voie":"BD","indice_repetition":"T","num_voie":"121","nom_voie":"NOM_RUE","infos_voie":"NOM_RUE2","distribution_speciale":"BP789","cp":"34000","ville":"MONTPELLIER","bureau_distributeur":""}
This is inserted with a prepared query
Code for retrieve DATA :
$formDataSQL = '
SELECT * FROM '.$this->prefix.'
WHERE formalite_id = '.$this->proc_id.'
';
$formDataReq = self::$db->prepare($formDataSQL);
$formDataReq->execute();
$formData = $formDataReq->fetch(PDO::FETCH_ASSOC);
Then on the JSON field :
$addrData = json_decode(str_replace('"', '"', $champ['value']), true); // WORKING BUT NOT MAINTAINABLE
$addrData = json_decode($champ['value'], true); // NOT WORKING => NULL + JSON ERROR = JSON_ERROR_SYNTAX
Here is a simplified example of my insert code :
foreach($saveData['personne_physique'] as $field => $value){
if(is_array($value)) $value = json_encode($value);
$param = ':'.$field;
$fields .= $field.'='.$param.', ';
$values[$param] = $value;
}
$fields = trim($fields, ', ');
$persPhysSQL = "UPDATE personne_physique SET $fields WHERE personne_id = ".$this->id;
$persPhysReq = self::$db->prepare($persPhysSQL);
$persPhysReq->execute($values);
Here is how I'm connecting :
$host = 'mysql:dbname='.BDD_NAME.';host='.BDD_HOST.';charset=utf8';
$user = BDD_USER;
$pass = BDD_PASS;
$db = new PDO($host, $user, $pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8") );
This is really strange :(
Here is my example script based on your data example:
<?php
try {
$Connection = new PDO('mysql:host=localhost;dbname=testing', USER, PASS);
$Connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo 'Unable to connect to database' . "\n";
}
$id = $argv[1];
try {
$data = $Connection->prepare('SELECT * FROM `stackoverflow_26399231` WHERE ID = :id');
$data->bindParam(':id', $id, PDO::PARAM_INT);
$data->execute();
while($row = $data->fetch(PDO::FETCH_OBJ)){
print_r($row);
print_r(json_decode($row->data));
}
$Connection = null;
}catch(PDOException $e){
echo 'Error executing query: ' . $e->getMessage() . "\n";
}
?>
The database table looks like this:
*************************** 1. row ***************************
id: 1
data: {"type_voie":"BD","indice_repetition":"T","num_voie":"121","nom_voie":"NOM_RUE","infos_voie":"NOM_RUE2","distribution_speciale":"BP789","cp":"34000","ville":"MONTPELLIER","bureau_distributeur":""}
When you run the script in the CLI, you get this back:
stdClass Object (
[id] => 1
[data] => {"type_voie":"BD","indice_repetition":"T","num_voie":"121","nom_voie":"NOM_RUE","infos_voie":"NOM_RUE2","distribution_speciale":"BP789","cp":"34000","ville":"MONTPELLIER","bureau_distributeur":""}
)
stdClass Object (
[type_voie] => BD
[indice_repetition] => T
[num_voie] => 121
[nom_voie] => NOM_RUE
[infos_voie] => NOM_RUE2
[distribution_speciale] => BP789
[cp] => 34000
[ville] => MONTPELLIER
[bureau_distributeur] =>
)
How does my script differ to yours? I'm not able to reproduce the issue.
UPDATE:
My update script following your example:
try {
$Connection = new PDO('mysql:host=localhost;dbname=testing', USER, PASS);
$Connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo 'Unable to connect to database' . "\n";
}
$id = $argv[1];
$ary = array(
'foo' => 'bar',
'bar' => 'foo',
'a' => 'b',
'c' => 'd',
'e' => 'f'
);
try {
$fields = 'data=:data';
$values = array('data' => json_encode($ary));
$update = $Connection->prepare("UPDATE `stackoverflow_26399231` SET $fields WHERE ID = $id");
$update->execute($values);
$Connection = null;
}catch(PDOException $e){
echo 'Error executing query: ' . $e->getMessage() . "\n";
}
Using the same script to receive as above but changing from PDO::FETCH_OBJ to PDO::FETCH_ASSOC as that's what you're using, I get this output:
Array
(
[id] => 1
[data] => {"foo":"bar","bar":"foo","a":"b","c":"d","e":"f"}
)
stdClass Object
(
[foo] => bar
[bar] => foo
[a] => b
[c] => d
[e] => f
)
So I can still not reproduce the issue you're having. There must be something different between the two scripts.
I'm trying to write my own little blog.
For this, I use the CodeIgniter framework.
In my blog posts, I also want to save a category and some keywords.
I need to be able to check if a category/keyword already exists, if not a new one needs to be created.
The ID of the existing/new one is saved to be used in a 'connecting' table.
I have the following database setup.
posts - id (AI), title, date, content
categories - id (AI), category
post_categories - post, category
keywords - id (AI), keyword
post_keywords - post, keyword
*AI = Auto Increment
The tables posts, post_categories and post_keywords get updated, the tables categories and keywords remain empty. The category and keyword values in the connecting tables are ofc incorrect.
When troubleshooting my code, I echo'ed every variable in every step.
For some reason, the whole if/else structures checking whether a category or keyword already exists is skipped.
/**
* Insert post into database
* Check if category already exists, if not add it
* Check if keywords already exist, if not add them
* Insert post-category and post-keyword links
* #param array $data
* #return boolean success
*/
function create($data) {
print_r($data);
try {
// posts
$this->db->insert('posts', array(
'title' => $data['title'],
'date' => $data['date'],
'content' => $data['content']
));
$postId = $this->db->insert_id();
echo '<p>Inserted new post (' . $data['title'] . ') at ' . $postId . '</p>';
// category
$category = $data['category'];
$query = $this->db->get_where('categories', array('category' => $category));
$cat = 666;
if ($this->db->count_all_results() == 1) {
foreach ($query->result() as $row) {
$cat = $row->id;
echo '<p>cat = ' . $cat . '</p>';
}
} else {
$this->db->insert('categories', array(
'category' => $category
));
$cat = $this->db->insert_id();
echo '<p>cat = ' . $cat . '</p>';
}
echo '<p>Inserted new category (' . $category . ') at ' . $cat . '</p>';
if($cat == 666) { echo ':('; }
$this->db->insert('post_categories', array(
'post' => $postId,
'category' => $cat
));
// keywords
$keywords = $data['keywords'];
foreach ($keywords as $keyword) {
$query = $this->db->get_where('keywords', array('keyword' => $keyword));
$key = 666;
if ($this->db->count_all_results() == 1) {
foreach ($query->result() as $row) {
$key = $row->id;
echo '<p>key = ' . $key . '</p>';
}
} else {
$this->db->insert('keywords', array(
'keyword' => $keyword
));
$key = $this->db->insert_id();
echo '<p>key = ' . $key . '</p>';
}
echo '<p>Inserted new keyword (' . $keyword . ') at ' . $cat . '</p>';
if($key == 666) { echo ':('; }
$this->db->insert('post_keywords', array(
'post' => $postId,
'keyword' => $key
));
}
return true;
} catch (Exception $e) {
print '<p>ERROR:</p>' . $e;
return false;
}
}
Also in my controller
echo '<p>' . ($this->m_posts->create($post) ? 'no errors :)' : 'error! :(') . '</p>';
Result
Array ( [title] => Foo Bar [date] => 2014-05-22 [content] => lorum ipsum dolore si amet [category] => Category [keywords] => Array ( [0] => Some [1] => Keywords ) )
Inserted new post (Foo Bar) at 2
Inserted new category (Category) at 666
:(
Inserted new keyword (Some) at 666
:(
Inserted new keyword (Keywords) at 666
:(
no errors :)
In my database
POSTS
stdClass Object ( [id] => 1 [title] => Title [date] => 2014-05-22 [content] => okokokokokokok )
stdClass Object ( [id] => 2 [title] => Foo Bar [date] => 2014-05-22 [content] => lorum ipsum dolore si amet )
CATEGORIES
POST_CATEGORIES
stdClass Object ( [post] => 1 [category] => 666 )
stdClass Object ( [post] => 2 [category] => 666 )
KEYWORDS
POST_KEYWORDS
stdClass Object ( [post] => 1 [keyword] => 666 )
stdClass Object ( [post] => 2 [keyword] => 666 )
stdClass Object ( [post] => 2 [keyword] => 666 )
note: I use 99 as a temp value to test if the variable was filled because I first thought the variable's value didn't leave the scope of the if/else. But echo'ing the values of the vars inside the if/else prints nothing. It seems to skip the whole if/else sections.
Adjust the code to:
In if statement num_rows of query it self
If you expect 1 record do a $query->row() directly instead of a foreach loop.
$query = $this->db->get_where('categories', array('category' => $category));
$cat = 666;
if ($query->num_rows() == 1) {
$row = $query->row();
$cat = $row->id;
echo '<p>cat = ' . $cat . '</p>';
} else {
$this->db->insert('categories', array(
'category' => $category
));
$cat = $this->db->insert_id();
echo '<p>cat = ' . $cat . '</p>';
}