AutoSuggest Using PHP/MySQL & Ajax - php

So I've created a autosuggest for my search engine similar to google using PHP/MYSQL and Ajax. If my MySQL has 2 different title of the same name how do i get only one of them to appear on autosuggest? For example: I have a field with title= ufc 131 and another with title=ufc 131 . When I search for UFC 131 how i get only one of them to show?
The code i use is..
<?php
include('conn.php');
$str = strtolower($_GET['content']);
if(strlen($str))
{
$sel = mysql_query("select * from Streams where title like '".trim($str)."%'");
if(mysql_num_rows($sel))
{
echo "<table border =\"0\" width=\"100%\">\n";
if(mysql_num_rows($sel))
{
echo "<script language=\"javascript\">box('1');</script>";
while($row = mysql_fetch_array($sel))
{
$country = str_ireplace($str,"<b>".$str."</b>",($row['title']));
echo "<tr id=\"word".$row['title']."\" onmouseover=\"highlight(1,'".$row['title']."');\" onmouseout=\"highlight(0,'".$row['title']."');\" onClick=\"display('".$row['title']."');\" >\n<td>".$country."</td>\n</tr>\n";
}
}
echo "</table>";
}
}
else
{
echo "<script language=\"javascript\">box('0');</script>";
}
?>

Well, you can use the DISTINCT function, you can use the GROUP BY function, or you can even put all of your search results in an array in PHP after fetching it from MySQL and then using the array_unique() function to filter out duplicates.
But none of that is as efficient as making sure that the database doesn't contain any duplicates. What I mean to say is that, since you are providing a suggestion, you want the 'SELECT' element to run as fast as possible. Any type of trickery, like the ones I listed above, will require a combination of more time, more memory, and more CPU. Therefore, what you want to do is make sure that the database is in a good condition so that the SELECT statements can be as smooth as possible. A good way to do this is to make the 'title' field in your 'Streams' table a UNIQUE index. However, what I personally have, is a FULLTEXT index on my 'suggestion field'. The UNIQUE index will make sure there won't be any duplicates in the database for sure, but all that does it let you get away with sloppy PHP code for the insert. If you use proper FULLTEXT search, you can do FULLTEXT searches (MATCH() AGAINST()). Since those searches uses the index, they are performed MUCH faster. Your query statement will with no type of index actually use the index.
On top of that, you probably also want to update your PHP (/ echo) code some bit, cause, though your code is really small, it is not written optimally (which again, is something you WANT to make sure, in the case of search suggestions).

your code needs to be revamped.
A good way for making autosuggestion is to use the minimum amount of data possible.
So in this case you can use JSON.
include('conn.php');
$str = strtolower($_GET['content']);
$str = mysql_real_escape_string($str); // escape to prevent sql injection
Now for your query, You can use the GROUP BY keyword in mysql to not have duplicate lines
$sel = "SELECT title FROM Streams
WHERE title LIKE '{$str}%'
GROUP BY title
LIMIT 10";
Now for the returned data you can return it in Javascript object notation JSON
$data = "{";
while($row = mysql_fetch_array($sel)) {
$data .= '"title":"'.$row['title'].'",';
}
$data .= "}";
now you can echo the content
echo $data;
In your javascript you can use a library like Jquery to make it easy to retrieve the lightweight json data
I hope this helps you make a very good autosuggestion box

Related

Ordering and Selecting frequently used tags

I have looked on stackoverflow for a solution to this however couldn't find a good answers which outlined the issues I was having; Essentially what I'm trying to achieve is to array out 15 of the most frequent tags used from all my users subjects.
This is how I currently select the data
$sql = mysql_query("SELECT subject FROM `users`");
$row = mysql_fetch_array($sql);
I do apologise for the code looking nothing like what I'm trying to achieve I really don't have any clue where to begin with trying to achieve this and came here for a possible solution. Now this would work fine and I'd be able to array them out and however my problem is the subjects contain words along with the hash tags so an example room subject would look like hey my name is example #follow me how would I only grab the #followand once I've grabbed all the hashtags from all of the subjects to echo the most frequent 15?
Again I apologise for the code looking nothing like what I'm trying to achieve and I appreciate anyone's help. This was the closest post I found to solving my issue however was not useful.
Example
Here is three room subjects;
`Hello welcome to my room #awesome #wishlist`
`Hey hows everyone doing? #friday #awesome`
`Check out my #wishlist looking #awesome`
This is what I'm trying to view them as
[3] #awesome [2] #wishlist [1] #friday
What you want to achieve here is pretty complex for an SQL query and you are likely to run in to efficiency problems with parsing the subject every time you want to run this code.
The best solution is probably to have a table that associates tags with users. You can update this table every time a user changes their subject. To get the number of times a tag is used then becomes trivial with COUNT(DISTINCT tag).
One way would be to parse the result set in PHP. Once you query your subject line from the database, let's say you have them in the array $results, then you can build a frequency distribution of words like this:
$freqDist = [];
foreach($results as $row)
{
$words = explode(" ", $row);
foreach($words as $w)
{
if (array_key_exists($w, $freqDist))
$freqDist[$w]++;
else
$freqDist[$w] = 1;
}
}
You can then sort in descending order and display the distribution of words like this:
arsort($freqDist);
foreach($freqDist as $word => $count)
{
if (strpos($word, '#') !== FALSE)
echo "$word: $count\n";
else
echo "$word: does not contain hashtag, DROPPED\n";
}
You could also use preg_match() to do fancier matching if you want but I've used a naive approach with strpos() to assume that if the word has '#' (anywhere) it's a hashtag.
Other functions of possible use to you:
str_word_count(): Return information about words used in a string.
array_count_values(): Counts all the values of an array.

