im having a odd problem os my website, i have a script that records all the searchs and insert those search words on database, the problem is that since search engine robots started sneaking around my website, they make my script to produce search keywords like "search keywords////////////////////////////////////////////////"
I want to strip that characteres ( ////////// ) before indexed on mysql.
This is what i have:
$search=htmlspecialchars($_GET['load']);
$say=mysql_query("SELECT * FROM madvideo WHERE MATCH (baslik) AGAINST ('*$search*' IN BOOLEAN MODE)");
$saydim=mysql_num_rows($say);
$count = $saydim;
$page = !empty($_GET["page"]) ? intval($_GET["page"]) : 1;
$s = ($page-1)*$perpage;
$sayfasayisi=ceil($count/$perpage);
if(ayaral("Arananlar-Kaydet")=="1") {
$ekle=cevir($search);
#mysql_query("insert into tag (baslik,tr,tarih) values ('$search','$ekle',now()) "); }
The variable " $search " will call the search word, and i dont know whats the strip syntax i have to use to strip that nasty ///////// character.
EDIT: the code that creates the words is this:
$vtitle = str_replace("\r\n\r\n", ' ', $vtitle);
$words = explode(' ', $vtitle);
$k = count($words);
$k3 = ceil($k/3);
$new = array();
for ($i=0; $i<$k; $i+=$k3) {
$new[] = join(' ', array_slice($words,$i, $k3));
}
$tag1 = $new[0];
$tag2 = $new[1];
$tag3 = $new[2];
Use MySQL TRIM function to remove from end of the string as follows:
TRIM(TRAILING '/' FROM <string>)
#mysql_query("insert into tag (baslik,tr,tarih)
values (TRIM(TRAILING '/' FROM '$search'),'$ekle',now())")
To trim from both beginning and ending, use following
TRIM(BOTH '/' FROM <string>)
#mysql_query("insert into tag (baslik,tr,tarih)
values (TRIM(BOTH '/' FROM '$search'),'$ekle',now())")
To remove all occurences of the string use REPLACE function as follows:
REPLACE(<string>, '/', '')
#mysql_query("insert into tag (baslik,tr,tarih)
values (REPLACE('$search', '/',''),'$ekle',now())")
Hope it helps...
If the / characters appear always at the end of the $search, you can use rtrim using the second (optional) parameter:
$search = "search keywords////////////////////////////////////////////////";
$search = rtrim($search, '/ ');
echo $search; // prints 'search keywords'
EDIT:
Real example...
<?php
if(isset($_REQUEST['str'])) {
$search = $_REQUEST['str'];
$ser_chk = strpos($search, "/");
if ($ser_chk > -1) {
$search = str_replace("/", "", $search);
}
}
?>
<h1><?php print $search; ?></h1>
<form action="" method="post">
<input type="text" size="100" value="search keywords////////////////////////////////////////////////" name="str" />
<input type="submit" />
</form>
LINK TO TEST: http://simplestudio.rs/tsto.php
At least do:
$search = mysql_real_escape_string($search);
Also you can check for that characters and if founded just replace them with empty string.
$ser_chk = strpos($search, "/");
if ($ser_chk > -1) {
$search = str_replace("/", "", $search);
}
$regex = "/\//";
$string = "////search";
$string = preg_replace($regex, '', $string);
echo $string;
The flexible solution for character repetition will be a regular expression.
$output = preg_replace('/\/[\/]+/', '/'. $input);
It will handle any number of "/" and replace it with a single "/".
Related
Using the following code:
$text = "أطلقت غوغل النسخة المخصصة للأجهزة الذكية العاملة بنظام أندرويد من الإصدار “25″ لمتصفحها الشهير كروم.ولم تحدث غوغل تطبيق كروم للأجهزة العاملة بأندرويد منذ شهر تشرين الثاني العام الماضي، وهو المتصفح الذي يستخدمه نسبة 2.02% من أصحاب الأجهزة الذكية حسب دراسة سابقة. ";
$tags = "غوغل, غوغل النسخة, كروم";
$tags = explode(",", $tags);
foreach($tags as $k=>$v) {
$text = preg_replace("/\b{$v}\b/u","$0",$text, 1);
}
echo $text;
Will give the following result:
I love PHP">love PHP</a>, but I am facing a problem
Note that my text is in Arabic.
The way is to do all in one pass. The idea is to build a pattern with an alternation of tags. To make this way work, you must before sort the tags because the regex engine will stop at the first alternative that succeeds (otherwise 'love' will always match even if it is followed by 'php' and 'love php' will never be matched).
To limit the replacement to the first occurence of each word you can remove tag from the array once it has been found and you test if it is always present in the array inside the replacement callback function:
$text = 'I love PHP, I love love but I am facing a problem';
$tagsCSV = 'love, love php, facing';
$tags = explode(', ', $tagsCSV);
rsort($tags);
$tags = array_map('preg_quote', $tags);
$pattern = '/\b(?:' . implode('|', $tags) . ')\b/iu';
$text = preg_replace_callback($pattern, function ($m) use (&$tags) {
$mLC = mb_strtolower($m[0], 'UTF-8');
if (false === $key = array_search($mLC, $tags))
return $m[0];
unset($tags[$key]);
return '<a href="index.php?s=news&tag=' . rawurlencode($mLC)
. '">' . $m[0] . '</a>';
}, $text);
Note: when you build an url you must encode special characters, this is the reason why I use preg_replace_callback instead of preg_replace to be able to use rawurlencode.
If you have to deal with an utf8 encoded string, you need to add the u modifier to the pattern and you need to replace strtolower with mb_strtolower)
the preg_split way
$tags = explode(', ', $tagsCSV);
rsort($tags);
$tags = array_map('preg_quote', $tags);
$pattern = '/\b(' . implode('|', $tags) . ')\b/iu';
$items = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE);
$itemsLength = count($items);
$i = 1;
while ($i<$itemsLength && count($tags)) {
if (false !== $key = array_search(mb_strtolower($items[$i], 'UTF-8'), $tags)) {
$items[$i] = '<a href="index.php?s=news&tag=' . rawurlencode($tags[$key])
. '">' . $items[$i] . '</a>';
unset($tags[$key]);
}
$i+=2;
}
$result = implode('', $items);
Instead of calling preg_replace multiple times, call it a single time with a regexp that matches any of the tags:
$tags = explode(",", tags);
$tags_re = '/\b(' . implode('|', $tags) . ')\b/u';
$text = preg_replace($tags_re, '$0', $text, 1);
This turns the list of tags into the regexp /\b(love|love php|facing)\b/u. x|y in a regexp means to match either x or y.
I am using regular expression for getting multiple patterns from a given string.
Here, I will explain you clearly.
$string = "about us";
$newtag = preg_replace("/ /", "_", $string);
print_r($newtag);
The above is my code.
Here, i am finding the space in a word and replacing the space with the special character what ever i need, right??
Now, I need a regular expression that gives me patterns like
about_us, about-us, aboutus as output if i give about us as input.
Is this possible to do.
Please help me in that.
Thanks in advance!
And finally, my answer is
$string = "contact_us";
$a = array('-','_',' ');
foreach($a as $b){
if(strpos($string,$b)){
$separators = array('-','_','',' ');
$outputs = array();
foreach ($separators as $sep) {
$outputs[] = preg_replace("/".$b."/", $sep, $string);
}
print_r($outputs);
}
}
exit;
You need to do a loop to handle multiple possible outputs :
$separators = array('-','_','');
$string = "about us";
$outputs = array();
foreach ($separators as $sep) {
$outputs[] = preg_replace("/ /", $sep, $string);
}
print_r($outputs);
You can try without regex:
$string = 'about us';
$specialChar = '-'; // or any other
$newtag = implode($specialChar, explode(' ', $string));
If you put special characters into an array:
$specialChars = array('_', '-', '');
$newtags = array();
foreach ($specialChars as $specialChar) {
$newtags[] = implode($specialChar, explode(' ', $string));
}
Also you can use just str_replace()
foreach ($specialChars as $specialChar) {
$newtags[] = str_replace(' ', $specialChar, $string);
}
Not knowing exactly what you want to do I expect that you might want to replace any occurrence of a non-word (1 or more times) with a single dash.
e.g.
preg_replace('/\W+/', '-', $string);
If you just want to replace the space, use \s
<?php
$string = "about us";
$replacewith = "_";
$newtag = preg_replace("/\s/", $replacewith, $string);
print_r($newtag);
?>
I am not sure that regexes are the good tool for that. However you can simply define this kind of function:
function rep($str) {
return array( strtr($str, ' ', '_'),
strtr($str, ' ', '-'),
str_replace(' ', '', $str) );
}
$result = rep('about us');
print_r($result);
Matches any character that is not a word character
$string = "about us";
$newtag = preg_replace("/(\W)/g", "_", $string);
print_r($newtag);
in case its just that... you would get problems if it's a longer string :)
I have a PHP search script that queries a MySQL database and then parses the results through HTML to allow CSS styling. I want the script to highlight all of the keywords in the results that the user has search for. How can I do this with PHP?
My PHP script is:
<?php
mysql_connect("localhost","username","password");
mysql_select_db("database");
if(!empty($_GET['q'])){
$query=mysql_real_escape_string(trim($_GET['q']));
$searchSQL="SELECT * FROM links WHERE `title` LIKE '%{$query}%' LIMIT 8";
$searchResult=mysql_query($searchSQL);
while ($row=mysql_fetch_assoc($searchResult)){
$results[]="<a href='{$row['url']}' class='webresult'><div class='title'>{$row['title']}</div><div class='desc'>{$row['description']}</div><div class='url'>{$row['url']}</div></a>";
}
if(empty($results)){
echo 'No results were found';
} else {
echo implode($results);
}
}
?>
Simplistically you could adapt the loop here:
$searchvar = trim($_GET['q']);
while ($row=mysql_fetch_assoc($searchResult)){
$description = str_replace($searchvar, '<span class="highlight">'.$searchvar."</span>", $row['description']);
$results .="<a href='{$row['url']}' class='webresult'>
<div class='title'>{$row['title']}</div>
<div class='desc'>{$description}</div>
<div class='url'>{$row['url']}</div></a>";
}
To make it a little better:
$searchvar = explode(" ", trim($_GET['q'])); //puts each space separated word into the array.
while ($row=mysql_fetch_assoc($searchResult)){
$description = $row['description'];
foreach($searchvar as $var) $description = str_replace($var, '<span class="highlight">'.$var."</span>", $description);
$description = str_replace($searchvar, '<span class="highlight">'.$searchvar."</span>", $row['description']);
$results .="<a href='{$row['url']}' class='webresult'>
<div class='title'>{$row['title']}</div>
<div class='desc'>{$description}</div>
<div class='url'>{$row['url']}</div></a>";
}
The benefit of the second one there is that if a user types in "ipod toudch yellow" you will be searching for "ipod", "toudch" and "yellow" which would negate the type and make the results more general.
You would need to exchange the single:
like '%query%'
with
foreach(explode(" ", trim($_GET['q']) as $searchvar) $where[] = "like '%$searchvar%'";
$wheresql = implode(" OR ", $where);
to get each search "word" to be looked for in the sql or you will have a limited search with a unrelated highlight.
i also found this solution to highlight each word of the results:
$text = $searchresults;
class highlight
{
public $output_text;
function __construct($text, $words)
{
$split_words = explode( " " , $words );
foreach ($split_words as $word)
{
$text = preg_replace("|($word)|Ui" , "<b>$1</b>" , $text );
}
$this->output_text = $text;
}
}
$highlight = new highlight($searchresults, $keywords);
echo $highlight;
In case that could help,
Regards,
Max
you can use regex or simply str replace to look for a particular string and add a span around it:
while ($row=mysql_fetch_assoc($searchResult)){
$str ="<a href='".$row['url']."' class='webresult'>";
$str .="<div class='title'>".$row['title']."</div>";
$str .="<div class='desc'>";
$str .= str_replace($query,"<span class='hightlighted'>".$query."</span>",$row['description']);
$str .="</div><div class='url'>".$row['url']."</div></a>";
$result[] = $str;
}
now the css:
span.highlighted {
background-color: yellow;
}
You can use str_replace. For each keyword the user uses, put it into the $search array, and also put it into a $replace array, but surround with with a classed span tag in the latter, which you can style with CSS later. For example:
$search = array('apple', 'orange');
$replace = array();
foreach ($search as $word)
{
$replace[] = "<span class='highlight'>$word</span>";
}
$string = str_replace($search, $replace, $string);
EDIT: assuming that $query just contains keywords delimited by a single whitespace, you could get the search array this way (with explode),
$search = explode(' ', $query);
Or, if you want to add more complex logic for processing the keywords out of the $query variable (like if you use query operators like +), you could use a for loop:
$queryTerms = explode(' ', $query);
$search = array();
foreach ($queryTerms as $term)
{
// do some processing of the $term (like delete "+"?)
// ...
$search[] = $processedTerm;
}
Im working on a commenting web application and i want to parse user mentions (#user) as links. Here is what I have so far:
$text = "#user is not #user1 but #user3 is #user4";
$pattern = "/\#(\w+)/";
preg_match_all($pattern,$text,$matches);
if($matches){
$sql = "SELECT *
FROM users
WHERE username IN ('" .implode("','",$matches[1]). "')
ORDER BY LENGTH(username) DESC";
$users = $this->getQuery($sql);
foreach($users as $i=>$u){
$text = str_replace("#{$u['username']}",
"<a href='#' class='ct-userLink' rel='{$u['user_id']}'>#{$u['username']}</a> ", $text);
}
$echo $text;
}
The problem is that user links are being overlapped:
<a rel="11327" class="ct-userLink" href="#">
<a rel="21327" class="ct-userLink" href="#">#user</a>1
</a>
How can I avoid links overlapping?
Answer Update
Thanks to the answer picked, this is how my new foreach loop looks like:
foreach($users as $i=>$u){
$text = preg_replace("/#".$u['username']."\b/",
"<a href='#' title='{$u['user_id']}'>#{$u['username']}</a> ", $text);
}
Problem seems to be that some usernames can encompass other usernames. So you replace user1 properly with <a>user1</a>. Then, user matches and replaces with <a><a>user</a>1</a>. My suggestion is to change your string replace to a regex with a word boundary, \b, that is required after the username.
The Twitter widget has JavaScript code to do this. I ported it to PHP in my WordPress plugin. Here's the relevant part:
function format_tweet($tweet) {
// add #reply links
$tweet_text = preg_replace("/\B[#@]([a-zA-Z0-9_]{1,20})/",
"#<a class='atreply' href='http://twitter.com/$1'>$1</a>",
$tweet);
// make other links clickable
$matches = array();
$link_info = preg_match_all("/\b(((https*\:\/\/)|www\.)[^\"\']+?)(([!?,.\)]+)?(\s|$))/",
$tweet_text, $matches, PREG_SET_ORDER);
if ($link_info) {
foreach ($matches as $match) {
$http = preg_match("/w/", $match[2]) ? 'http://' : '';
$tweet_text = str_replace($match[0],
"<a href='" . $http . $match[1] . "'>" . $match[1] . "</a>" . $match[4],
$tweet_text);
}
}
return $tweet_text;
}
instead of parsing for '#user' parse for '#user ' (with space in the end) or ' #user ' to even avoid wrong parsing of email addresses (eg: mailaddress#user.com) maybe ' #user: ' should also be allowed. this will only work, if usernames have no whitespaces...
You can go for a custom str replace function which stops at first replace.. Something like ...
function str_replace_once($needle , $replace , $haystack){
$pos = strpos($haystack, $needle);
if ($pos === false) {
// Nothing found
return $haystack;
}
return substr_replace($haystack, $replace, $pos, strlen($needle));
}
And use it like:
foreach($users as $i=>$u){
$text = str_replace_once("#{$u['username']}",
"<a href='#' class='ct-userLink' rel='{$u['user_id']}'>#{$u['username']}</a> ", $text);
}
You shouldn’t replace one certain user mention at a time but all at once. You could use preg_split to do that:
// split text at mention while retaining user name
$parts = preg_split("/#(\w+)/", $text, -1, PREG_SPLIT_DELIM_CAPTURE);
$n = count($parts);
// $n is always an odd number; 1 means no match found
if ($n > 1) {
// collect user names
$users = array();
for ($i=1; $i<$n; $i+=2) {
$users[$parts[$i]] = '';
}
// get corresponding user information
$sql = "SELECT *
FROM users
WHERE username IN ('" .implode("','", array_keys($users)). "')";
$users = array();
foreach ($this->getQuery($sql) as $user) {
$users[$user['username']] = $user;
}
// replace mentions
for ($i=1; $i<$n; $i+=2) {
$u = $users[$parts[$i]];
$parts[$i] = "<a href='#' class='ct-userLink' rel='{$u['user_id']}'>#{$u['username']}</a>";
}
// put everything back together
$text = implode('', $parts);
}
I like dnl solution of parsing ' #user', but maybe is not suitable for you.
Anyway, did you try to use strip_tags function to remove the anchor tags? That way you have the string without the links, and you can parse it building the links again.
strip_tags
I have a string in PHP that is a URI with all arguments:
$string = http://domain.com/php/doc.php?arg1=0&arg2=1&arg3=0
I want to completely remove an argument and return the remain string. For example I want to remove arg3 and end up with:
$string = http://domain.com/php/doc.php?arg1=0&arg2=1
I will always want to remove the same argument (arg3), and it may or not be the last argument.
Thoughts?
EDIT: there might be a bunch of wierd characters in arg3 so my prefered way to do this (in essence) would be:
$newstring = remove $_GET["arg3"] from $string;
There's no real reason to use regexes here, you can use string and array functions instead.
You can explode the part after the ? (which you can get using substr to get a substring and strrpos to get the position of the last ?) into an array, and use unset to remove arg3, and then join to put the string back together.:
$string = "http://domain.com/php/doc.php?arg1=0&arg2=1&arg3=0";
$pos = strrpos($string, "?"); // get the position of the last ? in the string
$query_string_parts = array();
foreach (explode("&", substr($string, $pos + 1)) as $q)
{
list($key, $val) = explode("=", $q);
if ($key != "arg3")
{
// keep track of the parts that don't have arg3 as the key
$query_string_parts[] = "$key=$val";
}
}
// rebuild the string
$result = substr($string, 0, $pos + 1) . join($query_string_parts);
See it in action at http://www.ideone.com/PrO0a
preg_replace("arg3=[^&]*(&|$)", "", $string)
I'm assuming the url itself won't contain arg3= here, which in a sane world should be a safe assumption.
$new = preg_replace('/&arg3=[^&]*/', '', $string);
This should also work, taking into account, for example, page anchors (#) and at least some of those "weird characters" you mention but don't seem worried about:
function remove_query_part($url, $term)
{
$query_str = parse_url($url, PHP_URL_QUERY);
if ($frag = parse_url($url, PHP_URL_FRAGMENT)) {
$frag = '#' . $frag;
}
parse_str($query_str, $query_arr);
unset($query_arr[$term]);
$new = '?' . http_build_query($query_arr) . $frag;
return str_replace(strstr($url, '?'), $new, $url);
}
Demo:
$string[] = 'http://domain.com/php/doc.php?arg1=0&arg2=1&arg3=0';
$string[] = 'http://domain.com/php/doc.php?arg1=0&arg2=1';
$string[] = 'http://domain.com/php/doc.php?arg1=0&arg2=1&arg3=0#frag';
$string[] = 'http://domain.com/php/doc.php?arg1=0&arg2=1&arg3=0&arg4=4';
$string[] = 'http://domain.com/php/doc.php';
$string[] = 'http://domain.com/php/doc.php#frag';
$string[] = 'http://example.com?arg1=question?mark&arg2=equal=sign&arg3=hello';
foreach ($string as $str) {
echo remove_query_part($str, 'arg3') . "\n";
}
Output:
http://domain.com/php/doc.php?arg1=0&arg2=1
http://domain.com/php/doc.php?arg1=0&arg2=1
http://domain.com/php/doc.php?arg1=0&arg2=1#frag
http://domain.com/php/doc.php?arg1=0&arg2=1&arg4=4
http://domain.com/php/doc.php
http://domain.com/php/doc.php#frag
http://example.com?arg1=question%3Fmark&arg2=equal%3Dsign
Tested only as shown.