Improve search result by broadening matches - php

I am trying to improve search result using PHP. e.g. when product name is ZSX-3185BC user can not find the product when put something like ZSX3185BC. So far i get something like:
$input = '01.10-2010';
$to_replace = array('.','-');
$clean = str_replace($to_replace, '/',$input);`
I've tried this, but it does not work correctly (not sure, posted in comment without elaboration -ed)
$str = "";
$len = strlen($strSearch) - 1;
// Loop through the search string to check each charecter is acceptable and strip those that are not
for ($i = 0; $i <= $len; $i++) {
if(preg_match("/\w|-| /",$strSearch[$i])) {
$str = $str . $strSearch[$i];
}
}

You should try to do this kind of fuzzy matching directly in your database query. A common approach to fuzzy string matching is the Levenshtein distance.
MySQL does not have this built in, however, it can be added. See this SO question.
The basic way is to add a stored function to MySQL. There is a Levenshtein implementation as a stored function.

Try this :
SELECT * FROM tablename WHERE replace(fieldname, '-', '') like '%ZSX3185BC%';

Related

Convert a search query into 1's and 0's and use as a variable

Hello everyone and thanks for the time you will spend on this question.
Problem
I am trying to convert my search query into 1's and 0's to check for a match inside my database.
Basically, I fill my form input with this query: SF12345
The code checks for each chars if it's numeric. If it is, it outputs a 1 if not it outputs a 0. So my code (SO's code :) ) so far will output 0011111. So far, so good:
$s = "SF12345";
for ($i = 0; $i < strlen($s); $i++){
$char = $s[$i];
if (is_numeric($char)) {
echo "1";
} else {
echo "0";
}
}
Question
How do I "implode" or "regroup" all these echo's to use as one variable inside my search query below
$dbConn->query("SELECT * FROM products WHERE code = '".$s.'");
I want it to look like this
$dbConn->query("SELECT * FROM products WHERE code = '0011111'");
If anyone has any idea on how to approach or solve this issue, you'll make one (very) happy man.
If it is important to know why I want to convert it to 1's and 0's I'll be glad to explain.
Thank you very much, all help is much appreciated.
You could append to a string in PHP with the concatenating assignment operator .=. (See https://www.php.net/manual/en/language.operators.string.php for more information). Then you could do this:
$s = "SF12345";
$output = ""; // This will store the result.
for ($i = 0;$i < strlen($s);$i++)
{
$char = $s[$i];
if (is_numeric($char))
{
$output .= "1";
}
else
{
$output .= "0";
}
}

How to save user-created content as a URL (hash) parameter?

I want to enable "Save" feature in my web app. I will send data to a PHP post receiver, and save the data in a MySQL row, so normally I can load it with its id like this:
site.com/content/123
But I want (just for the fancy looks) to use a "hash" (not sure if it's the right term) for this, like :
site.com/content/A2w7SqZ
just like jsFiddle does. How can I convert the id (integer) to a hash?
Example :
http://jsfiddle.net/sfu24/
The only way I can think of is MD5. But it generates a very long string. I think 6 characters are more than enough.
So how can I make a hash system like jsfiddle?
Thanks for any help !
P.S. I'm sure this question has been asked million times. But I couldn't find it. If you know an already-existing answer, please post the link and I will delete the question.
to generate random chars
function generate_random($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for($i = 0; $i < $length; $i ++) {
$randomString .= $characters [rand ( 0, strlen ( $characters ) - 1 )];
}
return $randomString;
}
Take a look as base_convert()
or the hashids
which will help you generate short hashes from numbers (like YouTube and Bitly).
function generateHash($int) {
$rand_letters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$newstr = '';
for ($i = 0; $i < strlen($int); $i++) {
$newstr .= $rand_letters[rand(0, strlen($rand_letters)-1)];
}
return $newstr;
}
function myHash($int) {
$newstr = generateHash($int);
$result = $db->query("SELECT COUNT(*) FROM hashes WHERE hash = '$newstr';");
if ($result->num_rows > 0) {
myHash($int);
}
return $newstr;
}
echo myHash(973451);
You generate string on the base of the length of your passed integer. That's what generateHash() does. And myHash() uses this string, if it's already present, runs itself again, until generate not-present string, so returns it.
The hashes are random, so they are not straight reversable (they still can be), but "12345" will not result in one and the same string everytime.

PHP/MySQL Limiting characters outputted from a field

When I get a database array, sometimes there is fields with too much data for my results list page, which is suppose to give just a short description. How do I limit the characters count to something like 100.
This is my array for the loop:
<?php
$i = 1;
while ($row = mysql_fetch_array($result)) {
?>
This is my echo statement:
<?php echo $row['description']; ?>
You can use substr like this:
<?php echo substr($row['description'], 0, 100); ?>
But it might be better—depending on your application needs—to do the limiting when making the initial MySQL query using SUBSTR which behaves the same way, but in MySQL.
SELECT SUBSTR(example_field, 1, 100)
FROM example_table
WHERE example_field IS NOT NULL
LIMIT 1
;
That MySQL script basically means return the substring of example_field starting from the first (1) character and going 100 characters in.
This might be better in some cases since if you are limiting text length to 100 characters, why grab the data for fields that might have 1,000+ characters? That would definitely bog down your PHP script in many cases. Handling that in MySQL is the best way to nip it in the bud if your app just needs 100 characters returned.
You can try with substr()
<?php echo substr($row['description'],0,100); ?>
OR
function truncate($input, $maxWords, $maxChars)
{
$words = preg_split('/\s+/', $input);
$words = array_slice($words, 0, $maxWords);
$words = array_reverse($words);
$chars = 0;
$truncated = array();
while(count($words) > 0)
{
$fragment = trim(array_pop($words));
$chars += strlen($fragment);
if($chars > $maxChars) break;
$truncated[] = $fragment;
}
$result = implode($truncated, ' ');
return $result . ($input == $result ? '' : '...');
}
// try with cuctom function truncate() , it help to cut description by words.
<?php echo truncate($row['description'],5,200); ?>
Like the other answers, you should use substr, but you can use it in combination with strpos so that when you shorten the string, you stop after a complete word instead of interrupting a word itself.
$pos = strpos($row['description'], ' ', 100);
echo substr($row['description'], $pos);
I would do it in the SQL query. It's better to limit the results returned which reduces I/O and network throughput by not returning data from the database you're not going to use. In your SQL query do:
SELECT LEFT(description, 100) AS description
,....
FROM ...
Just in case someone is interested in another code snippets on how to limit character output with dots, I use this and it works well for me
CONCAT(SUBSTR(<column_name_here>, 1, 100),'...... Read More') AS Column_Name

What Algorithm is used for this?

im doing research project for a the game Text twist,the text will automatically search word from a dictionary and scramble then, and also process the words to be found automatically using the same concept with this site http://grecni.com/texttwist.php , i also need to provide an algorithm that i will use for my project,and im planning to include this word unscrambler in this web site http://grecni.com/texttwist.php but i dont know what algorithm is possibly use to do the actions done on the website i posted. does any one know what type, or what you call the algorithm used,or can be use that will give the same results, an example of the algorithm will be greatly appreciated.
The data structure you want is called a Directed Acyclic Word Graph (dawg)
There are questions already answered about this:
Algorithm to get a list of all words that are anagrams of all substrings (scrabble)?
Writing an algorithm for scrabble
You could also perhaps implement the levenshtein algorithm which would accomplish pretty much the same result:
MySQL - Which Hash Algo should I use for this?
Update:
After giving myself a challenge to create an example to demonstrate the algorithm ive come up with this, as its from a plugin built for my cms its wrapped in a class but your get the idea there is a demo # http://cherone.co.uk/scrabble_suggest
First I created a table with id,word,sorted (word = the actual word, sorted = the word alphabetically sorted like for e.g: aardvark sorted would be aaadkrrv) i just found an english wordlist on the internets.
The form posts the string and then the string is sorted alphabetically to match 1:1 the sorted column, then the string is split into each character and then queried sequentially till the last character. The functions of interest are str_sort,permute,swap Perhaps its of some interest..
<?php
/**
* Scrabble solver Plugin this file is "inline" included within the frontController class
*/
Class plugin{
function __construct($core) {
$this->core = $core;
$this->plugin_path = SITE_ROOT.'/core/plugins/'.$this->core->router->action.'/';
$this->request = explode('/',$this->core->router->request);
//Assign Page meta tags ect
$this->core->template->meta_keywords = 'Text,Twist,Text Twist,word,letter,scrabble,unscrambler,unscramble,word finder,puzzle,anagram,scrabble,cheat,cheater,help,helper,solve,solver,free,php';
$this->core->template->meta_description = 'Scrabble and Anagram like word solver tool to help unscramble letters and words and cheat at your favorite word puzzle';
$this->core->template->page_title = $this->core->template->site_name." - Scrabble and Anagram like word solver";
$route = (isset($this->request[2])?$this->request[2]:null);
}
function load(){
set_time_limit(0);
$data=array('var'=>$this,'result'=>'','word'=>'','word_sort'=>'');
switch($this->core->router->subaction){
case "index":
$string='';
if($_SERVER['REQUEST_METHOD']=='POST'){
$string = substr(preg_replace('/[^a-zA-Z]/s', '', trim(strtolower($_POST['letters']))),0,8);
$data['word'] = $string;
$string = $this->str_sort($string);
$data['word_sort'] = $string;
}
$stringLen = strlen($string);
$result = array();
for($i=2;$i<=$stringLen;$i++){
$seq = substr($data['word_sort'],0,$i);
$rounds = explode('|',$this->permute($seq,0,strlen($seq)));
$r=$i;
foreach($rounds as $round){
$result[$r] = $this->get_words($round,strlen($seq));
$r++;
}
}
$data['result'] = $result;
$this->core->template->content_center = $this->core->template->loadContentView(get_class(),$this->core->router->subaction,$data);
$this->core->template->content_left = '';
$this->core->template->content_right = '';
break;
case "update":
$this->insert_word_lists();
header('Location: '.SITE_URL.'/'.$this->core->router->action);
die;
break;
case "api":
header('Content-Type: application/json');
echo 'No api for this plugin, perhaps one comming soon. ;p';
break;
default:
header('Location: '.SITE_URL.'/'.$this->core->router->action);
die;
break;
}
}
//Query Method to search for sequenced alphabetically sorted words.
private function get_words($word,$stringLen){
$chars = str_split($word,1);
$sql = "SELECT DISTINCT `word` FROM `plugin_scrabble_words` WHERE ";
foreach($chars as $char){
$sql .=' `sorted` LIKE "%'.$char.'%" AND';
}
$sql = trim($sql,'AND');
$sql .= ' AND LENGTH(sorted) = '.$stringLen;
$statement = $this->core->db->prepare($sql);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
//A Model method for updating the database word list.
private function insert_word_lists(){
set_time_limit(0);
$lists = glob($this->plugin_path."wordlists/*.txt");
foreach ($lists as $list){
$words = file($list);
foreach($words as $word){
$word = strtolower(preg_replace('/[^a-zA-Z]/s', '', $word));
if($this->sql_check_word($word)===false){
$this->sql_put_word($word);
}
}
}
}
//A Model method for checking the database specific word.
private function sql_check_word($word){
$sql = "SELECT `word` FROM `plugin_scrabble_words` WHERE `word` = :word";
$statement = $this->core->db->prepare($sql);
$statement->bindParam(':word', $word, PDO::PARAM_STR);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
if(!empty($result)){
return true;
}else{
return false;
}
}
//A Model method for adding the word to the database.
private function sql_put_word($word){
$sql = "INSERT into `plugin_scrabble_words` (word,sorted) VALUES (:word,:sorted)";
$statement = $this->core->db->prepare($sql);
$sorted = $this->str_sort($word);
$statement->bindParam(':word', $word, PDO::PARAM_STR);
$statement->bindParam(':sorted', $sorted, PDO::PARAM_STR);
$statement->execute();
}
//Sort Method that will sort a sring in alphabetical order
private function str_sort($string) {
$tmp = str_split($string);
sort($tmp);
return implode('',$tmp);
}
//Method to generate and return all permutations of the string with | delimiter.
private function permute($str,$i,$n) {
if ($i == $n){
return $str.'|';
} else {
for ($j = $i; $j < $n; $j++) {
$this->swap($str,$i,$j);
$this->permute($str, $i+1, $n);
$this->swap($str,$i,$j);
}
}
}
//Method to swap the char at pos $i and $j of $str.
private function swap(&$str,$i,$j) {
$temp = $str[$i];
$str[$i] = $str[$j];
$str[$j] = $temp;
}
}
?>
One approach would be to generate all possible permutations of the letters and match them against a dictionary. For an N lettered character sequence, this would take O(N!) time if you keep the dictionary in a set data structure.
For shorter sequences (10 characters or so), this is a perfectly good strategy.
For longer sequences, you should do the reverse. You can loop through the dictionary and determine if your character sequence has the characters to make the word. For M dictionary elements, this would take more or less O(M) time. There are various ways you can speed up this technique like pre-computing the number of each letter in each dictionary entry.
edit: The gentleman below me gives a more algorithmically rigorous and thorough treatment of the subject, and so I would direct you to his explanation (which employs big O notation which mine... embarrassingly does not).
Actually, although VanDang called it a "naive approach", there's nothing wrong with testing all possible combinations of the finite set of characters given. As long as a person is prevented from providing an arbitrary number of characters, there is a maximum of !n combinations of letters (with n = the number of letters, assuming there are no repeats), and, since words in English don't get THAT long, testing each combination wouldn't be that bad.
After all, the method of exhaustion is actually an accepted method for optimizing large boolean expressions when generating hardware descriptions.

PHP code for generating decent-looking coupon codes (mix of letters and numbers)

For an ecommerce site I want to generate a random coupon code that looks better than a randomly generated value. It should be a readable coupon code, all in uppercase with no special characters, only letters (A-Z) and numbers (0-9).
Since people might be reading this out / printing it elsewhere, we need to make this a simple-to-communicate value as well, perhaps 8-10 characters long.
Something like perhaps,
AHS3DJ6BW
B83JS1HSK
(I typed that, so it's not really that random)
$chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$res = "";
for ($i = 0; $i < 10; $i++) {
$res .= $chars[mt_rand(0, strlen($chars)-1)];
}
You can optimize this by preallocating the $res string and caching the result of strlen($chars)-1. This is left as an exercise to the reader, since probably you won't be generating thousands of coupons per second.
Try this:
substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, 10)
Why don't keep it simple?
<?php
echo strtoupper(uniqid());
?>
Always returns 13 character long uppercased random code.
You can use the coupon code generator PHP class file to generate N number of coupons and its customizable, with various options of adding own mask with own prefix and suffix. Simple PHP coupon code generator
Example:
coupon::generate(8); // J5BST6NQ
http://webarto.com/35/php-random-string-generator
Here you go.
function randr($j = 8){
$string = "";
for($i=0;$i < $j;$i++){
srand((double)microtime()*1234567);
$x = mt_rand(0,2);
switch($x){
case 0:$string.= chr(mt_rand(97,122));break;
case 1:$string.= chr(mt_rand(65,90));break;
case 2:$string.= chr(mt_rand(48,57));break;
}
}
return strtoupper($string); //to uppercase
}
If there are no security requirements for these, then you don't really need randomly generated codes. I would just use incremental IDs, such as those generated by whatever RDBMS you use. Optionally, if you have different types of coupons, you could prefix the codes with something, e.g.:
CX00019 QZ0001C
CX0001A QZ0001D
CX0001B QZ0001E
Alternately, you could even use dictionary words in the coupon, as such coupon codes are easier to remember and faster for users to type. Companies like Dreamhost use these for their promo codes, e.g.:
Promo60
NoSetupFee
YELLOWGORILLA82
Some of these are obviously human-created (which you might want to have the option of), but they can also be generated using a dictionary list. But even if they are randomly-generated nonsense phrases, the fact that the characters follow a logical pattern still makes it much more user-friendly than something like R7QZ8A92F1. So I would strongly advise against using the latter type of coupon codes just on the basis that they "look cool". Your customers will thank you.
$size = 12;
$string = strtoupper(substr(md5(time().rand(10000,99999)), 0, $size));
function generateCouponCode($length = 8) {
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$ret = '';
for($i = 0; $i < $length; ++$i) {
$random = str_shuffle($chars);
$ret .= $random[0];
}
return $ret;
}
you can find a lot of function in php rand manual
http://php.net/manual/en/function.rand.php
i like this one
<?php
//To Pull 8 Unique Random Values Out Of AlphaNumeric
//removed number 0, capital o, number 1 and small L
//Total: keys = 32, elements = 33
$characters = array(
"A","B","C","D","E","F","G","H","J","K","L","M",
"N","P","Q","R","S","T","U","V","W","X","Y","Z",
"1","2","3","4","5","6","7","8","9");
//make an "empty container" or array for our keys
$keys = array();
//first count of $keys is empty so "1", remaining count is 1-7 = total 8 times
while(count($keys) < 8) {
//"0" because we use this to FIND ARRAY KEYS which has a 0 value
//"-1" because were only concerned of number of keys which is 32 not 33
//count($characters) = 33
$x = mt_rand(0, count($characters)-1);
if(!in_array($x, $keys)) {
$keys[] = $x;
}
}
foreach($keys as $key){
$random_chars .= $characters[$key];
}
echo $random_chars;
?>
$length = 9;
$code = (strtoupper(substr(md5(time()), 0, $length)));
Just Write
$voucher_no = date('ymd') . rand(1000, 9999);
while(SapItem::where('voucher_no', $voucher_no)->exists()){
$voucher_no = date('ymd') . rand(1000, 9999);
}
Output: 2204171447

Categories