SQL query and preg_match - php

Need your help with sql query and php.
I have to pieces of code here:
1.
$sql = "SELECT SUBSTR(n.`title`, 1,1) FROM node n WHERE n.`type` = 'type1'";
$results = db_query($sql);
while ($fields = db_fetch_array($results)) {
foreach($fields as $key => $value) {
echo $value;
}
}
The code above returns first letters of my article titles (table - node, columns - type, title) like this - NHDKFLF...
2.
if (preg_match ('/A/i', $string)) {
echo ('Contains letter A'); //
}
else {
echo ('Nothing'); //
}
And the second part checks if the string contains certain letters.
Now, the question is how to combine these two pieces of code? I mean how to pull data from DB and check if it has certain letters.
Thanks in advance.

Two options come to mind: Do what you're doing now, or re-write the SQL to do both at once.
Option 1:
$sql = "SELECT SUBSTR(n.`title`, 1,1) FROM node n WHERE n.`type` = 'type1'";
$results = db_query($sql);
while ($fields = db_fetch_array($results)) {
foreach($fields as $key => $value) {
if (preg_match ('/A/i', $value)) {
echo ('Contains letter A'); //
} else {
echo ('Nothing'); //
}
}
}
Option 2:
$sql = "SELECT SUBSTR(n.`title`, 1,1) FROM node n WHERE n.`type` = 'type1' AND SUBSTR(n.`title`, 1,1) = 'A' ";
Depending on the rest of the details of your project there is probably a better way to handle this.

