single jquery autocomplete for multiple form dropdown - php

how can i use a single jquery autocomplete for multiple form dropdown?
here is my view page(header):
$("#full_name").autocomplete({
source: "<?php echo site_url('autocomplete/get_names');?>"
});
$("#department").autocomplete({
source: "<?php echo site_url('autocomplete/get_dept');?>"
});
*** and other like these for subjects, zip and country.
controller page:
public function get_names(){
$this->load->model('autocomplete_model');
if (isset($_GET['term'])){
$q = strtolower($_GET['term']);
$this->autocomplete_model->get_fullnames($q);
}
}
*** and other functions...
model page:
function get_fullnames($q)
{
$match = $q;
$this->db->select('full_name');
$this->db->like('full_name', $match,'after');
$query = $this->db->get('employee_list');
if($query->num_rows > 0){
foreach ($query->result_array() as $row){
$row_set[] = htmlentities(stripslashes($row['full_name']));
}
echo json_encode($row_set);
}
}
how can i implement a single search term that could be used for multiple criteria?
thank you guys in advance..

This is not going to scale; as your database tables grow, this implementation will become very sluggish. What you need to do is use an indexing engine to allow Full Text Searching.
MySQL does not allow Full Text Search on InnoDB tables (actually, it was just released in the latest version, but it's still in it's infancy). Look into using Elastic Search, Sphinx, or Solr.
Poke around StackOverflow to find the best engine for you - there are many helpful questions that have been asked in the past regarding this problem. Hopefully that sets you on the right course.

Related

Pagination not getting previous cursor google app engine in php

Hi have implement pagination in google app engine
with this code
https://github.com/GoogleCloudPlatform/php-docs-samples/blob/master/datastore/api/src/functions/concepts.php
function cursor_paging(DatastoreClient $datastore, $pageSize, $pageCursor = '')
{
$query = $datastore->query()
->kind('Task')
->limit($pageSize)
->start($pageCursor);
$result = $datastore->runQuery($query);
$nextPageCursor = '';
$entities = [];
/* #var Entity $entity */
foreach ($result as $entity) {
$nextPageCursor = $entity->cursor();
$entities[] = $entity;
}
return array(
'nextPageCursor' => $nextPageCursor,
'entities' => $entities
);
}
geting the next Cursor but did not get the previous cursor form this
Indeed, dealing with the previous cursor is something of a problem - even in other languages, it seems to be the bigger issue, when paginating data. There isn't much data or articles in the internet as well, on how to achieve that.
I will try to explain as much as I can, the possibilities, I believe, are available to you.
As per this other question from the Community here, you can create a new cursor with the information previous page, so you can use it for your pagination. This means that you would have three cursors now: $pageCursor, $nextPageCursor and $previousPageCursor. Using like this, you should be able to maintain the actual data, before setting the one for the next page.
Besides that, there is a reverse method in PHP that might help you, in case you want to count how many pages there will be on your application and put it backwards in the previous cursor. This way, you will have the inverted order, to use in your pagination as well - I still believe that giving a try in the first option, would be the best.
I have found some other useful questions from the Community, that might help you achieve your goal - that I believe are worth taking a look at it as well.
How do appengine cursors work?
App Engine datastore paging - previous page
Let me know if the information helped you!

PHP/MySQL better user searching

