Linking fetched data using "LIKE %columname%" for each parameter PHP - php

I have actors field in my movie database which is having many actors in one field separated by comma and fetching them using below code. My requirement is to link all fetched actors. on click on each actor will take to the list of their movie.
Since i am having all actors in one field and separated by commas, struggling to link each of them with separate url
<?php
require('connect');
$filmActor=$_GET['filmActor'];
$sql ="SELECT * FROM films WHERE filmActor LIKE '%$filmActor%' LIMIT 0 , 5;";
$result = mysqli_query($conn, $sql);
while($row = mysqli_fetch_array($result))
{
$filmActor=$row['filmActor'];
$filmName=$row['filmName'];
$url=$row['url'];
echo "
<a href='$url.html'>$filmName</a>: $filmActor<br>
";
}
mysqli_free_result($result);
mysqli_close($conn);
?>
Output i am getting like:
Expected:
Want to pass this parameter:
/actor.php?filmActor=Tom_Hanks, /actor.php?filmActor=Emma_Thompson etc will displace each actors film they have worked on.

This script should work. It takes the $row['filmActor'] and split all the actors into an array by ',', and then we print them out one after one.
Just keep in mind that this can be done a better way, but this should work.
Also, I've added a "mysqli_real_escape_string" to the GET input "$_GET['filmActor']" to prevent SQL injections.
<?php
require('connect');
// Escape the input from the user, preventing SQL injections
$filmActor = mysqli_real_escape_string($conn,$_GET['filmActor']);
$sql ="SELECT * FROM films WHERE filmActor LIKE '%$filmActor%' LIMIT 0 , 5;";
$result = mysqli_query($conn, $sql);
while($row = mysqli_fetch_array($result))
{
$filmActor=$row['filmActor'];
$filmName=$row['filmName'];
$url=$row['url'];
echo "<a href='$url.html'>$filmName</a>:";
// Make an array of the actors by splitting them by ','
$actorsArray = explode(',',$filmActor);
// Loop the array
foreach ($actorsArray as $key => $actor)
{
// Just trim the space in front of name in case there is any
$actor = trim($actor);
// Check if the current key is == to the last key in the array
// so it wont make an ',' in the end of the actors.
if ($key == (count($actorsArray)-1))
echo "<a href='/actor.php?filmActor=$actor'>$actor</a>";
else
echo "<a href='/actor.php?filmActor=$actor'>$actor</a>, ";
}
}
mysqli_free_result($result);
mysqli_close($conn);
Let me know how it works out.
And as tadman said in the comments above "NEVER put $_POST or $_GET data directly into a query, it can be very harmful if someone seeks to exploit your mistake."
Hope it helps!

Related

How can I store large chunks into json file without memory crash?

