autocomplete search form cakephp - php

Hey there, I'm a total newbie and I'm looking for a way to have a search box with autocomplete just like google does.
I've searched and the best prospect that I've found seems to be http://www.pengoworks.com/workshop/jquery/autocomplete.htm which I found on a forum. The guy who suggested it says he uses it with http://code.google.com/p/searchable-behaviour-for-cakephp/ which is dead on because I've managed to install searchable on my last attempt at figuring out cakephp.
The thing is, I've not used much javascript before and I'm a bit confused as to what exactly I'm meant to be doing. The documentation with the autocomplete codes doesn't go into any detail that I can understand.
If we assume that I manage to get searchable behaviour installed correctly, could any kind person explain to me how I would go about making the autocomplete work?
It says to just use:
$("selector").autocomplete(url [, options]);
eg:
$("#input_box").autocomplete("autocomplete_ajax.cfm");
Autocomplete expects an input element with the id "input_box" to exist. When a user starts typing in the input box, the autocompleter will request autocomplete_ajax.cfm with a GET parameter named q
thats the bit I don't get. Where am I meant to put that? And once I've put it somewhere then do I just need to name one of my inputs "input_box"?
thanks in advance.

There are three steps:
1) create a totally normal form with an input field, using the Html helper in your view:
// app/views/foo_bars/search.ctp
<?php
echo $this->Form->create('FooBar');
echo $this->Form->input('field');
echo $this->Form->end('Submit');
?>
2) Have a jquery autocomplete fired:
// app/views/foo_bars/search.ctp
<?php
echo $this->Html->scriptBlock(
.'$("#FooBarField").autocomplete({'
.'source:"/foo_bars/find",'
.'delay: 100,'
.'select:function(event,ui){$(this).parent().parent().children("input").val(ui.item.id);},'
.'open:function(event,ui){$(this).parent().parent().children("input").val(0);}'
.'});'
array('inline' => false));
?>
3) Query a database through a controller to get possible values:
// app/controllers/foo_bars_controller.php
<?php
public function find() {
if ($this->RequestHandler->isAjax()) {
$this->autoLayout = false;
$this->autoRender = false;
$this->FooBar->recursive = -1;
$results = $this->FooBar->find('all', array('fields' => array('id', 'name'), 'conditions' => array('name LIKE "%'.$_GET['term'].'%"')));
$response = array();
$i = 0;
foreach($results as $result){
$response[$i]['value'] = $result['FooBar']['name'];
$response[$i]['id'] = $result['FooBar']['id'];
$i++;
}
echo json_encode($response);
}
}
?>

echo $this->Html->scriptBlock(
'$("#FooBarField").autocomplete({'
.'source:"/Search/find",'
.'delay: 100,'
.'select:function(event,ui){$(this).parent().parent().children("input").val(ui.item.id);},'
.'open:function(event,ui){$(this).parent().parent().children("input").val(0);}'
.'});'.
array('inline' => false));

Related

get all categories listing from database