php mysql , need to take the result from a query to another page

code in page1.php (partial code)
while ($row = mysql_fetch_assoc($result))
{
echo '',($row[0]),'';
}
How can I take the value in $row[0] to page2.php?
Basically i want to use that value in page2.php to run a mysql query. Am I on the right track by using here?..
Any advice is appreciated.
Please let me know if my question is not clear.. i will try my best to word it better.
thanks for the help.
One possible way would be:
while ($row = mysql_fetch_assoc($result))
{
echo 'Link Text';
}
Then on the second page, you can access that variable using $_GET['value1']
In this example, you are taking values out of the database and sticking them in the query string. Just be sure you don't do it the other way around without sanitizing them!
To do two, do it like this:
echo 'Link Text';

Need to pull a list of image url's from a Mysql database based on a subdomain, and store them as a list

I have a Mysql Forum database which I need to query all the posts in for a specific set of images, on a particular url.
The url's are of images hosted on a subdomain that we don't have access to like this "http://images.website.com/images/randomnumberhere.jpg".
I need a mysql query to pull these out and process them into a list which we can later loop through to grab them all and move them.(I got this part handled)
I'm a php/mysql programmer but this feels like a regex problem and i'm not so great with that yet.
The issue is we don't have a list of the images, and it's a big long random number (so far as I can see). So what I need is a string like "images.website.com/images/(randomnumbers).jpg" and then put them into a list.
You could get all fancy pants-like and use regular expressions,
but you could also try a simple
SELECT * FROM image_table WHERE image_source LIKE '%images.website.com/images/%'
Is this what you are looking for?
If you're looking to pull all of the text from the database, and then use PHP to create a list of the images, try something like this:
$image_list = array();
while($row = $sql->fetch_array())
{
$text = $row['text'];
/* Changed to preg_match_all */
if(preg_match_all("/http:\/\/images.website.com\/images\/[0-9]+\.(jpg|jpeg|png|gif)/i", $text, $matches))
{
$image_list[] = $matches[0];
}
}
Nothing fancy, and I didn't test it, but it should work. That's a hardcoded regex that matches the URL you're looking for specifically. You may want to modify it so that it can match multiple domains from an array, or something, but it should get you started.
EDIT: Should have mentioned that you could then loop through the $image_list array to display the images, or whatever you're going to do with them.
$rand = //rand() function or whatever you would like to create the random number, since you didn't give ranges, it might be an array aswell;
$string = "images.website.com/images/$rand.jpg";
Or even a simple loop:
for ($i = 1; $i < 100; $i++) {
echo $string = "images.website.com/images/$i.jpg";
}
It's up to you how would you use it with your database

Alter Magento Index Fulltext Search?

