passing data to view CakePHP - cakephp

This might be easy, but I have tried a few ideas but no solution at all, I'm no expert with cakePhp but I'm trying to modify a existing project with limited time.
The problem is that I have a entity called 'centro' but I'm using its model on a different controller, 'rw', but I can't get it to pass that data to the view at all; it seems it's because the variable gets erased when I use a redirect to go back to the 'index'.
I need that data to generate a google map, the method $this->set(.....) is not working.
Here's the code of the 'rw' controller.
<?php
class RwController extends AppController {
var $name = 'Rw';
// var $paginate = array(
// 'Tip' => array(
// 'limit' => 1,
// 'order' => array(
// 'tip.created' => 'desc'
// ),
// ),
// 'Evento' => array(
// 'limit' => 1,
// 'order' => array(
// 'evento.fecha' => 'desc'
// ),
// )
// );
function map() {
$this->helpers[]='GoogleMapV3';
}
function pageForPagination($model) {
$page = 1;
// $chars = preg_split('/model:/', $this->params['url']['url'], -1, PREG_SPLIT_OFFSET_CAPTURE);
// #print_r($chars);
// if(sizeof($chars) > 1 && sizeof($chars) < 3) {
// #echo "Belongs to ".$model.": \n";
// #echo var_dump($chars);
// }
// $params = Dispatcher::parseParams(Dispatcher::uri());
// echo "<p>".var_dump($params)."</p><br />";
#echo $this->params['named']['model'].$model;
#echo $this->params['named']['page'];
$sameModel = isset($this->params['named']['model']) && $this->params['named']['model'] == $model;
$pageInUrl = isset($this->params['named']['page']);
if ($sameModel && $pageInUrl) {
$page = $this->params['named']['page'];
} else {
#echo var_dump($this->passedArgs);
}
$this->passedArgs['page'] = $page;
return $page;
}
function index() {
$this->loadModel('User');
$this->loadModel('Evento');
$this->loadModel('Tip');
$dataEvento = $this->Evento->find('all');
$dataTip = $this->Tip->find('all');
$page = $this->pageForPagination('Evento');
$this->paginate['Evento'] = array(
'contain' => false,
'order' => array('Evento.fecha' => 'desc'),
'limit' => 1,
'page' => $page
);
$dataEvento = $this->paginate('Evento');
$page = $this->pageForPagination('Tip');
$this->paginate['Tip'] = array(
'contain' => false,
'order' => array('Tip.created' => 'desc'),
'limit' => 1,
'page' => $page
);
$dataTip = $this->paginate('Tip');
$this->set('users', $this->User->find('all'));
$this->set('eventos', $dataEvento);
$this->set('tips', $dataTip);
$this->set('rw');
if(isset($this->params['named']['model'])) {
if (strcmp($this->params['named']['model'], 'Evento') == 0) {
if($this->RequestHandler->isAjax()) {
$this->render('/elements/ajax_rw_evento_paginate');
return;
}
} elseif (strcmp($this->params['named']['model'], 'Tip') == 0) {
if($this->RequestHandler->isAjax()) {
$this->render('/elements/ajax_rw_tip_paginate');
return;
}
}
}
}
function about($id = null) {
$this->Rw->recursive = 0;
$this->set('rw', $this->paginate());
}
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow(array('*'));
}
function getCentros($id = null ){
$this->loadModel('Centro');
$this->log('getcentros','debug');
$this->log('el id'.$id,'debug');
if( sizeof($id) > 1){
$this->set('centros', $this->Centro->query("SELECT centros.id, name, latitud ,longitud
FROM `centros`,`centrosmateriales`
WHERE centros.id = centro_id
AND material_id ='".$id[0]."'
OR material_id='".$id[1]."'"));
$this->log('size id > 1 ','debug');
}elseif( sizeof($id) >0) {
if($id == 0){
$this->set('centros', $this->Centro->find('all'));
}else{
$this->set('centros', $this->Centro->query("SELECT centros.id, name, latitud ,longitud
FROM `centros`,`centrosmateriales`
WHERE centros.id = centro_id
AND material_id ='".$id[0]."'"));
}
}
$this->Session->write('saludos', 'Saludando');
$this->redirect(array('action' => 'index'));
}
}
?>
I have been thinking about ajax but I'm not sure.
Anyways, thanks in advance.

Using redirect() sends an actual HTTP redirect to the browser. This causes the browser to send another request to the server, to the URL it has been redirected to.
The data that you pass to set() is only available within that single CakePHP request cycle. All PHP data is wiped from memory afterwards. The only way to pass data to the next request is in the URL or in the session.
In your case you should rethink your design and set() all data you need in the index() action. You could possibly move the logic from getCentros() into your Centro model. Then, in your index() function, you could just do
$this->set(
'centro',
$this->Centro->getCentros();
);

Related

unable get data from database cakephp

i want get data from database and calculate the average Rating but when i get data by author id i have message find() is null
this my function
public function teacher_average_rating_in_school()
{
$this->autoRender = false;
if($this->request->is('get'))
{
$author_id = $this->request->query('author_id');//
$rate = $this->UserRating->find('all',array('conditions'=>array('author_id'=> $author_id), 'fields'=> array('AVG(UserRating.rstings) as averageRating'), 'recursive' =>-1));
$average = $rate[0][0]['averageRating'];
$result = array('success'=>'1' , 'average' => $average );
}
else{
$result = array('success'=>'0','message'=>'request type is not GET');
}
echo json_encode($result);
}
and this my model
class UserRating extends AppModel {
public $validate = array(
'user_id' => array('rule' => 'notBlank'), 'author_id' => array( 'rule' => 'notBlank') , array('rstings' => 'notBlank' ));
}
why i get find()is null , and how can i solve that ?
Have you load the Modal??
public function teacher_average_rating_in_school()
{
$this->autoRender = false;
if($this->request->is('get'))
{
$this->loadModel('UserRating');
$author_id = $this->request->query('author_id');//
$rate = $this->UserRating->find('all',array('conditions'=>array('author_id'=> $author_id), 'fields'=> array('AVG(UserRating.rstings) as averageRating'), 'recursive' =>-1));
$average = $rate[0][0]['averageRating'];
$result = array('success'=>'1' , 'average' => $average );
}
else{
$result = array('success'=>'0','message'=>'request type is not GET');
}
echo json_encode($result);
}
If you have already loadModel using then check sql_dump.
You can use as follows
//inside controller action
debug($this->UserRating->lastQuery());
//Or inside layout call this
<?php echo $this->element('sql_dump'); ?>

hook_block_view not passing information

I am trying to build my first custom module in Drupal 7. It is a block form for the user to search a DB table for customer information. I've created both the module and info files. My module appears under the modules and blocks section, but when I add the block to Content, the subject and content aren't being passed from my hook_block_view. So, instead of the form being displayed, it just shows the block title and body. Can someone tell me what I'm missing?
<?php
/**
*#file
*
*/
/** Implements hook_block_info().
*
*/
function searchEngine_block_info(){
$blocks = array();
$blocks['searchEngine_form'] = array (
'info' => t("Applicant Search"),
'cache' => DRUPAL_CACHE_GLOBAL,
);
return $blocks;
}
/** Implements hook_block_view().
*
*/
function searchEngine_block_view($delta = ''){
$block = array();
switch($delta) {
case 'searchEngine_form':
$block['subject'] = t('Applicant Search');
$block['content'] = drupal_get_form('searchEngine_form');
break;
}
return $block;
}
function searchEngine_form($form, &$form_state) {
$form['searchOptions'] = array(
'#type' => 'select',
'#title' => t("Select how you would like to search for an applicant."),
'#default_value'=> variable_get("gwf", true),
'#options' => array(
'gwf' => "GWF".t(" Number"),
'email' => t("Email"),
'name' => t("Name"),
'phone_number' => t("Phone Number"),
),
);
$form['data'] = array(
'#type' => 'textfeild',
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
function searchEngine_submit($form, $form_state) {
if(isset($form['data'])){
if($form['searchOptions'] == "name"){
$name = preg_split("/[\s,]+/", $form['data']);
$result = db_query('SELECT * FROM tls_active_applicants WHERE first_name = '.$name['0'].' AND last_name = '.$name['1']);
}else{
$result = db_query('SELECT * FROM tls_active_applicants WHERE '.$form['searchOptions'].' = '.$form['data']);
}
print_r($result);
}
}
Passing a renderable array here is fine:
$block['content'] = drupal_get_form('searchEngine_form');
I've just tested your code and the form appears fine for me:
Now we know the code works it makes me wonder if it is just some css or something hiding it?
I would also install the devel module as it will help with debugging.
The you could use this code:
function searchEngine_block_view($delta = ''){
$block = array();
switch($delta) {
case 'searchEngine_form':
$block['subject'] = t('Applicant Search');
$form = drupal_get_form('test_form');
dpm($form); // call to dpm here to log if you are successfully getting the form at this point
$block['content'] = $form;
break;
}
return $block;
}

How to send data to custom block content

I'm trying to create a module that will display some last entries from database. I'd like to send last entry object to template file (guestbook-last-entries.tpl.php), that looks like that
<p><?php render($title); ?></p>
<?php echo $message; ?>
I have a function that implements hook_theme
function guestbook_theme() {
return array(
'guestbook_last_entries' => array(
'variables' => array(
'entries' => NULL,
),
'template' => 'guestbook-last-entries'
),
);
}
one that do preprocess
function template_preprocess_guestbook_last_entries(&$variables) {
$variables = array_merge((array) $variables['entries'], $variables);
}
and functions that implements hook_block_view
function guestbook_block_view($delta = '') {
switch ($delta) {
case 'guestbook_last_entries':
$block['subject'] = t('Last entries');
$block['content'] = array();
$entries = guestbook_get_last_entries(variable_get('guestbook_m', 3));
foreach ($entries as $entry) {
$block['content'] += array(
'#theme' => 'guestbook_last_entries',
'#entries' => $entry,
);
}
break;
}
return $block;
}
function that gets data from database
function guestbook_get_last_entries($limit = 3) {
$result = db_select('guestbook', 'g')
->fields('g')
->orderBy('posted', 'DESC')
->range(0, $limit)
->execute();
return $result->fetchAllAssoc('gid');
}
But in this case I get only one entry displayed. Can anyone tell me how to resolve this, how should I build that $block['content']?
Thank you
This here wont work:
$block['content'] += array(
'#theme' => 'guestbook_last_entries',
'#entries' => $entry,
);
Maybe you want this if you need an array as the result:
// note that I replaced += with a simple = and added two brackets that will create a new element in that array $block['content']
$block['content'][] = array(
'#theme' => 'guestbook_last_entries',
'#entries' => $entry,
);

CakePHP Pagination: how can I sort by multiple columns to achieve "sticky" functionality?

I see that this paginate can't sort two columns at the same time ticket is still open, which leads me to believe that what I'm trying to do is not possible without a workaround. So I guess what I'm looking for is a workaround.
I'm trying to do what many message boards do: have a "sticky" function. I'd like to make it so that no matter which table header link the user clicks on to sort, my model's "sticky" field is always the first thing sorted, followed by whatever column the user clicked on. I know that you can set $this->paginate['Model']['order'] to whatever you want, so you could hack it to put the "sticky" field first and the user's chosen column second. The problem with this method is that pagination doesn't behave properly after you do it. The table header links don't work right and switching pages doesn't work right either. Is there some other workaround?
User ten1 on the CakePHP IRC channel helped me find the solution. I told him that if he posted the answer here then I would mark it as the correct one, but he said I should do it myself since he doesn't have a Stack Overflow account yet.
The trick is to inject the "sticky" field into the query's "order" setting using the model's "beforeFind" callback method, like this:
public function beforeFind($queryData) {
$sticky = array('Model.sticky' => 'DESC');
if (is_array($queryData['order'][0])) {
$queryData['order'][0] = $sticky + $queryData['order'][0];
}
else {
$queryData['order'][0] = $sticky;
}
return $queryData;
}
What you can do is code it in the action. Just create the query you want when some parameters exist on the URL. (parameters has to be sent by GET)
For example:
public function posts(){
$optional= array();
if(!empty($this->params->query['status'])){
if(strlower($this->params->query['status']=='des')){
$optional= array('Post.status DESC');
}
else if(strlower($this->params->query['status']=='asc')){
$optional= array('Post.status ASC');
}
}
if(!empty($this->params->query['department'])){
//same...
}
//order first by the sticky field and then by the optional parameters.
$order = array('Post.stickyField DESC') + $optional;
$this->paginate = array(
'conditions' => $conditions,
'order' => $order,
'paramType' => 'querystring',
);
$this->set('posts', $this->paginate('Post'));
}
I have used something similar to filter some data using $conditions instead of $order and it works well.
You can use custom field for sorting and update pagination component.
Controller code
$order['Document.DATE'] = 'asc';
$this->paginate = array(
"conditions"=> $conditions ,
"order" => $order ,
"limit" => 10,
**"sortcustom" => array('field' =>'Document.DATE' , 'direction' =>'desc'),**
);
Changes in pagination component.
public function validateSort($object, $options, $whitelist = array()) {
if (isset($options['sort'])) {
$direction = null;
if (isset($options['direction'])) {
$direction = strtolower($options['direction']);
}
if ($direction != 'asc' && $direction != 'desc') {
$direction = 'asc';
}
$options['order'] = array($options['sort'] => $direction);
}
if (!empty($whitelist) && isset($options['order']) && is_array($options['order'])) {
$field = key($options['order']);
if (!in_array($field, $whitelist)) {
$options['order'] = null;
}
}
if (!empty($options['order']) && is_array($options['order'])) {
$order = array();
foreach ($options['order'] as $key => $value) {
$field = $key;
$alias = $object->alias;
if (strpos($key, '.') !== false) {
list($alias, $field) = explode('.', $key);
}
if ($object->hasField($field)) {
$order[$alias . '.' . $field] = $value;
} elseif ($object->hasField($key, true)) {
$order[$field] = $value;
} elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field, true)) {
$order[$alias . '.' . $field] = $value;
}
}
**if(count($options['sortcustom']) > 0 )
{
$order[$options['sortcustom']['field']] = $options['sortcustom']['direction'];
}**
$options['order'] = $order;
}
return $options;
}
Easy insert 'paramType' => 'querystring',
Show Code Example:
$this->paginate = array(
'conditions' => $conditions,
'order' => array(
'Post.name' => 'ASC',
'Post.created' => 'DESC',
),
'paramType' => 'querystring',
);
$this->set('posts', $this->paginate('Post'));

the rss helper doesnt generate the index.rss

i have an issue trying to generate rss. I followed all the steps of http://book.cakephp.org/1.3/en/view/1460/RSS, but when i try in the url my index.rss shows me only my index page not in xml format.
this is my index of post_Controller:
var $components = array('Session','RequestHandler');
var $helpers = array('Html','Form','Time','Text');
function index() {
if( $this->RequestHandler->isRss() ){
$posts = $this->Post->find('all', array('limit' => 20, 'order' => 'Post.created DESC'));
$this->set(compact('posts'));
}
$this->set('title_for_layout', 'mi blog');
$this->Post->recursive = 1;
$this->set('posts', $this->paginate());
}
this is my layout in app/views/layouts/rss/default.ctp:
echo $this->Rss->header();
if (!isset($documentData)) {
$documentData = array();
}
if (!isset($channelData)) {
$channelData = array();
}
if (!isset($channelData['title'])) {
$channelData['title'] = $title_for_layout;
}
$channel = $this->Rss->channel(array(), $channelData, $content_for_layout);
echo $this->Rss->document($documentData,$channel);
this the view in app/views/posts/rss/index.ctp
$this->set('documentData', array(
'xmlns:dc' => 'http://purl.org/dc/elements/1.1/'));
$this->set('channelData', array(
'title' => __("Articles", true),
'link' => $this->Html->url('/', true),
'description' => __("Articulos mas recientes.", true),
'language' => 'en-us'));
// content
foreach ($posts as $post) {
$postTime = strtotime($post['Post']['created']);
$postLink = array(
'controller' => 'posts',
'action' => 'view',
$post['Post']['id']);
// You should import Sanitize
App::import('Sanitize');
// This is the part where we clean the body text for output as the description
// of the rss item, this needs to have only text to make sure the feed validates
$bodyText = preg_replace('=\(.*?\)=is', '', $post['Post']['body']);
$bodyText = $this->Text->stripLinks($bodyText);
$bodyText = Sanitize::stripAll($bodyText);
$bodyText = $this->Text->truncate($bodyText, 400, array(
'ending' => '...',
'exact' => true,
'html' => true,
));
echo $this->Rss->item(array(), array(
'title' => $post['Post']['title'],
'link' => $postLink,
'guid' => array('url' => $postLink, 'isPermaLink' => 'true'),
'description' => $bodyText,
'pubDate' => $post['Post']['created']));
}
which could be the problem ... Also i have put the component in the app_controller.php
var $components = array ('Auth', 'Session', 'RequestHandler');
but nothing happens the index.rss is the Same of posts / index
It looks like you are not returning the RSS view in the index controller. Update the RSS section of the index function to return the rss view:
function index() {
if( $this->RequestHandler->isRss() ){
$posts = $this->Post->find('all', array('limit' => 20, 'order' => 'Post.created DESC'));
return $this->set(compact('posts'));
}
// ...snip...
}
UPDATE
It's how Chrome handles the layout. I know it is horrible. FireFox and IE handle RSS layout much better. But you can install the RSS Layout extension for Chrome and it will format it the same way.
https://chrome.google.com/extensions/detail/nlbjncdgjeocebhnmkbbbdekmmmcbfjd
In the action of the controller. You must add
$this->response->type("xml");
at the end.

Resources