In CakePHP, I am trying to create a autocomplete function from a textbox, using this tutorial: http://bakery.cakephp.org/articles/matt_1/2011/08/07/yet_another_jquery_autocomplete_helper_2
I keep getting a
Error: AutoCompleteHelper could not be found.
Undefined index: autoCompleteText
I am unsure how to fix this as I have tried relocating the files and still the same error.
I create the below files and copy the code from the tutorial,
create the auto_complete.php in the view/helpers directory,
and create webroot/js/views/helpers/auto_complete.js.
controller - Tests
function auto_complete
class TestsController extends AppController {
public $helpers = array('Html', 'Form', 'Session','Js','AutoComplete');
public function auto_complete() {
$this->loadModel('Tutor');
debug( $this->params);
$terms = $this->Tutor->find('all', array(
'conditions' => array(
'Tutor.first_name LIKE' => $this->params['url']['autoCompleteText'].'%'
),
'fields' => array('Tutor.first_name'),
'limit' => 3,
'recursive'=>-1,
));
$terms = Set::Extract($terms,'{n}.Tutor.first_name');
$this->set('terms', $terms);
$this->layout = '';
}
view
auto_complete.ctp
<?php
echo $this->AutoComplete->input(
'Tutor.first_name',
array(
'autoCompleteUrl'=>$this->Html->url(
array(
'controller'=>'tests',
'action'=>'auto_complete',
)
),
'autoCompleteRequestItem'=>'autoCompleteText',
)
);
if(isset($terms)) {
echo $this->Js->object($terms);
}
echo $this->Form->create('');
echo $this->Form->input('type', array('label' => 'Choose' ));
echo $this->Form->end('send');
?>
I had a good look around previous posts and I really couldnt solve the problem.
Cakephp form input with autocomplete
The tutorial you're looking at is for CakePHP 1.x (it's from August 2011, Cake 2 came out in October '11), but you're running Cake 2.5. The naming standards have changed between 1.x and 2.x, so Cake can't see your helper.
First: Your main problem is that you're naming your helper auto_complete.php when it should be AutoCompleteHelper.php.
Second, you are placing it in the wrong directory. In Cake 1.x, helpers lived under /view/helpers/. In 2.x, they live under /View/Helper/.
Third, regarding the undefined index error, you need to understand how this helper works in the first place, and why you're implementing it incorrectly.
The controller action auto_complete should not have a view. It's just a data source. When you use the helper, it loads the Javascript, which does its magic by polling /auto_complete?autoCompleteText=stringgoeshere.
You might notice that you removed $this->layout = 'ajax'; from the controller action, probably because your toolbars weren't rendering. They weren't supposed to. It's just a datasource, it NEEDS the ajax layout, and there should be no view on that action.
Because you were trying to put a form on your auto_complete action and not on another action, the helper was looking for the query parameter autoCompleteText, not finding it, and displaying an error.
You can solve this by changing the auto_complete action back as close as possible to how it was in the example, deleting auto_complete.ctp, and by trying to use the helper in the correct view, like add.ctp.
Fourth: You shouldn't be using jsHelper anymore. It's been deprecated in 2.5 and is going to disappear in the future. Basically, the tutorial is obsolete.
However, it's really easy to just replace $this->set('terms', $terms); with return json_encode($terms) and write your own piece of JS to make an AJAX call. I suggest incorporating Typeahead.js.
Finally: You should consult the 1.x -> 2.x migration guide, and as well, once you get your helper running you've got some other typos in your code that will break it anyway- "Ttuor.first_name", for example. Good luck!
Related
I would like to create reusable code in controller in "Cakephp way". I would like to replace always one field in few controllers before render website. For example I would like to replace string in field "body". I can do this like this in show method:
public function show($id = null) {
$site = $this->Sites->findById($id)->first();
$new_value = 'test2';
$site['body'] = str_replace('test', $new_value, $site['body']);
}
Is there any better way to do this in cakephp way for example in initalize method or beforeRender? I can't use behavior here.
EDIT:
I know about components, but how to use it to replace all $site['body] (in my code) for all controller methods (so I would like to do this automatic, like behavior for entity)?
Read about Components.
Components are packages of logic that are shared between controllers. CakePHP comes with a fantastic set of core components you can use to aid in various common tasks. You can also create your own components. If you find yourself wanting to copy and paste things between controllers, you should consider creating your own component to contain the functionality. Creating components keeps controller code clean and allows you to reuse code between different controllers.
And see Component Callbacks.
You can use component
https://book.cakephp.org/3.0/en/controllers/components.html
Don't forget to load it in appController or where your need it
After edit :
#nexequ
Maybe if you set the beforeRender in your appController
public function beforeRender()
{
debug($this->request);
}
In $this->request->data array you have your data to replace.
Exemple:
data => array(
'Reunion' => array(
'begin' => '2017-01-13 20:00:00',
'end' => '2017-01-13 20:30:00'
)
If you find the way to get the model ("Reunion" in my example.)
You can do a trick like
replace --> $this->request->data[$model]['body']
I found solution with burzum help, I can use virtual property in src/Model/Entity:
protected function _getBody() {
$new_value = 'test2';
$test = str_replace('test2', $new_value, $this->_properties['body']);
return $test;
}
It will replace for instance 'test2' with $new_value in all controller methods.
Ok so i've got a big problem with CodeIgniter flexibility. I've many personal rules (like 20) targeting an input in a form within a huge project.
Everything work while I use the classic "callback_" system by CodeIgniter. I just put the methods in the same class than the form check and it checks it correctly.
My problem is :
1) I'd like to use all these rules in another form_validation in another controller without copy/paste the code ; we all know it's dirty/evil.
2) Ideally, i'd appreciate to put these rules in a big library, because it takes something like 800 lines and this is not a good idea to let it be in my controller ; as I said this project is quite huge.
It's 6 hours i'm looking for a solution and there's absolutely nothing clean :
I already have a MY_Form_Validation to put some general rules but i don't like the idea to mix my specific rules in a global class which will call it everytime vainly. Plus these rules contain many libraries, models, native CI core methods such as $this->input->post() which generate errors when I put everything in this MY_Form_Validation. Not the good solution :(
I created a MY_Controller including a method named 'imports' which re-generate selected libraries methods within the controller (in PHP4 it was kind of the 'aggregate_methods' function if people are curious) ; the system works perfectly but CodeIgniter doesn't understand it. The methods can be called within the controller but it seems the framework check the $CI content to call the rules (Form_validation.php line 590 in '/system/') so it doesn't work at the end ; it's also hard to modify this core part, I prefered not touching it and gave up.
$this->load->library('volt/lbl_validation');
$this->imports('Lbl_validation');
// Then you can call any $this->lbl_validation->method() with $this->method() in the controller
I tried to hack CI creating a customized form_validation within my library ('lbl_validation') ; the system was a bit messy but worked. The problem is when i came back to the CI form_validation system to show error messages, it was a true spaghetti-code which wasn't working that well. Not the good solution either.
I also tried some other shitty solutions but i prefer not confess it.
Now i'm here in front of my computer asking myself why bad things happened to good people, why this is so hard to separate set_rules from the called methods in CodeIgniter, why they didn't plan ahead people could've needed to call libraries methods as rules. I don't know what to do and i'm hesitating to put a dumb require() somewhere and make it all dirty and messy like my desk right now.
Maybe, there's someone with a good dans clean solution. All my hope are turned to the StackOverFlow community ; someone ? A crazy CI geek ?
Thank you ;)
The only good, DRY way to handle validation is to put validation rules at the last resort before saving to the the database, in other words in the models. By doing this, the same rules can be used in any controller or library without being redefined.
The following idea is taken from Jamie Rumbelows excellent Codeigniter handbook:
Simply create an array in your model:
$validate = array(
array( 'field' => 'username', 'label' => 'Username', 'rules' => 'required,trim' ),
array( 'field' => 'password', 'label' => 'Password', 'rules' => 'required|min_length[8]' )
);
Then implement a method that you can use to validate your data prior to save()
function validate($data) {
if (!empty($this->validate)) {
foreach ($data as $key => $value) {
$_POST[$key] = $value;
}
$this->load->library('form_validation');
$this->form_validation->set_rules($this->validate);
return $this->form_validation->run();
}
else
{
return TRUE;
}
}
Now, in your controllers you can use:
if ($this->user->validate($user))
save...
I am very newbie about all of these PHP Frameworks. I was once created my own framework by using phpbb's template functions, language support and sessions. I turned them into a Model-View framework. I decided that is too complicated and searched for a new framework.
Right now I am using laravel and its quite well yet I still couldn't figure how to handle controllers and views. Here comes my stuck part.
I was using my phpbb's framework by creating a file.php to root folder and create a .html file styles folder. phpbb's framework can render a html file by calling
$template->set_filenames(array(
'body' => 'file.html'
));
however i can pass every variable to file.html from the controller.php like this :
$template->assign_var('THREAD_ID', $row['id']);
$template->assign_var('THREAD_NAME', $row['title']);
even cycles were too easy
while ($row = $db->sql_fetchrow($result))
{
$template->assign_block_vars('post_row', array
(
'ID' => $row['post_id'],
'COUNT' => $count++,
'USERNAME' => $row['post_username'],
'DATE' => $row['post_datetime'],
'ENTRY' => $row['post_entry'],
)
);
}
and then for rendering the view
$template->set_filenames(array(
'body' => 'file.html'
));
this is what i couldnt understand in laravel.
I am using this but when I using this for another variable it gives me error.
$this->layout->nest('content', 'index', array(
'data' => 'pokeçu'
));
in documents they made examples just for one variable. I dont know how to continue my way.
I'm assuming you're using Laravel 3, as that is the current stable version. There's a section in the Laravel docs covering this. Basically you're going to be using the View class in whatever way suits your app best. Remember, your controller methods (or route closures) will always return something, usually a View instance. To bind data to that view, the simplest method is to use with($data[, $value]) where $data is either an associative key-value array, or $data is a key and $value is the value. For example:
public function get_index()
{
$thread = array('id'=>23, 'name'=>'Skidoo');
return View::make('home.index')->with($thread);
}
Note the return. You don't need to return it right away. You can also instantiate the View object, and bind data to it directly:
public function get_index()
{
$view = View::make('home.index');
$view->thread = array('id'=>23, 'name'=>'Skidoo');
$view->welcome = 'Welcome to My Site!';
return $view;
}
In addition to the docs, there are a couple of recent tutorial books available. Check out the Learn section on the Laravel website at http://laravel.com/
I have site which is managed using CMS entirely developed on zend. Now I have to Implement a search feature too. I'vent done anything related to search in zend. Some suggestions that I received is to implement a spider. The site will have plenty of links(and it will keep on adding). I'm totally confused and I don't know where to start from. Will zend_search_lucene do the trick?
You probably aren't going to find something completely turnkey for this. If your content is all public, and you are fine with just using a crawler, the easiest thing to implement could be Google Site Search.
http://www.google.com/enterprise/search/products_gss.html
If you need to get different functionality out of the search that this wouldn't offer, you'll likely be stuck doing some code. The Zend Lucene link that Alvar posted is good. One of the ugly things about Zend_Lucene, if I am not mistaken, is that it's relying on the text based lucene indexes without any Java. It's just slower and more cumbersome to manage.
A more robust Lucene based approach is Solr. It's Java based, and runs on it's own service with an API. It scales well, and there's a PHP Pecl out now that will help you communicate with it.
See http://php.net/manual/en/book.solr.php
Another option is Sphinx. This search engine bolts directly to your database, so indexing might be a little more intuitive.
http://sphinxsearch.com/
Good luck to you!
Lucene is strange, i never got it to work properly and developed my own search logic, but maybe this helps:
http://devzone.zend.com/397/roll-your-own-search-engine-with-zend_search_lucene/
Because you are using a home grown product you'll likely be better served by keeping things as simple as possible, at least in the beginning. Also because you're product is home grown you should have a pretty good handle on the data structure.
Building a simple query based search may be something appropriate for starters.
I started with a simple search form:
<?php
class Application_Form_Search extends Zend_Form
{
public function init() {
$this->setMethod('POST');
$this->setDecorators(array(
array('ViewScript', array(
'viewScript' => '_searchForm.phtml'
))
));
// create new element
$query = $this->createElement('text', 'query');
// element options
$query->setLabel('Search Keywords');
$query->setAttribs(array('placeholder' => 'Title',
'size' => 27,
));
// add the element to the form
$this->addElement($query);
$submit = $this->createElement('submit', 'search');
$submit->setLabel('Search Site');
$submit->setDecorators(array('ViewHelper'));
$this->addElement($submit);
}
}
then I built a simple action helper to display and route the form:
<?php
class Library_Controller_Action_Helper_Search extends Zend_Controller_Action_Helper_Abstract
{
public function direct($action, $label = null, $placeHolder = null)
{
$form = new Application_Form_Search();
$form->setAction($action);
$form->search->setLabel($label);
$form->query->setAttribs(array('placeholder' => $placeHolder,
'size' => 27,
));
return $form;
}
}
then I added a placeholder for the search form in my layout.phtml
<?php echo $this->layout()->search ?>
then in the controllers that need to use the search function I add the helper to predispatch():
public function preDispatch()
{
//assign search action helper to view placeholder
$this->_helper->layout()->search = $this->_helper->search(
'url_for_action', 'Submit button label', 'placeholder text'
);
}
then I use a simple mapper method to perform the appropriate query and I usually return a paginator adapter:
public function fetchPagedMoviesByTitle($title)
{
$select = $this->getGateway()->select();
$select->where(new Zend_Db_Expr("title LIKE '%$title%'"));
$select->order('title', 'ASC');
//create a new instance of the paginator adapter and return it
$adapter = new Video_Model_Paginator_Video($select);
return $adapter;
}
This is simple way to implement a search function and is adaptable to most types of queries. I find that a switch statment and a couple of simple database queries and almost any information I need is available.
Good Luck.
On my CakePHP site I use a table called portfolio I tell Cake this in the model to get around the automated plural nonsense with the following code:
class Portfolio extends AppModel
{
var $name = 'Portfolio';
var $useTable = 'portfolio';
}
This works fine except when trying to add a new portfolio item as even though the url is fine at /portfolio/add/ the form itself has an action of /portfolios/add/ which breaks the app.
How do I fix this?
it's much better and easier to follow CakePHP conventions
that would save you a lot of time !!
your problem is just an example..
by time, you will face more similar problems !!
i strongly recommend that you follow the conventions of CakePHP
one of them is "use plural names for tables"
Ended up hacking it like so:
echo $this->Form->create(null, array('url' => array('controller' => 'portfolio', 'action' => 'add')));
Really hate how CakePHP adds a dam s to everything!