CodeIgniter - Search results - How to create good query and URI? - php

I'm working on some script and I would like to create search. My project is based on CodeIgniter and my desire is to have all code content compatibile with it.
So, I have already working on the query for searching but it's not good because it doesn't support more words than one. So if I enter word "test" in my search form (assume that the test word is in database in one of fields) there will be few results, but if I enter words "test test test" (again assume that the test words are in database in one of fields) there will be no any result.
My current query:
$this->db->select('title, content, date, hyperlink')->or_like(array('title' => $query, 'content' => $query))->order_by('id_article', 'desc')->get('news');
The next problem is with URI because if I search for "some article, today is sunny" there is problem with comma and in other cases probably with other disallowed characters too. I have read few other question there, but all that I found is $this->uri->uri_to_assoc(), which I think in my case wouldn't work, because I don't use English in my project.
What's the best solution for these two problems?

To solve the search issue you should probably explode the query into pieces.
$query = 'test test 2 test3';
$parts = explode(' ', $query);
Then loop through the parts and add or_like conditions.
foreach ($parts as $q)
{
$this->db->or_like(array('title' => $q, 'content' => $q));
}
Now it checks for any of the words.
You may also want to allow quoted values to be treated as one word so that "test 2" would search for the sequence test 2 and not just test and 2. You would need to adjust how you get parts, maybe by a regular expression like:
preg_match_all('/"(?:\\\\.|[^\\\\"])*"|\S+/', $query, $parts);
As for the invalid characters in the URI, pass the string through urlencode on one end then urldecode on the other.
$uri = urlencode('some article, today is sunny');

Related

To fetch a complete sentence containing the search key in it

I have to fetch a complete sentence from the given string in which the desired character must exist. Like say I have a search Key "different topic"and i am searching it in "Our community is defined by a specific set of topics in the help center; please stick to those topics and avoid asking for opinions or open-ended discussion. If your question is about the site itself, ask on our meta-discussion site. If you’re looking for a different topic, it might be covered on another Stack Exchange site."
After my search I want it to return as complete sentence "*If you’re looking for a different topic, it might be covered on another Stack Exchange site.*"
This is the complete sentence containing my search key too.
I have used the following for this but not getting the proper output:
substr($fp, strpos($fp, $search_string) - 100, 200).
This is all in PHP.
You really cannot do this using substr() but you can with a little regex:
[A-Z][^\\.;]*(different topic)[^\\.;]*
Here is an EXAMPLE
If you need the period at the end of the sentence, modify the regex slightly to remove the period from the character match at the end of the phrase, [^\\;] instead of [^\\.;]
[A-Z][^\\.;]*(different topic)[^\\;]*
I resolved my issue with this following code:-
Instead of this:-
substr($fp, strpos($fp, $search_string) - 100, 200);
I have used following to fetch the sentence with complete words containing my search key:-
$sentences = explode('.',$fp);
$subString = "";
foreach($sentences as $sentence) {
if(false !== stripos($sentence,$search_string)){
$subString = trim($sentence) . "\n";
}
}
and this helped me to fetch the proper result.

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.

Want to display few words before and end of search keyword

For example I have a string in database table
"This is a test and I want to test everything on my website using
testing tool. I need help of my people to search the new things on
portal but I can not find any source of help"
This data is in my mysql table
No when I search a word or string in this content then I want to display first 20 and next 20 words with Search string
For example if I search my people
Then I should get result as following
website using testing tool. I need help of my people to search the new things
Or if I search portal then it should give result as following
I need help of my people to search the new things on portal but I can not find any source of help
I tried using mysql like query but it show full content.
You can use mysql LIKE statement and then use php explode function to get the single sentence. Do a strpos checking on the exploded pieces to see whether you are taking the correct result.
$keyword = "portal";
$result_str = "This is a test and i want to test everything on my website using testing tool. I need help of my people to search the new things on portal but i can not find any source of help";
$suggestions = explode(".", $result_str);
$match = "";
foreach ($suggestions as $key => $value) {
if(strpos($value,$keyword) !==false)
$match = $value;
continue;
}
echo $match;

preg_replace limit issue, handling array values

I've been working with the Sphider search engine for an internal website, we need to be able to quickly search for contact details in exported .htm(l) files.
$fulltxt = ereg_replace("[_A-Za-z0-9-]+(\.[_A-Za-z0-9-]+)*#[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,3})", "\\0", $fulltxt);
I am replacing e-mail addresses with a convenient mailto: link so users can open Outlook straight from the search results.
However,
while (preg_match("/[^\>](".$change.")[^\<]/i", " ".$fulltxt." ", $regs)) {
$fulltxt = preg_replace("/".$regs[1]."/i", "<b>".$regs[1]."</b>", $fulltxt);
}
It replaces all matches in the search results with bold tags, which resuts into the tags been included in Outlook's 'To...' field. It looks something like this in HTML (thanks Yuriy):
<b>name</b>.surname#domain
I have tried adding a value to the 'limit' parameter:
while (preg_match("/[^\>](".$change.")[^\<]/i", " ".$fulltxt." ", $regs)) {
$fulltxt = preg_replace("/".$regs[1]."/i", "<b>".$regs[1]."</b>", $fulltxt, 1);
}
Supposingly this should be the solution to my problem by simply replacing only the first occurrence (being the name as the pattern is name-phone num-email and we always search by name), instead it only makes it incredibly slow to the point i get a timeout message from the server. I've been trying various solutions but have been out of luck.
Any ideas? Am i doing something wrong?
Thanks.
(*Original heavily edited).
Did I understand you right that something like this happens?
<b>email#domain</b>
Why don't you put tags into search results first, and only then apply "mailto:" anchors to emails? Added 's would be easy to filter out in the patter on that second step.

php search and replace

I am trying to create a database field merge into a document (rtf) using php
i.e if I have a document that starts
Dear Sir,
Customer Name: [customer_name], Date of order: [order_date]
After retrieving the appropriate database record I can use a simple search and replace to insert the database field into the right place.
So far so good.
I would however like to have a little more control over the data before it is replaced. For example I may wish to Title Case it, or convert a delimited string into a list with carriage returns.
I would therefore like to be able to add extra formatting commands to the field to be replaced. e.g.
Dear Sir,
Customer Name: [customer_name, TC], Date of order: [order_date, Y/M/D]
There may be more than one formatting command per field.
Is there a way that I can now search for these strings? The format of the strings is not set in stone, so if I have to change the format then I can.
Any suggestions appreciated.
You could use a templating system like Smarty, that might make your life easier, as you can do {$customer_name|ucwords} or actually put PHP code in your email template.
Try a RegEx and preg_replace_callback:
function replace_param($matches)
{
$parts = explode(',',$matches[0]);
//$parts now contains an array like: customer_name,TC,SE,YMD
// do some substitutions and:
return $text;
}
preg_replace_callback('/\[([^\]]+)\]/','replace_param',$rtf);
You can use explode on it to separate them into array values.
For Example:
$customer_name = 'customer_name, TC';
$get_fields = explode(',', $customer_name);
foreach($get_fields as $value)
{
$new_val = trim($value);
// Now do whatever you want to these in here.
}
Sorry if I'm not understanding you.

Categories