I have an array $table and it contains 6000 items.
When I want to convert this array to json and store it into a file, my memory crashes.
So I had the idea to break the array into chunks of parts with 500 items:
$table = array_chunk($table, 500);
$table_json = $serializer->serialize($table[0], 'json', $context);
$myfile = fopen($_SERVER['DOCUMENT_ROOT']."/files/myfile.json", "w") or die("Unable to open file!");
file_put_contents($_SERVER['DOCUMENT_ROOT']."/files/myfile.json", $table_json);
This runs fast now, but of course now only 500 items are stored. Is there a way to add the other parts of the $table array without memory crash?
You could do something like this as you mentioned you know how to use array_chunk();
Let's look into simplifying the process with a built-in PHP function called array_chunk();
We'll be using HTML tables for design which isn't recommended. The task is better accomplished with CSS, you can follow same way without HTML and CSS.
Our table :
id datePosted firstName lastName pictureName anotherColumn
1 2013-07-01 John Smith SmithJohn.jpg anotherValue
2 2013-05-06 Elroy Johnson JohnsonElroy.jpg anotherValue
3 2013-06-18 Jake Bible BibleJake.jpg anotherValue
4 2013-07-17 Steve Stevenson StevensonSteve.jpg anotherValue
5 2013-04-08 Bill Smith SmithBill2.jpg anotherValue
Building HTML Tables
PDO query is used to grab the database information with prepared statements, Note that the loop only generates the code to display the columns.
The tests to detect where the rows begin and end are unnecessary.
//INITIALIZE VARIABLES
$colsToDisplay = 3;
$htmlOutput = array();
//GET PICTURE LIST
$sql = "SELECT datePosted, firstName, lastName, pictureName FROM pictureList ORDER BY datePosted DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$htmlOutput[] = "<td><img src='images/{$row['pictureName']}' alt='' /><br />{$row['firstName']} {$row['lastName']}</td>";
}
Once the loop is done, the array containing the column information can be broken into groups of three... or whatever value was assigned to $colsToDisplay, What we did here ? we tooks 3 columns from table, So divide table in two parts.
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
//...
}
//BREAK THE COLUMNS INTO GROUPS
$htmlOutput = array_chunk($htmlOutput, $colsToDisplay);
All that's left is to display the table information. Note that array_chunk() creates a multi-dimensional array. The foreach loop is used to process the groups of columns. Each group is assigned to $currRow which contains an array of columns for the current row. The implode() function is used to quickly display the columns as a string.
Lets continue :
//BREAK THE COLUMNS INTO GROUPS
$htmlOutput = array_chunk($htmlOutput, $colsToDisplay);
//DISPLAY TABLE
print '<table>';
foreach($htmlOutput as $currRow) {
print '<tr>' . implode('', $currRow) . '</tr>';
}
print '</table>';
Checking For Missing Column Tags
One thing you may have noticed is the code to add missing columns was left out.
In other words, this example results in an HTML table where the last row only has two columns.
Apparently, the missing columns aren't needed according to the W3C Markup Validation Serviceā€¦ so they weren't included. However, they can be added by running the following code right before array_chunk() is called.
$colsDifference = count($htmlOutput) % $colsToDisplay;
if($colsDifference) {
while($colsDifference < $colsToDisplay) {
$htmlOutput[] = '<td></td>';
$colsDifference++;
}
}
Final Code :
//INITIALIZE VARIABLES
$colsToDisplay = 3;
$htmlOutput = array();
//GET PICTURE LIST
$sql = "SELECT datePosted, firstName, lastName, pictureName FROM pictureList ORDER BY datePosted DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$htmlOutput[] = "<td><img src='images/{$row['pictureName']}' alt='' /><br />{$row['firstName']} {$row['lastName']}</td>";
}
//OPTIONAL CODE
//IF NEEDED, ADD MISSING COLUMNS
$colsDifference = count($htmlOutput) % $colsToDisplay;
if($colsDifference) {
while($colsDifference < $colsToDisplay) {
$htmlOutput[] = '<td></td>';
$colsDifference++;
}
}
//END: OPTIONAL CODE
//BREAK THE COLUMNS INTO GROUPS
$htmlOutput = array_chunk($htmlOutput, $colsToDisplay);
//DISPLAY TABLE print '<table>';
foreach($htmlOutput as $currRow) {
print '<tr>' . implode('', $currRow) . '</tr>';
}
print '</table>';
Idea Behind This Tutorial :
You dont need to create a file and write arrays into that file to display in datatable.
If you still wants that you can (divide table in two parts) to create two arrays and than write into file, and than use array_push(); or array_merge(); to get both arrays into one.
I might have bad explanition please forgive for mistakes, Hope this help you in your coding life :)
Sticking to your solution, you can append the other chunks to your exisiting file. This works by setting the flag FILE_APPEND, e.g.:
$table_json = $serializer->serialize($table[1], 'json', $context);
$myfile = fopen($_SERVER['DOCUMENT_ROOT']."/files/myfile.json", "w") or die("Unable to
open file!");
file_put_contents($_SERVER['DOCUMENT_ROOT']."/files/myfile.json", $table_json, FILE_APPEND | LOCK_EX);
(LOCK_EX flag to prevent anyone else writing to the file at the same time)

echo key value from a row before postgres php while loop

Can't believe this is giving me a problem but here it is. An example of the query and code is:
$sql = "SELECT
o.order_id, o.order_number, o.broker_id, o.agent_id
FROM orders o";
$sql_res = safe_query($sql);
/* I want to echo broker_id and angent_id only once here,
before the while loop, because the values are all the same */
while ($row = pg_fetch_array($sql_res)){
echo $order_number;
}
Assume broker and agent id numbers are each the same in every row. I don't want to echo them every time in the loop. I just want them to echo one time before the loop. Since they are the same, it does not matter which row they are echoed from.
I figured out a different way for a means to an end. It works well.
$sql = "SELECT
o.order_id, o.order_number, o.broker_id, o.agent_id
FROM orders o";
$sql_res = safe_query($sql);
$count = 0;
while ($row = pg_fetch_array($sql_res)){
if ($count == 0) {
echo $broker_id;
echo $agent_id;
}
echo $order_number;
$count += 1;
}
I realize I'm echoing the broker and agent IDs inside the while loop, but it's only an echo the first time through, and I can display them at top. And then every unique order is echoed. Visually, it accomplished what was needed for the end user.

Improving Ajax auto-complete to return better result

I am using ajax & php to fetch elements that matches keys(letters) entered by user with elements resembling the database.
for e.g database contain manufacturer names as:
Hydfloo, Rexflex, Easton, Vickters, EVER GUSH, Thomas Hydraulics, AVT Pumps
and say for example user has entered the letter "H" into the input box. Then I only receive Hydfloo as return and not Thomas Hydraulics along with it. Also if "p" is typed I wd expect to see "AVT Pumps". What changes do I need to make to my php in order to be able to have all the values returned that matches either the first or even the second word of the manufacturer name.
PHP code
<?php
require('../config/connection.php');
if(!$dbc) {
echo 'Could not connect to the database.';
} else {
if(isset($_POST['queryString'])) {
$queryString = mysqli_real_escape_string($dbc, $_POST['queryString']);
if(strlen($queryString) >0) {
$query = mysqli_query($dbc, "SELECT distinct name FROM prdct_subcat WHERE name LIKE '$queryString%' LIMIT 10");
echo '<ul>';
while ($result = mysqli_fetch_assoc($query)) {
echo '<li onClick="fill(\''.addslashes($result['name']).'\');">'.$result['name'].'</li>';
}
echo '</ul>';
}
}
}
?>
Use a regular expression instead of LIKE, so you can match a word boundary anywhere in the value.
Change
WHERE name LIKE '$queryString%'
to:
WHERE name REGEXP '[[:<:]]$queryString'
in the SQL.

PHP multiple entries

I'm creating a small project with PHP/MYSQL but i can't get my query working the way i need it. I have 2 tables
Table 1 (char):
Id, name.
Table 2 (spells):
Id, char, spell_name.
I'm getting the output:
Name Spell1
Name Spell2
Name Spell3
But I need it to be:
Name Spell1
Spell2
Spell3
Here's my query:
$query = "SELECT char.name AS name, spells.spell_name AS spell
FROM char, spells
WHERE (char.id = spells.spell_name)";
Any ideas?
I think you're gonna have to first get the ID of the character to query, and then pull the spells s/he has access to. Example:
$char_id = 0; // value would be assigned arbitrarily.
$query = "SELECT *
FROM 'spells' s
WHERE s.char = $char_id;";
$result = $pdo->query($query);
while($row = $result->fetchObj()){
// do something with the spells obj here
}
With SQL, you need to grab full rows at a time, so I believe the situation you want isn't possible.
As Goldentoa11 wrote. Make two selects, or create query with two result sets (more selects in one command), or accept current state (is normal and you can verify data consistency). I prefer current state, but sometimes use any of described solution (based on query frequency, size of result etc.).
If you need to list such data, you can than use something like this:
$currentName = null;
while ($row = mysql_fetch_object($result))
{
if ($currentName != $row->name)
{
echo "<b>" . $row->name . "</b><br />";
$currentName = $row->name;
}
echo $row->spell_name . "<br />";
}

How do you count and format user tags

I have user entered tags that go under the table field tags.
$sql="SELECT tags from table";
$stmt16 = $conn->prepare($sql);
$result=$stmt16->execute();
while($row = $stmt16->fetch(PDO::FETCH_ASSOC)){
echo $tags=$row['tags'];
}
This produces
cool,yes,okcool,yes,ok
because there are 2 entries with the same 3 tags under that field. I want to be able to count how many duplicates there are of each tag such that the result should be cool(2) yes(2) ok(2). Anyone know the proper way to approach this? Should I fetch the results as an array or explode them?
With your current data structure, the answer I'd give is yes: as you said, explode them, and put them into an array.
$tags = array();
while($row = $stmt16->fetch(PDO::FETCH_ASSOC)){
foreach(explode(',',$row['tags']) as $tag) {
if(isset($tags[$tag]) {$tags[$tag]++;} else {$tags[$tag]=1;}
}
}
//now you can see how many times each tag occurred...
foreach($tags as $tag=>$count) {
print "Tag {$tag} occurred {$count} times<br />";
}
However, if you can change the database structure, you'll find it a lot easier to manage your tags if you only have one per DB record. It will make it a lot easier to query them that way.
I would alter the statement to
SELECT COUNT(*) as cnt, tags
FROM table
GROUP BY tags
and there you are.
Edit:
Don't forget to alter your echo to echo $row['tags'] ."(". $row['count'] .")";
Simply with this query:
SELECT tag, COUNT(*)
FROM table
GROUP BY tag
HAVING COUNT(*) >1;

Categories