I have a unique task that I have been given, and I am in the last leg of it, but this sub-task is proving to be extremely difficult! So you have background: We run a Magento site, and use a custom built SOLR search page. I am using phpSolrClient to parse the Solr XML and return usable result which I then build the search results page from.
The task I have been given is to have an "attribute" in the back end of Magento, lets call that "search_tags". The goal is to be able to insert a tag, and it's weight delimitered by commas:
ie sight^2,hearing^1,smell^3
I would like to edit the code in Magento's fulltext reindex to break apart the string, and insert that tag X of times into the fulltext1_en field. So it would add "sight" twice, "hearing" once, and "smell" three times. This is going to allow us to say, put a blender on the page when someone searches for juicers, even though the term "juicer" or "juice" does not appear in the fulltext1_en string. I have developed the code to pull, split and iterate ... However I am at an stand-still since I don't know what code to edit to include this in my fulltext1_en during the reindex process. If anyone has any experience with editing Magento's Fulltext Reindex, your input would be greatly appreciated! I looked in Indexer.php, but everything in that file is ambiguous at best, so that was no help! Gotta love Magento!
OK for those looking to alter and give "weighted tags" to custom search in Magento using SOLR, I was up all night getting this right, but it works...
First, create a filter in Magento and apply it to all products. I named mine "search_tags".
Next, use the following formula in that filter for a test item:
dude^25,crazyman^25,wierdsearch^25
Each word followed by a carat, and then the weight you want to give it. (This is how many times the word will be repeated and then added to fulltext1_en.)
After that is done, open the following file:
/app/code/core/Mage/CatalogSearch/Model/Mysql4/Fulltext.php
I know it says MySQL4, pay no attention, SOLR uses this index.
About line 500, you will see the following block:
if ($selects) {
$select = '('.join(')UNION(', $selects).')';
$query = $this->_getWriteAdapter()->query($select);
while ($row = $query->fetch()) {
JUST BELOW this block insert the following:
NOTE: Do not use the attribute ID I have listed here, that is unique to my setup. You are going to have to search your database to find this ID. I used JOIN to join eav_attributes with catalog_product_entity_varchar and used SELECT to find attribut_id and value WHERE entity_id = (Insert your product ID here). It's a pain, but it's the only way. This will return all the attributes for that product. Look for the one that has the tags we entered in earlier, and get it's ID. Insert that into the code below.
$attr_val = $row['value']; // Set attr_val so that it can be manipulated in following IF
if ($row['attribute_id'] == 457) { // 457 is the ID of MY search_tags filter, yours WILL be different! It can be found by joining eav_attributes table and catalog_product_entity_varchar and searching for the attribute value and ID where entity_id is X
$input = $row['value']; // Set $input to value of filter
$attr_val = ""; // Create Emtpy string
$pieces = explode( ',', $input ); // Explode filter by comma
foreach ($pieces as $val){
$i=1;
$val = explode( '^', $val); // Explode each "tag" by carat
while ($i <= $val[1]) { // Loop while $i is less than or equal to the number on the right side of the carat
$i++;
$attr_val = $attr_val . " " . $val[0]; // Append $attr_val with the word to the right side of the carat
}
}
}
$result[$row['entity_id']][$row['attribute_id']] = $attr_val; // Modified from Original
After you insert that ... Then comment out the following block.
$result[$row['entity_id']][$row['attribute_id']] = $row['value']; // ORIGINAL BLOCK -- UNCOMMENT -- DO NOT DELETE
Now run a fulltext reindex, and your fulltext1_en should show that you've added "dude", "crazyman", and "weirdsearch" all 25 times! When the index is completed, search for any of the tags in your site search: That item you added the tags to should show up close to, if not the top. Enjoy!

Good coding practice

I am graduating this June, so before that I want to prepare myself for working in the industry :)
My Question:
For example I want to list all the songs in the table using a list box and this is how I implemented it:
playlist.php
<tr id='' >
<td width="" class=""> <font color=#00000 />Select Songs</td>
<td width="" colspan="">
<select size='25'multiple='multiple' id="select_songs" name="playlist_songs[]">
<?php
display_songs_list();
?>
</select></td>
</tr>
and I have a seperate php_functions.php file where I have implemented all the php functions
function display_songs_list(){
$query = "select * from songs order by ID asc";
$result = mysql_query($query);
if(!$result)
echo "<script language = 'javascript'>alert('$result Sorry couldn't connect to the database...');</script>";
else{
$num_rows = mysql_num_rows($result);
if($num_rows > 0){
while($row = mysql_fetch_array($result)){
$ID = $row['ID'];
$title = $row['title'];
$value = $ID.'_'.$title;
echo "<option id=\"$ID\" value=\"$value\">$ID : $title</option>";
}
}
}
}
Is this way of implementation recommended. What else I can do to increace the scalability/maintainability/re-usability. please guide me on this. Is it recommended to follow any industry coding standards, if so what you perfer. Thank you.
Inline style attributes (color=#00000) are deprecated and kill kittens. Learn about CSS.
Tables are discouraged for anything except tabular data (think spreadsheets), use CSS for layout instead.
Hardcoding whitespace with is not desirable either if it doesn't add any meaning, learn to add spacing using CSS.
echoing either HTML or Javascript from the same function is bad. The Javascript alert will cause invalid HTML syntax at the point you're calling the function.
Mixing database calls and HTML so tightly is not good. Look into MVC separation.
Outputting a random, rather meaningless Javascript alert to the user in the middle of a half finished page is bad. You should display a dedicated error page instead. See MVC, which helps you accomplish this.
Mixing single quotes and double quotes for the attributes is inconsistent and makes the code more difficult to read. Stick to one type of quotes instead.
There is no form in your markup shown to submit the selected select options
Take my advice with a grain of salt, but first, you should really separate the code that talks with the database from the code that's given the user errors, they are two separate things. So an idea of how to achieve that in php might be a function that queries the database and returns an associate array with all the results that another function then prints. Also, you should have a more general database class that all your queries go through. The reason this would be preferred is that you can easily switch databases at a later point in time with minimal changes to your code, but if in every function you call mysql_query() it could become more complicated.
Its a reasonably good approach to take for php.
I normally split up my code into an Model/View/Controller type model.
The "controller" is the program which runs when the URL hits the server. It:-
grabs and checks any get/posted variables from the screen.
kicks of any requested actions such as database updates.
kicks of some "model" functions to get the data for the next screen.
formats the next screen using a "view" function or functions.
Note the controller doesn't itself emit any html.
The "model" functions do the database access and apply "business" rules.
The "view" functions emit html tags etc.
Apart from general neatness the big advantage of this is that you processing sequences isn't tied to the order the fields appear on the screen. So it really does make the programs more maintainable.

Categories