In trying to rejuvinate code I wrote mostly 14+ years ago. I've come to see that the lovely little setup I wrote then was... lacking in certain places, namely handling user inputs.
Lesson: Never underestimate users ability to inject trash, typos, and dupes past your validators.
The old way is reaching critical mass as there are 470 items in a SELECT dropdown now. I want to reinvent this part of the process so I don't have to worry about it hitting a breaking point.
So the idea is to build a fuzzy search method so that after the typist enters the search string, we check against five pieces of data, all of which reside in the same row.
I need to check the name submitted against the Stage Name, two also-known-as names, as well as their legal name and as a final check against a soundex() index based on their Stage Name (this catches a few spelling errors missed otherwise)
I've tried a complicated block of code to check these things (and it doesn't work, mostly because I think I coded the comparisons too strict) as part of a do/while loop.
In the below, var $Rin would contain the user supplied name.
$setr = mysql_query("SELECT ID,StageName,AKA1,AKA2,LegalName,SoundEx FROM performers");
IF ($R = mysql_fetch_array($setr)) {
do {
$RT = substr(trim($Rin), 5);
$RT1 = substr($R[1], 5);
$RT2 = substr($R[2], 5);
$RT3 = substr($R[3], 5);
$RT4 = substr($R[4], 5);
$RTx = soundex($RT);
IF ($RT == $RT1) {
$RHits[] = $R[0];
}
IF ($RT == $RT2) {
$RHits[] = $R[0];
}
IF ($RT == $RT3) {
$RHits[] = $R[0];
}
IF ($RT == $RT4) {
$RHits[] = $R[0];
}
IF ($RTx == $R[5]) {
$RHits[] = $R[0];
}
} while ($R = mysql_fetch_array($setr));
}
The idea being that I'll build an array of the ID#'s of the near hits, which I'll populate into a select dropdown that has only hopefully fewer hits that the whole table. Which means querying for a result set from the contents of that array, in order to display the Performer's name in the SELECT dropdown and pass the ID# as the value for those choices.
Thats when I hit the 'I need to use an array in my WHERE clause' problem, and after finding that answer, I am starting to suspect I'm out of luck due to Stipulation #2 below. So I started looking at alternate search methods and I'm not sure I've gotten anywhere but more confused.
So, is there a better way to scan a single table for six fields, checking five against user input and noting the sixth for display in a subset of the original table?
Thought process:
Against the whole table, per record, test $Rin against these tests in this order:
$Rin -> StageName
$Rin -> AKA1
$Rin -> AKA2
$Rin -> LegalName
soundex($Rin) -> SoundEx
where a hit on any of the five operations adds the ID# to a result array that is used to narrow the results from 470 performers down to a reasonable list to choose from.
Stipulations:
1) As written, I know this is vulnerable to an SQL injection attack.
2) Server runs PHP 4.4.9 and MySQL 4.0.27-Standard, I can't upgrade it. I've got to prove it works before money will be spent.
3) This is hobby-level stuff, not my day job.
4) Performers often use non-English names or elements in their names, and this has led to typos and duplication by the data entry typists.
I've found a lot of mysqli and PDO answers for this sort of thing, and I'm seeing a lot of things that only half make sense (like link #4 below). I'm working on getting up to speed on these things as I try and fix whats become broken.
Places already looked:
PHP mysql using an array in WHERE clause
PHP/MySQL small-scale fuzzy search
MySQL SubString Fuzzy Search
Sophisticated Name Lookup
I mentioned in the comments that a Javascript typeahead library might be a good choice for you. I've found Twitter's Typeahead library and Bloodhound engine to be pretty robust. Unfortunately, the documentation is a mixed bag: so long as what you need is very similar to their examples, you're golden, but certain details (explanations of the tokenizers, for example) are missing.
In one of the several questions re Typeahead here on Stack Overflow, #JensAKoch says:
To be honest, I think twitter gave up on typeahead.js. We look at 13000 stars, a full bugtracker with no maintainer and a broken software, last release 2015. I think that speaks for itself, or not? ... So, try one of the forks: github.com/corejavascript/typeahead.js
Frankly, in a brief check, the documentation at the fork looks a bit better, if nothing else. You may wish to check it out.
Server-side code:
All of the caveats of using an old version of PHP apply. I highly recommend retooling to use PDO with PHP 5, but this example uses PHP 4 as requested.
Completely untested PHP code. json_encode() would be better, but it doesn't appear until PHP 5. Your endpoint would be something like:
headers("Content-Type: application/json");
$results = mysql_query(
"SELECT ID,StageName,AKA1,AKA2,LegalName,SoundEx FROM performers"
);
$fields = array("ID","StageName","AKA1","AKA2","LegalName","SoundEx");
echo "[";
$first = true;
while ($row = mysql_fetch_array($results)) {
($first) ? $first = false : echo ',';
echo "\n\t,{";
foreach($fields as $f) {
echo "\n\t\t\"{$f}\": \"".$row[$f]."\"";
}
echo "\n\t}";
}
echo "]";
Client-side code:
This example uses a static JSON file as a stub for all of the results. If you anticipate your result set going over 1,000 entries, you should look into the remote option of Bloodhound. This would require you to write some custom PHP code to handle the query, but it would look largely similar to the end point that dumps all (or at least your most common) data.
var actors = new Bloodhound({
// Each row is an object, not a single string, so we have to modify the
// default datum tokenizer. Pass in the list of object fields to be
// searchable.
datumTokenizer: Bloodhound.tokenizers.obj.nonword(
'StageName','AKA1','AKA2','LegalName','SoundEx'
),
queryTokenizer: Bloodhound.tokenizers.whitespace,
// URL points to a json file that contains an array of actor JSON objects
// Visit the link to see details
prefetch: 'https://gist.githubusercontent.com/tag/81e4450de8eca805f436b72e6d7d1274/raw/792b3376f63f89d86e10e78d387109f0ad7903fd/dummy_actors.json'
});
// passing in `null` for the `options` arguments will result in the default
// options being used
$('#prefetch .typeahead').typeahead(
{
highlight: true
},
{
name: 'actors',
source: actors,
templates: {
empty: "<div class=\"empty-message\">No matches found.</div>",
// This is simply a function that accepts an object.
// You may wish to consider Handlebars instead.
suggestion: function(obj) {
return '<div class="actorItem">'
+ '<span class="itemStageName">'+obj.StageName+"</span>"
+ ', <em>legally</em> <span class="itemLegalName">'+obj.LegalName+"</span>"
}
//suggestion: Handlebars.compile('<div><strong>{{value}}</strong> – {{year}}</div>')
},
display: "LegalName" // name of object key to display when selected
// Instead of display, you can use the 'displayKey' option too:
// displayKey: function(actor) {
// return actor.LegalName;
// }
});
/* These class names can me specified in the Typeahead options hash. I use the defaults here. */
.tt-suggestion {
border: 1px dotted gray;
padding: 4px;
min-width: 100px;
}
.tt-cursor {
background-color: rgb(255,253,189);
}
/* These classes are used in the suggestion template */
.itemStageName {
font-size: 110%;
}
.itemLegalName {
font-size: 110%;
color: rgb(51,42,206);
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script>
<p>Type something here. A good search term might be 'C'.</p>
<div id="prefetch">
<input class="typeahead" type="text" placeholder="Name">
</div>
For ease, here is the Gist of the client-side code.

How to make search autocomplete faster?

I have implemented a basic auto-complete feature using jQuery autocomplete. I am querying DB every time which is making auto-complete thing quite slow. I am looking for ways to make it faster much like Quora.
Here is the code from front-end:
<script type="text/javascript">
var URL2 = '<?php e(SITE_URL); ?>fronts/searchKeywords';
jQuery(document).ready(function(){
var CityKeyword = jQuery('#CityKeyword');
CityKeyword.autocomplete({
minLength : 1,
source : URL2
});
});
</script>
Here is the code from server side:
function searchKeywords(){
if ($this->RequestHandler->isAjax() ) {
$this->loadModel('Expertise_area');
Configure::write ( 'debug',0);
$this->autoRender=false;
$expertise=$this->Expertise_area->find('all',array(
'conditions'=>array('Expertise_area.autocomplete_text LIKE'=>'%'.$_GET['term'].'%'),
'fields' => array('DISTINCT (Expertise_area.autocomplete_text) AS autocomplete_text'),
'limit'=>5
));
$i=0;
if(!empty($expertise)){
$len = strlen($_GET['term']);
foreach($expertise as $valueproductname){
$pos = stripos($valueproductname['Expertise_area']['autocomplete_text'],$_GET['term']);
$keyvalue = "";
if($pos == 0) {
$keyvalue= "<strong>".substr($valueproductname['Expertise_area']['autocomplete_text'],$pos,$len)."</strong>"
.substr($valueproductname['Expertise_area']['autocomplete_text'],$len);
}else {
$keyvalue= substr($valueproductname['Expertise_area']['autocomplete_text'],0,$pos)."<strong>"
.substr($valueproductname['Expertise_area']['autocomplete_text'],$pos,$len)."</strong>"
.substr($valueproductname['Expertise_area']['autocomplete_text'],$pos+$len);
}
$response[$i]['value']=$valueproductname['Expertise_area']['autocomplete_text'];
$response[$i]['label']="<span class=\"username\">".$keyvalue."</span>";
$i++;
}
echo json_encode($response);
}else{
}
}
}
I have researched a bit and so far following solutions are worth looking at:
Query data on page load and store it in COOKIE to be used in future.
Implement some caching mechanism (memcache??). But my website is on Cakephp which does it internal cahcing if I am right. So will it be worth to go in this direction.
Use some third party indexing mechanism like Solr, Lucene etc. Don't know much about this.
Implement a much complex "Prefix Search" myself
What is the right way to go about it? Please help me out here.
I've never tried this but will be doing it soon for a project I'm working on.
I always considered the possibility of during the initial page load recieveing some AJAX (or perhaps just including it in the page) the top 10 words for each alphabet letter.. e.g.
A - apples, anoraks, alaska, angela, aha, air, arrgh, any, alpha, america
B - butter, bob etc.....
This way when user presses A-Z you can instantly provide them with 10 of the most popular keywords without any further requests, as you already have them stored in an array in the JS.
I'm not sure of size/memory usage but this could be extended further to handle the first 2 letters, e.g. AA, AB, AC.....BA, BB, BC.... ZA, ZB, ZZ... of course many combinations such as words starting with ZZ won't have any data unless it's a music site and it's ZZ Top! This means it probably won't take up so much memory or bandwidth to send this data during initial page load. Only when the user types the 3rd letter do you need to do any further data lookups/transfers.
You auto-update this data every day, week or whatever depending on site usage and the most popular searches.
I am adding a solution to my question which I figured out after a lot of research.
Problem was:
I was using Ajax to fetch keywords from database every time a user changes text in search box
I was doing a wild card search to match search item within entire strings and not just starting of keywords for ex. "dev" would return "social development", "development" etc
Solution:
I have a fixed array of keywords (200) which is not going to increase exponentially in near future. So, instead of doing complex indexing I am currently sending all keywords in an array.
I am sending this data in an array on page load since it is small. If it becomes large, I will fetch it in background via some ajax in different indexed arrays.
I am using jQuery's Autocomplete widget to do rest of thing for me.
For highlighting search item, I am using a hack by working around __renderItem. (Copied from Stackoverflow. Thanks to that!!)
Code:
function monkeyPatchAutocomplete() { //Hack to color search item
jQuery.ui.autocomplete.prototype._renderItem = function( ul, item) {
var re = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + this.term + ")(?![^<>]*>)(?![^&;]+;)", "gi");
var t = item.label.replace(re,"<span style='font-weight:bold;color:#434343;'>" +
"$&" +
"</span>");
return jQuery( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + t + "</a>" )
.appendTo( ul );
};
}
function getKeywords(){
//Function that returns list of keywords. I am using an array since my data is small.
//This function can be modified to fetch data in whatever way one want.
//I intend to use indexed arrays in future if my data becomes large.
var allKeywords = <?php echo json_encode($allKeywords); ?>;
return allKeywords;
}
jQuery(document).ready(function(){
monkeyPatchAutocomplete();
var CityKeyword = jQuery('#CityKeyword');
CityKeyword.autocomplete({
minLength : 1,
source : getKeywords()
});
});

PHP, MYSQL,JSOn Fast search functionality tips for social networking website

Hi I am developing social networking website and need a suggestion. I am using codeignitor framework, php as core language and jQuery as client side script.
Now I want to implement user search functionality to the website where a user can search for another users.
If I am using pagination with php it is bit slow and performance is not fast and even if the database will be huge then it will be more slow.
so what I have tried is, I made query of first 1000 people and encoded with json and showing first 10 results at a time by using this plugin http://www.stephenrhoades.com/?p=8
Is there anyone who can help my what all thing I need to follow here including technology, tips, query, mysql database etc.
Here is my current function in model
function search_user($cntry,$male,$female,$age_min,$age_max){
$this->db->select('user_profiles.user_id,user_profiles.first_name,
user_profiles.birthday,user_profiles.gender,user_profiles.picture,
user_profiles.last_active,location.city,location.country');
$this->db->from('user_profiles');
$this->db->join('location', 'user_profiles.user_id = location.user_id');
$this->db->limit(800);
// Search condition :::: Country
if($cntry){
$this->db->like('location.country',$cntry, 'both');
}
// Search condition :::: Male or Female
if($male==1 && $female==0) { $g='Male'; $this->db->like('user_profiles.gender',$g, 'both'); }
if($male==0 && $female==1) { $g='Female'; $this->db->like('user_profiles.gender',$g, 'both'); }
// Search condition :::: Age range
if($age_min && !$age_max){
$this->db->where('(YEAR(NOW())-YEAR(user_profiles.birthday)) >= ', $age_min);
}
if($age_min && $age_max){
$this->db->where('(YEAR(NOW())-YEAR(user_profiles.birthday)) >= ', $age_min);
$this->db->where('(YEAR(NOW())-YEAR(user_profiles.birthday)) <= ', $age_max);
}
$this->db->order_by("user_profiles.last_active", "desc");
$query = $this->db->get();
$data=array();
foreach ($query->result() as $row){
$row->last_active=$this->online_status($row->last_active);
$row->birthday=$this->birthday($row->birthday);
$data[]=$row;
}
if ($query->num_rows() > 0)
{
return $data;
}
else
{
$data = array(
'result' =>'404'
);
return $data;
}
}
Thanks in advance
There are numerous factors that could lead to this process being slow. These are questions that we'd need to address:
What columns are you searching in your database?
Are those columns indexed?
What does your query look like? Are you only returning necessary columns?
How quickly do you want to show results? Immediately as user types, or after they click 'search'?
How do you return results?
How do you display results?
Generally, you can search VERY large datasets in a matter of milliseconds - so I doubt the database is the issue as long as you have things set up correctly.
OK, with all that being said...
If you do have a VERY large social network, I would recommend implementing something like Zend Search Lucene. It's a search index and can be implemented into CodeIgniter pretty easily:
http://www.cmjackson.net/2009/02/17/how-to-use-zend_search_lucene-with-the-php-framework-codeigniter/
You can add your users, their profile data, posts, comments, etc. into the index and search it with a powerful language processing query language, and return results very quickly and in any format you wish. This is very easy to turn into a "live" search with ajax and json.

select from dropdown list containing sql data

Pls help.
I am working on a php project and this requires adding and altering data from the SQL database. There are two tables involved with this: emp which contains employee details and pay containing payroll records for each employee.
I would like to have a dropdown list containing all employee names (empname) from the database. Below the list is a form where the user shall input the payroll details. These details will then be saved into the SQL pay table corresponding to the employee name selected.
I've tried searching over the web but it doesn't seem to similar to my problem. How should I do this? Thanks!
Wihtout knowing any more details about your datbase, table structure and other stuff, this is closes that I could get.
<?php
/* Connect to SQL and retreive data */
$sqlConf = array('u'=>'username','p'=>'password','h'=>'localhost','d'=>'myDatabase');
$sqlCon = mysql_connect($sqlConf['h'], $sqlConf['u'], $sqlConf['p']);
if ($sqlCon) {
$emp = array();
mysql_select_db($sqlConf['d'], $con);
$result = mysql_query("SELECT * FROM emp");
while($row = mysql_fetch_array($result)) { $emp[] = $row; }
mysql_close($sqlCon);
}
/* Generate select box contents */
$html = '<select name="emp">';
$html .= '<option>Employee list</option>';
if (!empty($emp)) {
foreach ($emp as $k => $v) {
$html .= '<option value="'.$v['empid'].'">'.$v['empname'].'</option>';
}
}
$html .= '</select>';
/* Output */
echo $html;
?>
Sounds like you need to learn some basic php/SQL. The basic outlines of the problem are:
Query the dropdown list from SQL, and display in an option-select.
When they the form submit, send a corresponding query to update the database.
Is there some particular aspect of this problem that you can't get past?
This can be solved in any number of ways and the overall structure, design and layout of your application would dictate which route to go.
You could have classes that represent your database objects, classes that represent your forms, you could print your forms by mixing php and html like a crazy person and so on and so on.
Then it all depends on if you will be using ajax or not.
So give us a bit more information about how your application is designed and that will probably help.
If you have not started at all I would suggest you to look into some of the many frameworks. Zend Framework or Symphony for example. They have a good way of handling db abstractions and forms creation etc.

Categories