CakePHP Controller Method Variables - cakephp

I am trying to define a variable that will pass into the Action of a Controller as follows
public function index($branch = null) {
//padmanabha-nagar
//jp-nagar
$branch = "padmanabha-nagar";
$this->loadModel('Branch');
// Check if the Branch is valid
if(!empty($branch)){
$this->Branch->recursive = -1;
$branch_result = $this->Branch->find('first', array('order' => array('Branch.name ASC'), 'conditions' => array('Branch.slug' => $branch)));
//debug($branch_result);
// Fetch the Branch ID
if(!empty($branch_result)){
$branch_id = $branch_result['Branch']['id'];
} else {
return $this->redirect(array('controller' => 'pages', 'action' => 'home'));
}
// Fetch the Gallery Images
$this->Gallery->recursive = -1;
$this->Paginator->settings = $this->paginate;
$galleries = $this->Gallery->find('all', array('conditions' => array('Gallery.branch_id' => $branch_id)));
//debug($galleries);
}
$this->set(compact('galleries', 'branch_result'));
}
But when i try to access $branch it does not seem to be set. Is there any other configuration i need to do so that i can get the content?

You are over writing the input variable
public function index($branch = null) {
//padmanabha-nagar
//jp-nagar
$branch = "padmanabha-nagar"; <= you are over writing the input variable
...
You could do this
$branch = !empty($branch)?$branch:"padmanabha-nagar";

Try to add branch to this line as follows:
$this->set(compact('galleries', 'branch_result', 'branch'));

You can create a variable to class using
$branches = null;
instead of to action, then use the variable using
$this->branches

Related

custom datasource find('list') issue

I am creating a custom datasource and I am having problems when i request find('list'). find('all') returns perfectly what I want within my controller but find('list') just returns an empty array.
The funny thing is if I do a die(Debug($results)) in the datasource within the read function then I get my find('list') array correctly but if I return it i then get an empty array in my controller. Any ideas?
Code below:
public function read(Model $model, $queryData = array(), $recursive = null) {
if ($queryData['fields'] == 'COUNT') {
return array(array(array('count' => 1)));
}
$this->modelAlias = $model->alias;
$this->suffix = str_replace('Flexipay', '', $model->alias);
if(empty($model->id)){
$this->url = sprintf('%s%s%s', $this->sourceUrl, 'getAll', Inflector::pluralize($this->suffix));
}
$r = $this->Http->get($this->url, $this->config);
if($r->isOk()){
$results_src = json_decode($r->body, true);
if(is_array($results_src)){
//$this->find('list');
if($model->findQueryType == 'list'){
return $this->findList($queryData, $recursive, $results_src);
}
//$this->find('all');
foreach($results_src['PortalMandantenResponses']['portalMandantenResponses'] as $r){
$results[] = $r;
}
if(!empty($results)){
$e = array($model->alias => $results);
return $e;
}
}
}else{
//
}
return false;
}
My response from die(debug(array($model->alias => $results);
(int) 0 => array(
'Mandant' => array(
'ns2.id' => (int) 79129,
'ns2.name' => 'company a'
)
),
(int) 1 => array(
'Mandant' => array(
'ns2.id' => (int) 70000,
'ns2.name' => 'company b'
)
),
Controller Code is here:
public function test2(){
//$a = $this->User->find('list');
//die(debug($a));
$this->loadModel('Pay.Mandant');
$a = $this->Mandant->find('list', array('fields' => array('ns2.systembenutzernr', 'ns2.systembenutzernrBezeichnung')));
die(debug($a));
}
use,
$a = $this->Mandant->find('list', array('fields' => array('ns2.systembenutzernr', 'ns2.systembenutzernrBezeichnung')));
$this->set(compact('a'));
You can use $a for the dropdown creation in view file.
I just had the same problem writing my custom model though I don't know if the cause in your case is the same, though you should probably look in the same place.
in Model.php there is a function _findList($state, $query, $results), my issue was the fields you specify in the find() call must match the $results structure exactly, otherwise at the end of the _findList() function the call to:
Hash::combine($results, $query['list']['keyPath'], $query['list']['valuePath'], $query['list']['groupPath'])
returns the empty array. The keyPath of {n}.MODELNAME.id, etc must match the name of the model specified in $results, for example
[0] => ['MODELNAME'] = array()
[1] => ['MODELNAME'] = array()
In my case my keyPath and valuePath had a different value for MODELNAME than in the results array
Hope that helps

How Cake PHP pass parameters from one controller action to another view

I have a search method in my WorkersController.php like following:
public function search() {
$conditions = array();
if(!empty($this->request->data)){
foreach($this->request->data['Search'] as $field => $search_condition ) {
if(!empty($search_condition))
$conditions["$field LIKE "] = "%$search_condition%";
}
}
if(!empty($conditions)){
$this->Worker->recursive = 0;
$workers = $this->Worker->find('all',array('conditions' => $conditions));
}
$this->redirect(array('action' => 'index','search' ));
}
IN the method I call redirect(), then the page goes to index.ctp, where I want to fetch $workers like this:
if($this->request->params['pass']==array('search')){
if (empty($workers)){
echo('No result found!');
}else{
foreach ($workers as $worker){
//do something
}
}
}
But I just can't fetch $workers, how can I pass it from search() to index.ctp?
Thanks a lot!
You could try and use Session for this case.
//in controller1
$this->Session->write('worker', $workers);
//in controller2
$workersData = $this->Session->read('worker');
yes you can use as per below syntax to
$this->redirect(array('controller' => 'workers', 'action' => 'index', 'pass' => 'param', 'pass1' => 'param1'));
for more detail you can use doc

Drupal 7 - Module block with custom template not rendering

I can't seem to get my custom block within my module to render the template file I created. Here is my code:
<?php
include_once 'e_most_popular.features.inc'; //this is from features module
function e_most_popular_block_info() {
$blocks['e_most_popular'] = array(
'info' => t('e_most_popular block TITLE'),
'cache' => DRUPAL_NO_CACHE, //there are a number of caching options for this
);
return $blocks;
}
function e_most_popular_block_view($delta = ''){
switch($delta){
case 'e_most_popular':
if(user_access('access content')){ //good idea to check user perms here
$block['subject'] = t('MYblock_TITLE');
$block['content'] = e_most_popular_block_function_items();
}
break;
}
}
function e_most_popular_block_function_items(){
$items = array();
$items['VAR_ONE'] = array('#markup' => 'VAR_ONE_OUTPUT'); //this is the simplest kind of render array
$items['VAR_TWO'] = array(
'#prefix' => '<div>',
'#markup' => 'VAR_TWO_OUTPUT',
'#suffix' => '</div>',
);
//this is where the $items get sent to your default e_most_popular_block.tpl.php that gets //registered below
return theme('e_most_popular_block_function_items', array('items' => $items));
}
//here you are registering your default tpl for the above block
function e_most_popular_theme() {
$module_path = drupal_get_path('module', 'e_most_popular');
$base = array(
'path' => "$module_path/theme", );
return array(
'e_most_popular_block_function_items' => $base + array(
'template' => 'e_most_popular_block',
'variables' => array('items' => NULL,),
),
);
}
I have confirmed that it does read the template file, since it will error if not named correctly, and I have enabled the and module assigned the block to the sidebar in the block menu. I also clear the cache after making changes. I still get no output. Here is the template file:
Template file Test
<?php
$items = $variables['items'];
print render($items['VAR_ONE']);
Any idea what I am doing incorrectly?
As I mentioned in my comment, the issue is that you are not returning the $block variable in your hook_block_view. That is why nothing is being output.
Check out the documentation for hook_block_view.
Your hook_block_view should be like the following:
function e_most_popular_block_view($delta = ''){
$block = array();
switch($delta){
case 'e_most_popular':
if(user_access('access content')){ //good idea to check user perms here
$block['subject'] = t('MYblock_TITLE');
$block['content'] = e_most_popular_block_function_items();
}
break;
}
return $block;
}

passing data to view 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();
);

CakePHP - how to apply translate behavior to existing database?

I have and existing application in CakePHP with a database.
The task is to apply translate behavior to its models. The problem is that i18n.php script just creates _i18n table but doesn't copy existing data to this table.
Don't you know any script that could do that?
Thanks for any help.
I extended the answers from Aziz and MarcoB and created a even more generic CakeShell out of it.
In the method _execute() simply set something like:
$this->_regenerateI18n('BlogPosts', array('title'), 'deu');
And all entries for the Model BlogPosts for the column title in the language deu will be create in the i18n table.
This is CakePHP 2.4 compatible!
<?php
class SetuptranslationsShell extends AppShell {
public function main() {
$selection = $this->in('Start to create translated entries?', array('y', 'n', 'q'), 'y');
if (strtolower($selection) === 'y') {
$this->out('Creating entries in i18n table...');
$this->_execute();
}
}
function _execute() {
$this->_regenerateI18n('BlogPosts', array('title'), 'deu');
$this->_regenerateI18n('BlogTags', array('name'), 'deu');
}
/**
* See http://stackoverflow.com/q/2024407/22470
*
*/
function _regenerateI18n($Model, $fields = array(), $targetLocale) {
$this->out('Create entries for "'.$Model.'":');
if (!isset($this->$Model)) {
$this->{$Model} = ClassRegistry::init($Model);
}
$this->{$Model}->Behaviors->disable('Translate');
$out = $this->{$Model}->find('all', array(
'recursive' => -1,
'order' => $this->{$Model}->primaryKey,
'fields' => array_merge(array($this->{$Model}->primaryKey), $fields))
);
$this->I18nModel = ClassRegistry::init('I18nModel');
$t = 0;
foreach ($out as $v) {
foreach ($fields as $field) {
$data = array(
'locale' => $targetLocale,
'model' => $this->{$Model}->name,
'foreign_key' => $v[$Model][$this->{$Model}->primaryKey],
'field' => $field,
'content' => $v[$Model][$field],
);
$check_data = $data;
unset($check_data['content']);
if (!$this->I18nModel->find('first', array('conditions' => $check_data))) {
if ($this->I18nModel->create($data) AND $this->I18nModel->save($data)) {
echo '.';
$t++;
}
}
}
}
$this->out($t." entries written");
}
}
As far as I know, there's no way to do this. Moreover, because of the way the i18n table is configured to work, I think there's a better solution. A while back, I wrote a patch for the TranslateBehavior that will keep you from having to copy existing data into the i18n table (that felt insanely redundant to me and was a huge barrier to implementing i18n). If no record for that model exists in the i18n table, it will simply read the model record itself as a fallback.
Unfortunately, the Cake team appears to have moved everything to new systems, so I can no longer find either the ticket or the patch that I submitted. My patched copy of the TranslateBehavior is in my Codaset repository at http://codaset.com/robwilkerson/scratchpad/source/master/blob/cakephp/behaviors/translatable.php.
As you might expect, all of the usual warnings apply. The patched file was developed for 1.2.x and works for my needs, by YMMV.
try to use it
function regenerate()
{
$this->Article->Behaviors->disable('Translate');
$out = $this->Article->find('all', array('recursive'=>-1, 'order'=>'id'));
$t = $b = 0;
foreach($out as $v){
$title['locale'] = 'aze';
$title['model'] = 'Article';
$title['foreign_key'] = $v['Article']['id'];
$title['field'] = 'title';
$title['content'] = $v['Article']['title'];
if($this->Article->I18n->create($title) && $this->Article->I18n->save($title)){
$t++;
}
$body['locale'] = 'aze';
$body['model'] = 'Article';
$body['foreign_key'] = $v['Article']['id'];
$body['field'] = 'body';
$body['content'] = $v['Article']['body'];
if($this->Article->I18n->create($body) && $this->Article->I18n->save($body)){
$b++;
}
}
}
Thanks Aziz. I modified your code to use it within the cakeshell
(CakePHP 2.3.8)
function execute() {
$this->out('CORE_PATH: '. CORE_PATH. "\n");
$this->out('CAKEPHP_SHELL: '. CAKEPHP_SHELL. "\n");
$this->out('Migrate BlogPosts');
$this->regenerateI18n('BlogPost', 'title', 'BlogPostI18n');
}
/**
* #param string $Model
* #param string $Field
* #param string $ModelI18n
*/
function regenerateI18n($Model = null, $Field = null, $ModelI18n = null)
{
if(!isset($this->$Model))
$this->$Model = ClassRegistry::init($Model);
if(!isset($this->$ModelI18n))
$this->$ModelI18n = ClassRegistry::init($ModelI18n);
$this->$Model->Behaviors->disable('Translate');
$out = $this->$Model->find('all', array('recursive'=>-1, 'order'=>'id'));
$t = 0;
foreach($out as $v){
$data = array(
'locale' => 'deu',
'model' => $this->$Model->name,
'foreign_key' => $v[$Model]['id'],
'field' => $Field,
'content' => $v[$Model][$Field],
);
if($this->$ModelI18n->create($data) && $this->$ModelI18n->save($data)){
echo '.';
$t++;
}
}
$this->out($t." Entries written");
}

Resources