Use a generated string for an array in MySQL with variables - php

I need to use a generated string as an array within a MySQL-Loop.
The string/array is built into $argumentarray from the $rows arguments and should after be used as the array of multiSQLarray[]
The function is called as:
multiSQL('**id,title,description,link**','menu')
The string gets correctly generated as
array('id' => $result['id'],'title' => $result['title'],'description' => $result['description'], 'link' => $result['link'])
But instead of using it as a string for the array it just adds it to the array for every result from the sql
Array ( [0] => array('id' => $result['id'],'title' => $result['title'],'description' => $result['description'], 'link' => $result['link']) [1] => array('id' => $result['id'],'title' => $result['title'],'description' => $result['description'], 'link' => $result['link']) )
What i expect is the SQL result as the array
Array ( [0] => Array ( [id] => 1 [title] => Customers [description] => Display the Customer Dashboard [link] => index.php ) [1] => Array ( [id] => 2 [title] => Server [description] => Display all Servers [link] => servers.php ) )
My code:
function multiSQL($rows=null,$table=null,$select=null) {
if(is_null($select)) {$filter="";} else { $filter = ' where '.$select; }
global $pdo;
$sql = 'SELECT '.$rows.' FROM '.$table.$filter.'';
$connection =$pdo->prepare($sql);
$connection->execute();
$multiSQLarray = array();
$arguments = explode(',',$rows);
$argumentarray = "";
$argumentscount=count($arguments);
$loopcount = 1;
foreach($arguments as $argument){
if($loopcount==$argumentscount){
$loopcount++;
$argumentarray = $argumentarray.' \''.$argument.'\' => $result[\''.$argument.'\']';
}
else{
$loopcount++;
$argumentarray = $argumentarray.'\''.$argument.'\' => $result[\''.$argument.'\'],';
}
}
$argumentarray = 'array('.$argumentarray.')';
echo $argumentarray.'<br><br>';
while ($result = $connection->fetch(PDO::FETCH_BOTH)) {
//$multiSQLarray[] = array('id' => $result['id'], 'title' => $result['title'], 'description' => $result['description'], 'link' => $result['link']);
$multiSQLarray[] = $argumentarray;
}
print_r($multiSQLarray);
return $multiSQLarray;

Structured data is structured data. Be it in a string or an array. I can't make sense of some of your code. The arrays in strings... unless you are angling to use an eval. I think that bit confuses your question some.
One thing you need to consider is how exposed you will be to SQL injection. Basically never trust the user right? So, you could do things like predfine, in code, the allowed columns. If the form submitted references something not whitelisted then stop! Also, have to think about escaping the user supplied values.
I'd want my function to accept a known, arguments that make sense for what it needs passed in... Clean things up first and then pass some data types that make the most sense to the function. Maybe something like...
/**
* #param string $table
* #param array $fields
* #param array $criteria (key/value pairs where key is field and value is scalar)
*/
function buildQuery($table, $fields, $criteria) {
$where = [];
$whereVals = [];
foreach($criteria as $k => $v) {
$where[] = "({$k} = ?)";
$whereVals[] = $v;
}
$where = implode(' AND ', $where);
$fields = implode(', ', $fields);
$sql = "SELECT {$fields} FROM {$table} WHERE {$where}";
//eg. SELECT id, name, bar FROM fooTable WHERE (id = ?) AND (name = ?)
$query = $pdo->prepare($sql);
$retval = $query->execute($whereVals);
return $retval;
}
$response = buildQuery( 'fooTable',
['id', 'name', 'bar'],
[
'id' => 5,
'name' => 'john'
]);
Maybe look at some frameworks or an ORM like Doctrine? Can see some good examples of OOP representations of a select statement. Makes dynamic query building a lot easier. End up with something DRYer too.

Related

Php array and json

help me to convert the following array in to json.
I tried to convert the array.
Array
(
[0] => Array
(
[c_code] => 200001
[itemname] => 303 10CAP
[c_pack_code] => PK0075
[c_web_img_link] =>
)
[1] => Array
(
[c_code] => 200005
[itemname] => 3P 4TAB
[c_pack_code] =>
[c_web_img_link] =>
)
)
current result for the following code is
public function searchOrder($idx, $data) {
if (!empty($data)) {
$result = OrderbukModel::func_get_searchlist($idx,$data);
if (!empty($result)) {
$resultArray[] = $result;
print_r(json_encode($result));
} else {
$resultArray[$idx] = ["Mysql returns empty result !"];
print_r(json_encode($resultArray));
exit;
}
}
}
now i got the result is like
[{"c_code":"200001","itemname":"303 10CAP","c_pack_code":"PK0075","c_web_img_link":""},{"c_code":"200005","itemname":"3P 4TAB","c_pack_code":"","c_web_img_link":""}]
But I need the result as follows
[{"c_code":"2000001","c_code":"200005"},
{"itemname":"303 10CAP","itemname":"3P 4TAB"},
{"c_pack_code":"PK0075","c_pack_code":""},
{"c_web_img_link":"","c_web_img_link":""}]
Example of how you can you make the json from array. Collect the data in two different array and after loop marge them and store the result in another array after that encode them.
Note: Your desired JSON is not a valid format, you can't use same index
for two data.
Online Example: https://3v4l.org/kdPDI
$arr = array(
array(
'c_code' => '200001',
'itemname' => '303 10CAP',
'c_pack_code' => 'PK0075',
'c_web_img_link' => ''
),
array(
'c_code' => '200005',
'itemname' => '3P 4TAB',
'c_pack_code' => '',
'c_web_img_link' => ''
)
);
$res1 = array();
$res2 = array();
foreach($arr as $val){
$res1['c_code'][] = $val['c_code'];
$res1['itemname'][] = $val['itemname'];
$res2['c_pack_code'][] = $val['c_pack_code'];
$res2['c_web_img_link'][] = $val['c_web_img_link'];
}
$out = array(array_merge($res1, $res2));
echo json_encode($out);

Searching for a value in an array using PHP

I have a list of users in my mongodb database, which can then follow each other -pretty standard. Using php I want to check if a specific user is following another user. My data looks like this.
array (
'_id' => ObjectId("56759157e1095db549d63af1"),
'username' => 'Joe',
'following' =>
array (
0 =>
array (
'username' => 'John',
),
1 =>
array (
'username' => 'Tom',
),
),
)
array (
'_id' => ObjectId("56759132e1095de042d63af4"),
'username' => 'Tom',
'following' =>
array (
0 =>
array (
'username' => 'Joe',
),
1 =>
array (
'username' => 'John',
),
2 =>
array (
'username' => 'Sam',
),
),
)
I want a query that will check if Joe is following Sam (which he's not) - so it would produce no results. However, if I was to query the database to check if Tom was following Sam, then it would produce a result to indicate he is (because he is). Do you know how I would do this in PHP? I've experimented with Foreach loops, but I haven't been able to get the results I want.
Make it by DB query, by php it will take more resources
Still if you want by php you can make it so
$following=false;
foreach($data as $v) if ($v['username'] == 'Joe') {
foreach($v['following'] as $v1) if (in_array('Sam', $v1)) {
$following=true;
break 2;
}
}
echo $following;
Such queries are best done in SQL, but if you insist on a PHP-based solution I would suggest to turn the data structure into items keyed by name. Once you have that it is a piece of cake to find relationships:
function organisePersons($data) {
$persons = array();
foreach($data as $person) {
$list = array();
foreach($person["following"] as $following) {
$list[$following["username"]] = $following["username"];
}
$person["following"] = $list;
$person["followedBy"] = array();
$persons[$person["username"]] = $person;
}
// link back to get all "followedBy":
// You can skip this block if you don't need "followedBy":
foreach ($persons as $person) {
foreach($person["following"] as $following) {
echo $person["username"] . " f. $following<br>";
if (!isset($persons[$following])) {
$persons[$following] = array(
"_id" => null, // unknown
"username" => $following,
"following" => array(),
"followedBy" => array()
);
}
$persons[$following]["followedBy"][] = $person["username"];
}
}
// return the new structure
return $persons;
}
So first call the function above with the data you have:
$persons = organisePersons($data);
And then you can write this:
if (isset($persons["Joe"]["following"]["Sam"])) {
echo "Joe is following Sam"; // not in output
};
if (isset($persons["Tom"]["following"]["Sam"])) {
echo "Tom is following Sam"; // in output
};
But also:
echo "Tom is following " . implode($persons["Tom"]["following"], ", ");
// Output: Tom is following Joe, John, Sam
And even the reverse question "Tom is followed by who?":
echo "Tom is followed by " . implode($persons["Tom"]["followedBy"], ", ");
// Output: Tom is followed by Joe

Fetch array using both if and while doesn't work

Basically I have 2 methods in the same class, getMovie and getGenres. They are very similar but One doesn't return what I expect.
Here's getMovie method:
public function getMovie($argType, $arg){
$movieQuery = "SELECT id,
rt_id,
imdb_id,
url,
rt_url,
type,
adult,
DATE_FORMAT(release_date, '%Y') AS year,
date_added,
title,
runtime,
budget,
revenue,
homepage,
rating,
tagline,
overview,
popularity,
image,
backdrop,
trailer
FROM movies
WHERE " . $argType . " = " . $arg;
$movieResult = $this->_query($movieQuery);
$movies = array();
if($movieResult->fetch_array(MYSQLI_ASSOC)){
while($m = $movieResult->fetch_array(MYSQLI_ASSOC)){
$movies[] = array( 'title' => $m['title'],
'duplicate' => $m['duplicate'],
'url' => $m['url'],
'rt_url' => $m['rt_url'],
'release_date' => $m['release_date'],
'date_added' => $m['date_added'],
'type' => 'movie',
'adult' => $m['adult'],
'id' => $id,
'rt_id' => $m['rt_id'],
'imdb_id' => $m['imdb_id'],
'rating' => $m['rating'],
'tagline' => $m['tagline'],
'overview' => $m['overview'],
'popularity' => $m['popularity'],
'runtime' => $m['runtime'],
'budget' => $m['budget'],
'revenue' => $m['revenue'],
'homepage' => $m['homepage'],
'image' => $m['image'],
'backdrop' => $m['backdrop'],
'trailer' => $m['trailer'] );
}
return $movies;
}
else{
return false;
}
Here's getGenres method:
public function getGenres($movieId = NULL){
$genresQuery = "";
if($movieId != NULL){
$genresQuery = "SELECT id,
name
FROM genres
WHERE id = ANY (
SELECT genre_id
FROM movie_genres
WHERE movie_id = " . $movieId . ")";
}
else{
$genresQuery = "SELECT id,
name
FROM genres";
}
$genresResult = $this->_query($genresQuery);
$genres = array();
if($genresResult->fetch_array(MYSQLI_ASSOC)){
while($genre = $genresResult->fetch_array(MYSQLI_ASSOC)){
$genres[] = array( 'id' => $genre['id'],
'name' => $genre['name'] );
}
return $genres;
}
else{
return false;
}
}
And here's how I call them:
$mov = $movie->getMovie(2207);
print_r($mov); // output: Array()
$gen = $movie->getGenres(2207);
print_r($gen); // output: Array(values inside)
Both queries do actually return expected values but getMovies method doesn't work with the if statement. It works fine if I just have while loop.
I am using if as well as while as I heard that while loop can sometimes execute even when there's not values. Is there any truth to this? If there is indeed a reason to use an if statement as well as wile loop then why doesn't it work with getMovies method?
Edit 1: I tried storing the array like so but that resulted in a memory related error:
$r = $genresResult->fetch_array(MYSQLI_ASSOC);
if($r){
while($r){
$genres[] = array( 'id' => $genre['id'],
'name' => $genre['name'] );
}
return $genres;
}
I am using if as well as while as I heard that while loop can sometimes execute even when there's not values. Is there any truth to this?
No, according to the php manual mysqli_result::fetch_array returns an array of strings that corresponds to the fetched row or NULL if there are no more rows in resultset.
Null is falsy so the while loop will not be entered.
Although the if statement is unnecessary if you had one you would use mysqli_result::$num_rows to check if the query returned any rows.
if($movieResult->num_rows > 0){
while($m = $movieResult->fetch_array(MYSQLI_ASSOC)){
...
}
}

Most efficient way to replace empty values in an array

Is there a better way of doing this PHP code? What I'm doing is looping through the array and replacing the "title" field if it's blank.
if($result)
{
$count = 0;
foreach($result as $result_row)
{
if( !$result_row["title"] )
{
$result[$count]["title"] = "untitled";
}
$count++;
}
}
Where $result is an array with data like this:
Array
(
[0] => Array
(
[title] => sdsdsdsd
[body] => ssdsd
)
[1] => Array
(
[title] => sdssdsfds
[body] => sdsdsd
)
)
I'm not an experienced PHP developer, but I guess that the way I've proposed above isn't the most efficient?
Thanks
if($result) {
foreach($result as $index=>$result_row) {
if( !$result_row["title"] ) {
$result[$index]["title"] = "untitled";
}
}
}
You don't need to count it. It's efficient.
if ($result)
{
foreach($result as &$result_row)
{
if(!$result_row['title'])
{
$result_row['title'] = 'untitled';
}
}
}
Also, you may want to use something other than a boolean cast to check the existence of a title in case some young punk director releases a movie called 0.
You could do something like if (trim($result_row['title']) == '')
Mixing in a little more to #Luke's answer...
if($result) {
foreach($result as &$result_row) { // <--- Add & here
if($result_row['title'] == '') {
$result_row['title'] = 'untitled';
}
}
}
The key is the & before $result_row in the foreach statement. This make it a foreach by reference. Without that, the value of $result_row is a copy, not the original. Your loop will finish and do all the processing but it won't be kept.
The only way to get more efficient is to look at where the data comes from. If you're retrieving it from a database, could you potentially save each record with an "untitled" value as the default so you don't need to go back and put in the value later?
Another alternative could be json_encode + str_replace() and then json_decode():
$data = array
(
0 => array
(
'title' => '',
'body' => 'empty',
),
1 => array
(
'title' => 'set',
'body' => 'not-empty',
),
);
$data = json_encode($data); // [{"title":"","body":"empty"},{"title":"set","body":"not-empty"}]
$data = json_decode(str_replace('"title":""', '"title":"untitled"', $data), true);
As a one-liner:
$data = json_decode(str_replace('"title":""', '"title":"untitled"', json_encode($data)), true);
Output:
Array
(
[0] => Array
(
[title] => untitled
[body] => empty
)
[1] => Array
(
[title] => set
[body] => not-empty
)
)
I'm not sure if this is more efficient (I doubt it, but you can benchmark it), but at least it's a different way of doing the same and should work fine - you have to care about multi-dimensional arrays if you use the title index elsewhere thought.
Perhaps array_walk_recursive:
<?php
$myArr = array (array("title" => "sdsdsdsd", "body" => "ssdsd"),
array("title" => "", "body" => "sdsdsd") );
array_walk_recursive($myArr, "convertTitle");
var_dump($myArr);
function convertTitle(&$item, $key) {
if ($key=='title' && empty($item)) {$item = "untitled";}
}
?>
If you want sweet and short, try this one
$result = array(
array(
'title' => 'foo',
'body' => 'bar'
),
array(
'body' => 'baz'
),
array(
'body' => 'qux'
),
);
foreach($result as &$entry) if (empty($entry['title'])) {
$entry['title'] = 'no val';
}
var_dump($records);
the empty() will do the job, see the doc http://www.php.net/manual/en/function.empty.php

Create array of hierarchical directories in PHP

I have the following code (I know that this code is not optimized but it's not for discussion):
function select_categories($cat_id)
{
$this->db = ORM::factory('category')
->where('parent', '=', $cat_id)
->find_all();
foreach ($this->db as $num => $category)
{
if($category->parent == 0)
{
$this->tmp[$category->parent][$category->id] = array();
}
else {
$this->tmp[$category->parent][$category->id] = array();
}
$this->select_categories($category->id);
}
return $this->tmp;
}
Function returns this array:
array(3) (
0 => array(2) (
1 => array(0)
2 => array(0)
)
2 => array(1) (
3 => array(0)
)
3 => array(2) (
4 => array(0)
5 => array(0)
)
)
But how should I change the code
else {
$this->tmp[$category->parent][$category->id] = array();
// ^^^^^^^^^^^^^^^^^^^^^^ (this bit)
}
To merge array[3] to array[2][3] for example (because array[3] is a subdirectory of array[2] and array[2] is a subdirectory of array[0][2]), so, I need to make this (when I don't know the level of subdirectories):
array (
0 => array (
1 => array
2 => array (
3 => array (
4 => array
5 => array
)
)
)
)
A long time ago I wrote some code to do this in PHP. It takes a list of entities (in your case, categories) and returns a structure where those entities are arranged in a tree. However, it uses associative arrays instead of objects; it assumes that the “parent” ID is stored in one of the associative array entries. I’m sure that you can adapt this to your needs.
function make_tree_structure ($nontree, $parent_field)
{
$parent_to_children = array();
$root_elements = array();
foreach ($nontree as $id => $elem) {
if (array_key_exists ($elem[$parent_field], $nontree))
$parent_to_children [ $elem[$parent_field] ][] = $id;
else
$root_elements[] = $id;
}
$result = array();
while (count ($root_elements)) {
$id = array_shift ($root_elements);
$result [ $id ] = make_tree_structure_recurse ($id, $parent_to_children, $nontree);
}
return $result;
}
function make_tree_structure_recurse ($id, &$parent_to_children, &$nontree)
{
$ret = $nontree [ $id ];
if (array_key_exists ($id, $parent_to_children)) {
$list_of_children = $parent_to_children [ $id ];
unset ($parent_to_children[$id]);
while (count ($list_of_children)) {
$child = array_shift ($list_of_children);
$ret['children'][$child] = make_tree_structure_recurse ($child, $parent_to_children, $nontree);
}
}
return $ret;
}
To see what this does, first try running it on a structure like this:
var $data = array (
0 => array('Name' => 'Kenny'),
1 => array('Name' => 'Lilo', 'Parent' => 0),
2 => array('Name' => 'Adrian', 'Parent' => 1)
3 => array('Name' => 'Mark', 'Parent' => 1)
);
var $tree = make_tree_structure($data, 'Parent');
If I’m not mistaken, you should get something like this out: (the “Parent” key would still be there, but I’m leaving it out for clarity)
array (
0 => array('Name' => 'Kenny', 'children' => array (
1 => array('Name' => 'Lilo', 'children' => array (
2 => array('Name' => 'Adrian')
3 => array('Name' => 'Mark')
)
)
)
Examine the code to see how it does this. Once you understand how this works, you can tweak it to work with your particular data.
Assuming you dont want any data/children tags in your array:
foreach ($this->db as $num => $category)
{
// save the data to the array
$this->tmp[$category->id] = array();
// save a reference to this item in the parent array
$this->tmp[$category->parent][$category->id] = &$this->tmp[$category->id];
$this->select_categories($category->id);
}
// the tree is at index $cat_id
return $this->tmp[$cat_id];
If you just need to retrieve the full tree out of the database, you can even simplify your query (get all records at once) and remove the recursive call in this function. You will need an extra check that will only set the $this->tmp[$catagory->id] when it does not exist and else it should merge the data with the existing data.

Categories