Main purpose is to get all categories listing from database by passing variables to url and show it to the main page.here i have omitted some code bt i tried to clarify.
1.can I exclude encodeHtml() method, too difficult for me to understand
2.i am not getting specially this part of code and having my head for 4 days
foreach($cats as $cat) {
echo "<li><a href=\"/?page=catalogue&category=".$cat['id']."\"";//here id is 'category id' from database. this full line will echo what?
echo Helper::getActive(array('category' => $cat['id']));//it will output what ?
echo ">";
echo Helper::encodeHtml($cat['name']);//as from ur answer can we omit encodeHTML() method and use htmlspecialchars($cat['name']); instead ?
echo "</a>
3.any easier solution will be more appreciated
in our database we have 'id' and 'name' of catagory listing
please check below for reference
/*below is the code in header section of template */
<?php
$objCatalogue = new Catalogue();// creating object of Catalogue class
$cats = $objCatalogue->getCategories(); // this gets all categories from database
<h2>Categories</h2>
<?php
foreach($cats as $cat) {
echo "<li><a href=\"/?page=catalogue&category=".$cat['id']."\"";
echo Helper::getActive(array('category' => $cat['id']));
echo ">";
echo Helper::encodeHtml($cat['name']);
echo "</a></li>";
}
?>
/*below is the helper class which is Helper.php */
public static function getActive($page = null) {
if(!empty($page)) {
if(is_array($page)) {
$error = array();
foreach($page as $key => $value) {
if(Url::getParam($key) != $value) //getParam takes name of the parameter and returns us the value by $_GET
{
array_push($error, $key);
}
}
return empty($error) ? " class=\"act\"" : null;
}
}
//CHECK THIS LINE BROTHER
return $page == Url::currentPage() ? " class=\"act\"" : null;// url::currentPage returns the current page but what is 'class =act ' :(
}
public static function encodeHTML($string, $case = 2) {
switch($case) {
case 1:
return htmlentities($string, ENT_NOQUOTES, 'UTF-8', false);
break;
case 2:
$pattern = '<([a-zA-Z0-9\.\, "\'_\/\-\+~=;:\(\)?&#%![\]#]+)>';
// put text only, devided with html tags into array
$textMatches = preg_split('/' . $pattern . '/', $string);
// array for sanitised output
$textSanitised = array();
foreach($textMatches as $key => $value) {
$textSanitised[$key] = htmlentities(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8');
}
foreach($textMatches as $key => $value) {
$string = str_replace($value, $textSanitised[$key], $string);
}
return $string;
break;
}
}
Firstly, in your URL (/?page=catalogue&category=) you don't need to put &, as this is an HTML entity for actually displaying an ampersand in a web page. Just use /?page=catalogue&category=.
Secondly, you can use urlencode() to prepare strings for sending in the URL, and urldecode() on the other end.
In answer to your first point you just need to make sure that ANYTHING from the user (whether via $_POST or $_GET) is sanitized, prior to being used in code, output to a web page, or used in database queries. Use htmlspecialchars() for cleaning before outputting to a web page, and prepared statements prior to entering user input into a query.
In answer to your second point please read the documentation in the links I have provided above. Just reading the documentation on htmlspecialchars() will help you a lot.
Hope this helps.
Alright then.
<?php
foreach($cats as $cat) {
echo "<li><a href=\"/?page=catalogue&category=".$cat['id']."\"";
echo Helper::getActive(array('category' => $cat['id']));
echo ">";
echo Helper::encodeHtml($cat['name']);
echo "</a></li>";
}
?>
Im just going to kindof skim through it, because honestly if you really want to learn all this you should probably google the shit out of every piece of code you don't understand, it's the way we all learn things.
< ?php announces some php script to follow. And as you can see, there does follow some php code after.
foreach is a way of getting each element from an array or list and doing something to that element.
echo sends whatever string comes after it to the page, or whatever is listening to its output. In this case, it looks like the echo's are printing some <li> list item with an <a> anchor in it.
Helper::getActive(): Helper is some class that is defined somewhere, :: is syntax for calling a static function that belongs to the class (Helper in this case). getActive is the function name.
array('category' => $cat['id'] is a piece of code that creates an array with 1 element in it, being one with key 'category' and a value of whatever is in $cat['id'].
By looking at getActive: it looks like it's a function that checks the url for some value so it can determine which page to display. It also checks if the url contains errors.
By lookingat encodeHtml(): it looks like it's a function that makes sure that whatever text you're trying to put on the screen, isn't something that could cause harm. In some situations, people will try to make your server print javascript that could harm the user (by sending personal data to somewhere). The encodeHtml() will ensure that no such thing can be done by stripping certain characters from the text you're about to send to the page.
USE GOOGLE.

How can i run php code within array?

im using this php code (from a question on here):
<?php
define(TEMPLATES_LOCATION, 'templates/');
function TemplateFunction ($template, $replaces) {
$template = file_get_contents(TEMPLATES_LOCATION . $template);
if (is_array($replaces)) {
foreach($replaces as $replacekey => $replacevalue){
$template = str_replace('{$' . $replacekey . '}', $replacevalue, $template);
}
}
return $template;
}
$keys = array(
'TITLE' => 'This is page title',
'HEADER' => 'This is some header',
'GALLERY' => 'php while loop here'
);
echo TemplateFunction('body.tpl', $keys);
?>
The way my template file is set up is the following HTML:
<body>
<div id="gallery">{GALLERY}</div>
</body>
so where {GALLERY} is, the php script should replace that with my automatically generated <li><img src="images/'.$filename.'"/></li> which is being run in a while loop generated from a mysql request
what i thought might work is:
$keys = array(
'TITLE' => 'This is page title',
'HEADER' => 'This is some header',
'GALLERY' => 'while($row = mysql_fetch_array($result)){<li><img src="'.$row['filename'].'"/></li>})'
);
but it doesnt :(
Re your code:
$keys = array(
'TITLE' => 'This is page title',
'HEADER' => 'This is some header',
'GALLERY' => 'while($row = mysql_fetch_array($result)){<li><img src="'.$row['filename'].'"/></li>})'
);
I would consider it very poor practice to have PHP code embedded in your template data this way. Allow me to offer you a completely different solution...
Firstly, we need to encapsulate the code. The code you've shown above is trying to fetch data from a $result variable, but $result itself is obviously been set elsewhere. This isn't good, because if we ever want to change the way the gallery feature works, we would need to search all over the code to find different bits of it.
Instead, you should write the feature as a self-contained function (or a class if it's too complex for a single function), which would load the data, and process it.
Let's call that function loadGallery(). It might look something like this:
function loadGallery() {
$output = '';
$result = mysql_query('...gallery query here...');
while($row = mysql_fetch_array($result)) {
$output .= "<li><img src='{$row['filename']}'/></li>";
}
return '<ul>'.$output.'</ul>';
}
Obviously, it could be a lot more complex than that (eg you may want to paginate it, or offer category options; these would be written as parameters for the function). I've also not written any error checking, etc here for brevity.
Now that you've got that function, you can plug it into the template engine. You need to reference the function in your template.
You currently have template markers like this {TITLE}. In your code, these markers are swapped with plain text using str_replace(). That's fine. But in this case we now want to call a function instead, so we need to have a different kind of marker.
Let's write the gallery marker like this: {FUNCTION:loadGallery} instead of {GALLERY} as you currently have.
Now you can have an additional bit of code in your template engine that looks at these {function:} markers and replaces them with a function call. (You can keep the existing simple str_replace() method as well of course)
$funcReplaces = array( //similar to your existing $keys array, but for allowed functions
'loadGallery'
);
foreach($funcReplaces as $replaceFunc){
$template = str_replace('{function:' . $replaceFunc . '}', $replaceFunc(), $template);
}
This will run the function and put the output into the template.
So that answers the question for you.
What I should point out, however, is that there are a lot of other issues that you need to think about when writing a templating engine, from both a technical and security perspective. The above describes a basic way to resolve the specific question at hand, but it isn't a fantastic all-singing all-dancing template engine. It's still just a pretty basic one.
That's fine, if that's all you need, but if you expect this system to grow, it's worth noting that this whole area is that this is very much a problem that others have already solved, and solved well. There are several very good templating engines available for PHP. I would suggest that your best course of action would be to investigate some of them, and maybe use one of those instead of writing your own.
Some that you could try:
Smarty
Twig
Mustache
Hope that helps.
You cannot "execute PHP code within an array". You simply build the array programmatically:
while (/* something */) {
$keys['GALLERY'][] = $something;
}
I have found the following code that i've written to be the right solution to my issue:
$gallery = array();
while($row = mysql_fetch_assoc($result))
{
$gallery[] = '<li><img src="'.$row['gallery_image_filename'].'" width="'.$final_image_width.'" height="auto" style="margin: '.$other_margin.'px '.$gallery_image_margin.'px '.$other_margin.'px 0px"/></li>';
}
$gallery = implode(' ', $gallery);
i then can concatenate my $gallery variable into the 'GALLERY' => 'value' value and it outputs all the database results as required. Thanks to all for your help :)
Well, you can create an class with __toString magic method which will process all images on your gallery and then return the string.
class TemplateGallery{
private $images = array();
public function addImage($src){
$images[] = $src;
}
public function __toString(){
$str = "";
foreach($images as $image){
$str .= sprintf('<li><img src="%s"></li>',$image);
}
return $str;
}
}
Well, as the guy in comments said, it's too "hard", so, you can use an "pre-process" function, that will process your images array, and then return your template string.
$images = array(/* Put images src here */);
function processGallery($images){
$str = "";
foreach($images as $image){
$str .= sprintf('<li><img src="%s"></li>',$image);
}
return $str;
}
And then call that function on your array.

Adding an Array multiple times in the DB via Controller

I'm having an issue producing this array multiple times upon how many coupons purchased.
Now it looks like
$coupon_array = array(
'user_id'=>$_POST["user_id"],
'mergent_id'=>$_POST["merchant_id"],
'deals_id'=>$_POST["deal_id"],
'order_id'=>$order_id,
'secret'=>$secret,
'expire_time'=>$time,
'create_time'=>$time,
'status'=>1
);
$this->common_model->insertData('coupon', $coupon_array);
But i have a post value such as:
"quantity"=>$_POST["quantity"]
and i would like to produce this X times. Example:
$quantity x $this->common_model->insertData('coupon', $coupon_array);
Sorry for my english, and i hope i explain this so it's understandable... ;)
Another one! when we insert the coupons they all have the same md5($secret), is it possible to have that also with all the different code...
$secret = md5($secret);
$coupon_array = array(
'user_id'=>$_POST["user_id"],
'mergent_id'=>$_POST["merchant_id"],
'deals_id'=>$_POST["deal_id"],
'order_id'=>$order_id,
'secret'=>$secret,
'expire_time'=>$time,
'create_time'=>$time,
'status'=>1
);
Well, if I understand what you want, you can use for, but that's obvious:
for($i=0; $i<$this->input->post('quantity');$i++) {
$coupon_array['secret'] = md5($coupon_array['secret'].$i);
$this->common_model->insertData('coupon', $coupon_array);
}
Also, never use $_POST["..."] in CodeIgniter, use only $this->input->post('...') as it escapes properly. More info about input class can be found here.
for ($i=0; $i<$quanity; $i++) {
$this->common_model->insertData('coupon', $coupon_array);
}

PHP & MySQL with options page

Finally completed the frontend of my website, I am now looking at coding the backend which needs an overhaul, the coding is very messy and uses far too many SQL Connections and commands, so much so that the host is complaining about it.
One of the main problems I am having is the Site Settings page, problem is this page will soon contain over 10 different options, and I prefer not to have a MySQL Update simply updating the option field to what it already is, so I am wondering if anyone has any ideas?
This is the structure of my options table, nice and simple which I recently changed from an awful layout.
What would be the best way to edit these options without having to update every single one, and what would be the best way to have them in a function? Currently, the function I have was made back when I was new to coding, and you can see that is is very uneffective(note it uses the old table structure)
function site_upd($site_title, $site_email, $maint_status, $maint_mess, $upload_disable, $site_url, $reg_status, $land_mess)
{
if( !$site_title )
{
echo $this->errorMessage('There was no <b>site title</b> supplied, therefore we can not continue with this request.', 'error');
}
else
{
$this->logQuery('Updated site settings');
$query = "UPDATE `table`.`settings` SET `site_title` = '".$site_title."', `site_email` = '".$site_email."', `maint_status` = '".$maint_status."', `maint_mess` = '".$maint_mess."', `upload_disable` = '".$upload_disable."', `site_url` = '".$site_url."', `registration_status` = '".$reg_status."', `landing_mess` = '".$land_mess."' WHERE `settings`.`sid` = '1'";
mysql_query($query) or die(''.mysql_error()); } }
So yeah, there is the awful old structure and my old way of doing things, before I get stuck into coding I want other peoples opinions on what is the best way to do this!
You can work with $_POST Variable to simplify the update method.
This is what I usually do:
First I create a non specific function to update:
function update_db($table, $id,$idvalue,$field,$fieldvalue){
return mysql_query("update ".$table." set ".$field."=".$fieldvalue." where ".$id."=".$idvalue);
}
Then i create the specific function to the table (config i.e):
function update_table_config($name,$value){
return update_db("config","name",$id,"value",$value);
}
In the form i call all <input> like its name on the table:
Site Name: <input type="text" name="site_name">
...
and in the "action" page i check $_POST array:
$data_array=$_POST;
if(check_variables($data_array)){
foreach ($data_array as $key=>$value){
update_table_config($key,$value);
}
}
the function check_variables has all the checks that you need for all the fields:
function check_variables($data){
if($data["site_title"]=="") return false;
if(!is_numeric($data["landing_mess"])) return false;
...
return true;
}
with this methods if in the future you have to include more fields in the configuration table you only have to add the <input> field and a check in check_variables function if needed

MODX parse error function implode (is it me or modx?)

Update 4-June-2010: This appears to be a bug in MODx v 1.0.3, nothing to do with the implode function but rather a problem with mis-matched datatypes in the resulting filter clause. Bug has been filed with JIRA: MODX-2035.
Hi, I cannot for the life of me figure this out, maybe someone can help.
Using MODX a form takes user criteria to create a filter and return a list of documents. The form is one text field and a few checkboxes. If both text field and checkbox data is posted, the function works fine; if just the checkbox data is posted the function works fine; but if just the text field data is posted, modx gives me the following error:
Error: implode() [function.implode]: Invalid arguments passed.
I've tested this outside of modx with flat files and it all works fine leading me to assume a bug exists within modx. But I'm not convinced. Here's my code:
<?php
$order = array('price ASC'); //default sort order
if(!empty($_POST['tour_finder_duration'])){ //duration submitted
$days = htmlentities($_POST['tour_finder_duration']); //clean up post
array_unshift($order,"duration DESC"); //add duration sort before default
$filter[] = 'duration,'.$days.',4'; //add duration to filter[] (field,criterion,mode)
$criteria[] = 'Number of days: <strong>'.$days.'</strong>'; //displayed on results page
}
if(!empty($_POST['tour_finder_dests'])){ //destination/s submitted
$dests = $_POST['tour_finder_dests'];
foreach($dests as $value){ //iterate through dests array
$filter[] = 'searchDests,'.htmlentities($value).',7'; //add dests to filter[]
$params['docid'] = $value;
$params['field'] = 'pagetitle';
$pagetitle = $modx->runSnippet('GetField',$params);
$dests_array[] = ''.$pagetitle.'';
}
$dests_array = implode(', ',$dests_array);
$criteria[] = 'Destinations: '.$dests_array; //displayed on results page
}
if(is_array($filter)){
$filter = implode('|',$filter);//pipe-separated string
}
if(is_array($order)){
$order = implode(',',$order);//comma-separated string
}
if(is_array($criteria)){
$criteria = implode('<br />',$criteria);
}
echo '<br />Order: '.$order.'<br /> Filter: '.$filter.'<br /> Criteria: '.$criteria;
//next: extract docs using $filter and $order, display user's criteria using $criteria...
?>
The echo statement is displayed above the MODX error message and the $filter array is correctly imploded.
Any help will save my computer from flying out the window.
Thanks
I think your problem lies here :
$dests_array = implode(', ',$dests_array);
$dest_array may be empty and not even initialized if $dests is empty.
This really should be posted in the MODx forums. I love stackoverflow, but MODx is more niche.

Categories