Avoid creating a view for each AJAX function at CakePHP - cakephp

I am trying to avoid creating a view for each AJAX function I am using at my controller. (as i don't manipulate the resulting data in any way and in most cases is just a boolean value)
I am using RequestHandler component at my controller:
var $components = array('RequestHandler');
And I added this in routes.php
Router::parseExtensions('json');
I am trying to make this function to work, but I am getting a null value:
public function test(){
$this->layout = 'ajax';
$result = '1';
$this->set('_serialize', $result);
}
To access to the json version of the function i use this URL finishing in .json to avoid loading any view:
http://localhost/cakephp/demoController/test.json
I have been following the steps from CakePHP documentation:
http://book.cakephp.org/2.0/en/views/json-and-xml-views.html#json-and-xml-views
What am I doing wrong? Why don't I get the expecting result and instead I get a null?
Also, if I try to to serialize some array, like this one:
$result = array('demo' => '1');
$this->set('_serialize', $result);
I'm getting this notice:
Notice (8): Undefined index: 1 [CORE\Cake\View\JsonView.php, line 89]Code Context $data = array();
foreach ($serialize as $key) {
$data[$key] = $this->viewVars[$key];$view = null
$layout = null
$serialize = array(
'demo' => '1'
)
$data = array()
$key = '1'JsonView::render() - CORE\Cake\View\JsonView.php, line 89
Controller::render() - CORE\Cake\Controller\Controller.php, line 957
Dispatcher::_invoke() - CORE\Cake\Routing\Dispatcher.php, line 193
Dispatcher::dispatch() - CORE\Cake\Routing\Dispatcher.php, line 161
require - APP\webroot\index.php, line 92
[main] - ROOT\index.php, line 42{"1":null}

As far as I understand the documentation you have to specify a view variable and then refer to this variable when you use the _serialize key. This means your snippet would look like:
$result = '1';
$this->set('theResult', $result);
$this->set('_serialize', array('theResult'));

I don't have the .json extension in the URL and the Router::parseExtensions('json'); line in my routes.php file, so the #dhofstet's answer did not work for me.
My solution was to add the renderAs() call:
public $components = array('RequestHandler');
public function my_ajax_action() {
// do something
$result = '1';
$this->set('result', $result);
$this->set('_serialize', array('result'));
$this->RequestHandler->renderAs($this, 'json');
}

You could create an element and render it.
function test() {
$this->autoRender = false;
$result = array('demo' => '1');
$this->set(compact('result'));
$this->set('_serialize', array('result'));
$this->render(DS.'Elements'.DS.'element_name');
}
See docs

The simplest way is this. Works well for me.
public function fun() {
$this->autoRender = false;
$this->request->onlyAllow('ajax');
$result = array('data1' => 'hello', 'data2' => 'world');
return json_encode($result);
}

Related

Return doctrine object to array/json by findall() -gives an error - of on object

I am getting an error on line 10 :
Call to a member function getUserId() on a non-object in
/** #var $users User*/
$users= $this->getRepository("repo")->findAll();
$response = array();
foreach ($users $user) {
$response[] = array(
**line10 'user_id' => $user->getUserId()
);
}
basicly in line 10 it did not recognize the call to getUserId
so how could I fetch the data to array or json ?
thanks
Inside your loop on $campaigns, one of the elements of the array seem to be null, so this element does not have the method getUserId. Try to var_dump your $campaigns array to check its content, I'm pretty sure you would be able to find the mistake after that.
Try: $campaigns = $this->getDoctrine->getRepository("repo")->findAll();
Looks like $campaigns have no results, try:
if($capaigns) {
foreach ($campaigns as $user) {
$response[] = array('user_id' => $user->getUserId());
}
}

CakePHP: finding data after save

I'm working on an edit method. After saving data, an email is sent out with the changes made during the edit. Everything works except for one infuriating but crucial bug. Here it is distilled down very simply:
$data = $this->SupportTicket->readForView($st_id);
$this->SupportTicket->id = $st_id;
if ($this->SupportTicket->save($this->request->data)) {
//call custom model method to pull view data
$data = $this->SupportTicket->readForView($st_id);
//do something with this data
}
The issue is that $data comes out with the pre-save data. So what I then try to do with the new data doesn't work.
I can't just use $this->request->data because it doesn't have the full data that I want in it.
The save does however work. If I refresh the view method for the same record, it shows as updated. So it's saving, but when I do the find after saving it is giving me old data.
Any ideas?
Update: it doesn't happen with findById($st_id) so it must be something to do with my custom method. Code:
public function readForView($id)
{
$data = $this->find('first', array(
'conditions' => array(
'SupportTicket.id' => $id
),
'contain' => array(
'User',
'Owner'
)
));
if (empty($data)) {
throw new notFoundException('Ticket not found');
}
$data['SupportTicket']['type_long'] = $this->getLongType($data['SupportTicket']['type']);
$data['SupportTicket']['status_long'] = $this->getLongStatus($data['SupportTicket']['status']);
$data['SupportTicket']['name'] = 'Support Ticket #' . $data['SupportTicket']['id'] . ' - ' . $data['SupportTicket']['title'];
return $data;
}
Copying the code from this method into the Controller gives the same result.
I've found this helpful: https://edivad.wordpress.com/2008/04/15/cakephp-disable-model-queries-caching/
By model:
class Project extends AppModel {
var $cacheQueries = false;
...
By function:
function someFunction {
$this->Model->cacheQueries = false;
...
try using last Insert ID
$id=$this->getLastInsertID();
public function readForView($id)

Codeigniter URI Not Working - 404 Error

I have searched around for examples but i am getting an odd result
i wish to have the following occur /pages/1 URL to return from the database the markup column of row 1 of the pages table.
controller
public function index()
{
$id = $this->uri->segment(2);
$content = $this->page->specificMarkup($id);
$this->template->set('nav', 'support');
$this->template->set('content', $content);
$this->template->load('master', 'contact');
}
model
public function specificMarkup($id)
{
$query = $this->db->get_where('pages', $id);
$row = $query->row();
return $row->markup;
}
it works when i specifically set the $id, but now returns a 404 error when i try to use segments, the user guide gives me the impression that this should work.
I will answer my own question for others that run into this issue.
1.
the model needs to be
public function specificMarkup($id)
{
$query = $this->db->get_where('pages', array('id' => $id));
$row = $query->row();
return $row->markup;
}
2.
Their does need to be an entry in the routes.php
$route[ 'pages/(:num)' ] = 'pages/index/$1'
This is so codeigniter knows where to direct the traffic

How do I use Model in Helper - CakePHP 2.x

I recently upgraded my app from cake 1.3.x to cake 2.x. Now I have a helper which uses model in some function. Initially syntax for loading model was (working for 1.3.x)
App::import('Model', $modelName);
$modelObject = &ClassRegistry::getObject($modelName);
$modelObject->find()
Now I changed it to following
App::uses($modelName,'Model');
$modelObject = &ClassRegistry::getObject($modelName);
$modelObject->find()
Problem is, this conversion is not working. Can anybody tell me where am I doing wrong. Thanking in advance.
PS:
Error message is:
Call to a member function find() on a non-object
working code should be
//let $modelName be User
App::import("Model", "User");
$model = new User();
$model->find("list");
I hope this will help some needy fellow
You can also load model in helper, add following method in helper class:
Step1:
public function loadModel($modelClass = null, $id = null) {
if ($modelClass === null) {
$modelClass = $this->modelClass;
}
$this->uses = ($this->uses) ? (array) $this->uses : array();
if (!in_array($modelClass, $this->uses, true)) {
$this->uses[] = $modelClass;
}
list($plugin, $modelClass) = pluginSplit($modelClass, true);
$this->{$modelClass} = ClassRegistry::init(array(
'class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id
));
if (!$this->{$modelClass}) {
throw new MissingModelException($modelClass);
}
return true;
}
Step2: call above method as you do in controller like this:
$this->loadModel(ModelName);
I hope this would resolve problem
I wanna go through helper to view data In the form of foreach
public function display()
{
$links = TableRegistry::getTableLocator()->get('category');
$category = $links->find('all')
->where(['status' => 1, 'position' => 0])
->select([
"category" => 'parent', 'name'
])
->toArray();
return $category['category'];
}

cake php link to the current page with different prefix

In my default layout I would like to show link which points to the current page but with different prefix. I am using prefix 'language' to use address like www.site.com/eng/controller/action/param.
I tried $this->Html->link('eng', array('language' => 'eng') );
But this creates link with url eng/controller/action without passed arguments, without named arguments and without url params.
How I can do this? I would prefer elegant solution like 1 line of code - I know it can be done but can't find it :(.
Try this:
// helper method, possibly AppHelper, or in AppController and set a view var
function getCurrentParams() {
$route = Router::currentRoute();
$params = $this->request->params;
$pass = $params['pass'];
$named = $params['named'];
unset($params['pass'], $params['named']);
if (!empty($route->options['pass'])) {
$pass = array();
}
return array_merge($params, $named, $pass);
}
$params = $this->SomeHelper->getCurrentParams();
$params['language'] = 'eng';
// use $params for your link now
in my case this easy solution worked too!
<?php
App::uses('HtmlHelper', 'View/Helper');
class MyHtmlHelper extends HtmlHelper {
public function url($url = null, $full = false) {
if(!isset($url['language']) && isset($this->params['language']) && is_array($url)) {
$url['language']= $this->params['language'];
}
if(count($url) == 1 && isset($url['language'])){
$params = $this->params;
$url = array_merge($params['pass'],$url);
}
return parent::url($url, $full);
}
}
and in AppController
public $helpers = array(
...
'Html' => array('className' => 'MyHtml')
...
);
$this->Html->link('eng', array('language' => 'eng', 'pass') );
Something like this should work:
$url = Router::parse($this->here);
$url['language'='end';
$this->Html->link('eng', $url);
It's not one line, but you could compress it into one line but it would be pretty unreadable.
You could wrap it in a helper / function which would be a one line call though ;-)

Resources