Why wouldn't you just query for the ones you want?
... where SUBSTR(n.`title`, 1,1) = 'A' ...
If you must filter in your code, outside the query, then:
foreach($fields as $key => $value) {
if (preg_match ('/A/i', $value)) {
...
}

Related

php for each loop conditional total

I have a foreach loop, I am trying to get total count value which works fine. But the problem is that, most of the hard_disk3 column rows in database contains value "None", I want php to not count where row value is "None".
Here is the php code, what can I do to achieve this?
<?php
$type="systype, hard_disk3";
$typeQuery = $basequery." GROUP BY ".$type;
// Perform the Query
$objDbResultByType = $objDatabase->Query($typeQuery);
$imran9 = array();
foreach ($objDbResultByType as $row) {
$result = "{ label: \"".$row['systype']." ".$row['hard_disk3']."\", y: " .$row['total']." },";
array_push($imran9,$result);
}
$lastIndex = count($imran9)-1;
$lastValue = $imran9[$lastIndex];
$imran9[$lastIndex] = rtrim($lastValue, ',');
?>
You can achieve this in two ways, first one is already mentioned by Sherif (which is the better way to do that), second one in PHP is really easy. Try this:
<?php
$type="systype, hard_disk3";
$typeQuery = $basequery." GROUP BY ".$type;
// Perform the Query
$objDbResultByType = $objDatabase->Query($typeQuery);
$imran9 = array();
foreach ($objDbResultByType as $row) {
if ($row['hard_disk3'] == "None")
{
continue;
}
$result = "{ label: \"".$row['systype']." ".$row['hard_disk3']."\", y: " .$row['total']." },";
array_push($imran9,$result);
}
$lastIndex = count($imran9)-1;
$lastValue = $imran9[$lastIndex];
$imran9[$lastIndex] = rtrim($lastValue, ',');
?>
Or you could try:
if ($row['hard_disk3'] != "None") {
$result = "{ label: \"".$row['systype']." ".$row['hard_disk3']."\", y: " .$row['total']." },";
array_push($imran9,$result);
}
You should instead just specify that in your SQL query. SELECT COUNT(hard_disk3) FROM table WHERE hard_disk3 != "None" that way your dbms just returns the total row count and you neither need a foreach loop nor do you need PHP to do any real work to get to your result.

Writing a PDO search query from a PHP array

I'm building an application using PHP 7 and a PDO connection to a MySQL database.
One part of the application contains a search form which allows a user to search for a training course by 3 different fields: the course category, the course name, and a date.
The types of elements on the form are:
Course category - dropdown, with numerical (int) ID's.
Course name - text input
Date - date picker (using HTML 5 type="date" parameter to get a calendar in the browser).
These fields can be used in conjunction, or on their own. This means a user could search, for example, just by (1), or (2 & 3), or all (1 & 2 & 3).
I've written the PHP to get the POST data and it's now in an array - for example:
$search_data = [
'category' => 3,
'name' => 'Hazard training',
'date' => ''
]
I want to use this within a PDO query but I don't know what the best way to write it is because (1) and (3) would be an = query condition, whereas (2) is a LIKE. My solution was going to be looping through the search terms and then trying to construct a query, e.g.
$sql = ' WHERE ';
foreach ($search_data as $key => $value) {
if ($key == 'category') {
$sql .= ' category = ' . $value;
}
if ($key == 'course_name') {
$sql .= ' course_name LIKE % ' . $value ' % ';
}
if ($key == 'date') {
$sql .= ' date = ' . $value;
}
}
The trouble with this is it doesn't work because of having to bind the parameters in PDO. It also doesn't work because I can't find a way to get the AND between each query (if there is a preceding statement).
I'm lost with this now and unsure what the best way to write this is.
Any help would be appreciated.
Edit: I realise that hardcoding the names, e.g. ($key == 'course_name') isn't ideal, but this is only being done because of the different query conditions (LIKE vs =). I assume that one could make $search_data multi-dimensional to say which type of query it was, but this is beyond my initial problem and probably another post.
Here`s a simple solution to your problem:
$sql = 'SELECT ..... FROM ... WHERE 1 ';
$where = '';
$pdoData = [];
foreach ($search_data as $key => $value) {
if(!$value) continue; // skip empty values
if ($key === 'category') {
$pdoData[':category'] = $value;
$where .= ' AND category = :category ';
}
if ($key === 'course_name') {
$pdoData[':course_name'] = '%'.$value.'%';
$where .= ' AND course_name LIKE (:course_name) ';
}
if ($key === 'date') {
$pdoData[':date'] = $value;
$where .= ' AND date = :date ';
}
}
$sql = $sql.$where;
$stmt = $this->ci->db->prepare($sql);
$stmt->execute($pdoData);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
And you have $pdoDate array holding the binded data.

Loop through an array to create an SQL Query

I have an array like the following:
tod_house
tod_bung
tod_flat
tod_barnc
tod_farm
tod_small
tod_build
tod_devland
tod_farmland
If any of these have a value, I want to add it to an SQL query, if it doesnt, I ignore it.
Further, if one has a value it needs to be added as an AND and any subsequent ones need to be an OR (but there is no way of telling which is going to be the first to have a value!)
Ive used the following snippet to check on the first value and append the query as needed, but I dont want to copy-and-paste this 9 times; one for each of the items in the array.
$i = 0;
if (isset($_GET['tod_house'])){
if ($i == 0){
$i=1;
$query .= " AND ";
} else {
$query .= " OR ";
}
$query .= "tod_house = 1";
}
Is there a way to loop through the array changing the names so I only have to use this code once (please note that $_GET['tod_house'] on the first line and tod_house on the last line are not the same thing! - the first is the name of the checkbox that passes the value, and the second one is just a string to add to the query)
Solution
The answer is based heavily upon the accepted answer, but I will show exactly what worked in case anyone else stumbles across this question....
I didnt want the answer to be as suggested:
tod_bung = 1 AND (tod_barnc = 1 OR tod_small = 1)
rather I wanted it like:
AND (tod_bung = 1 OR tod_barnc = 1 OR tod_small = 1)
so it could be appended to an existing query. Therefore his answer has been altered to the following:
$qOR = array();
foreach ($list as $var) {
if (isset($_GET[$var])) {
$qOR[] = "$var = 1";
}
}
$qOR = implode(' OR ', $qOR);
$query .= " AND (" .$qOR . ")";
IE there is no need for two different arrays - just loop through as he suggests, if the value is set add it to the new qOR array, then implode with OR statements, surround with parenthesis, and append to the original query.
The only slight issue with this is that if only one item is set, the query looks like:
AND (tod_bung = 1)
There are parenthesis but no OR statements inside. Strictly speaking they arent needed, but im sure it wont alter the workings of it so no worries!!
$list = array('tod_house', 'tod_bung', 'tod_flat', 'tod_barnc', 'tod_farm', 'tod_small', 'tod_build', 'tod_devland', 'tod_farmland');
$qOR = array();
$qAND = array();
foreach ($list as $var) {
if (isset($_GET[$var])) {
if (!empty($qAND)) {
$qOR[] = "$var = 1";
} else {
$qAND[] = "$var = 1";
}
$values[] = $_GET[$var];
}
}
$qOR = implode(' OR ', $qOR);
if ($qOR != '') {
$qOR = '(' . $qOR . ')';
}
$qAND[] = $qOR;
$qAND = implode(' AND ', $qAND);
echo $qAND;
This will output something like tod_bung = 1 AND (tod_barnc = 1 OR tod_small = 1)
As the parameter passed to $_GET is a string, you should build an array of strings containing all the keys above, iterating it and passing the values like if (isset($_GET[$key])) { ...
You could then even take the key for appending to the SQL string.
Their are a lot of ways out their
$list = array('tod_house', 'tod_bung', 'tod_flat', 'tod_barnc', 'tod_farm', 'tod_small', 'tod_build', 'tod_devland', 'tod_farmland');
if($_GET){
$query = "";
foreach ($_GET as $key=>$value){
$query .= (! $query) ? " AND ":" OR ";
if(in_array($key,$list) && $value){
$query .= $key." = '".$value."'";
}
}
}
Sure you have to take care about XSS and SQL injection
If the array elements are tested on the same column you should use IN (...) rather than :
AND ( ... OR ... OR ... )
If the values are 1 or 0 this should do it :
// If you need to get the values.
$values = $_GET;
$tod = array();
foreach($values as $key => $value) {
// if you only want the ones with a key like 'tod_'
// otherwise remove if statement
if(strpos($key, 'tod_') !== FALSE) {
$tod[$key] = $value;
}
}
// If you already have the values.
$tod = array(
'tod_house' => 1,
'tod_bung' => 0,
'tod_flat' => 1,
'tod_barnc' => 0
);
// remove all array elements with a value of 0.
if(($key = array_search(0, $tod)) !== FALSE) {
unset($tod[$key]);
}
// discard values (only keep keys).
$tod = array_keys($tod);
// build query which returns : AND column IN ('tod_house','tod_flat')
$query = "AND column IN ('" . implode("','", $tod) . "')";

Displaying values from mysqli with loop

I need to be able to display the course_desc on line 30, beside the course_name.
<?php
$result = $db->query("select distinct c.dbid, c.course_name, c.course_image, m.module_id, m.module_name, m.module_name_id, m.module_image, m.hasFiles, m.files from courses c join modules_to_courses mc on (c.dbid = mc.courses_id) join modules m on (mc.modules_id = m.module_id)");
$course_name = $db->query("SELECT distinct course_name, course_desc FROM courses");
while ($temp = $course_name->fetch_assoc()) {
$courses[] = $temp['course_name'];
}
$final = array();
// Retrieve results
while ($row = $result->fetch_assoc()) {
// Add to final array via counter if valid course is found
if (in_array($row['course_name'], $courses)) {
$final[$row['course_name']][] = $row;
}
}
// Display if final array is not empty
if (!empty($final)) {
// Loop through each potential course name
foreach ($courses as $name) {
// Output if the course has values within the final array
if (array_key_exists($name, $final)) {
echo '<div>'."\n";
echo ' '. $name . "\n";
echo '<!-- list of modules -->'."\n";
// Loop through internal values
foreach ($final[$name] as $value) {
$module_name = $value['module_name'];
echo ' '. $module_name ."\n";
}
echo ' </div>'."\n";
}
}
}
?>
You already having your course description in $final so you can access it using,
$final[$name]['course_desc']
I have created a paste based on your with changes. Also note that it's need to change your $final array.
distinct course_name, course_desc means you are trying to fetch the values regarding to distinct course_name and distinct course_desc together. You may wanna use group by instead. If I understood correctly, your statement will not bring you distinct course names and their related course desc. (if that is what you want)

Break a special character in MySQL

I have a requirement where I need to check a pipe | in the database. If found I need to play around differently.
Here how my db table looks like //Please check the | character in row 11
And if I run a group by sql command myresult will be
Which is correct.
But my requirement is to break the | in any cell and give the count accordingly. The expected result as
Can this be done using MySQL commands alone or do I need to use some php script as well?
Any snippet will be helpful.
Hope this script might help u
$frt =array();
$stmt = $mysqli->prepare("select `fruits` from `meva`") or $mysqli->error ;
$stmt->execute();
$stmt->bind_result($fruits);
while ($stmt->fetch()) {
$frt[]=$fruits;
}
// var_dump($frt); //check all the fruits is in array
$res = array();
$tot = count($frt);
for($i=0;$i<=$tot;$i++)
{
if(preg_match("/\|/", $frt[$i]))
{
$res[] =explode( '|', $frt[$i]);
}else
{
$res[] = $frt[$i];
}
}
// var_dump($res);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($res));
foreach($it as $v) {
$ary[]=$v;
}
$all_fruits = array();
$tot_ary = count($ary);
for($io=0;$io<=$tot_ary;$io++)
{
if(isset($ary[$io])!='')
{
$all_fruits[] = trim($ary[$io]);
}else
{
continue;
}
}
// var_dump($all_fruits);
$newArray = array_count_values($all_fruits);
foreach ($newArray as $key => $value) {
echo "$key - <strong>$value</strong> <br />";
}
I think you should fix your data. You can run these two statements in a row until all the data is fixed:
INSERT INTO meva (fruits)
SELECT SUBSTR(fruits, LOCATE('|', fruits) - 1) FROM meva
WHERE LOCATE('|', fruits) > 0;
UPDATE meva
SET fruits = SUBSTR(fruits, LOCATE('|', fruits) + 1)
WHERE LOCATE('|', fruits) > 0;
This will fix the table.
However, if it is your interview question (or a school assignment) just to count from the table as it is, then you can only do it if you know the maximum number of pipes in a given row.
So, if the maximum number of pipes in a row is 1, then your select statement would be:
SELECT count(*),
CASE WHEN LOCATE('|', fruits) > 0 THEN SUBSTR(fruits, LOCATE('|', fruits) - 1) ELSE fruits END
FROM meva
GROUP BY CASE WHEN LOCATE('|', fruits) > 0 THEN SUBSTR(fruits, LOCATE('|', fruits) - 1) ELSE fruits END
If you can have more than one pipe in a row, then your CASE statement will be more complex
Actually the best solution is to change your data structure. This current structure is not recommended. each 'cell' has to contain only one value. If you need to store several fuirts for a specific ID, use
id fruit
11 Apple
11 Mango
this might require some adjustments to your code / tables, but it will prevent the need for more future hacks.
You can use php and do it like below
$query = mysql_query("SELECT fruit FROM meva");
$cnt_array = array();
while($row = mysql_fetch_assoc($query)){
$fruits = $row["fruit"];
$fruit = explode("|", $fruits);
foreach($fruit as $fru){
if(array_key_exists($fru,$cnt_array)){
$cnt_array[$fru] = $cnt_array[$fru]+1;
}
else{
$cnt_array[$fru] = 1;
}
}
}
print_r($cnt_array);
NOTE : This code is not tested,please try it and edit accordingly

Categories