cakephp: how to display associated records of associated records - cakephp

My objective is to display records for a related child model (once removed) in the view. I understand that setting the recursive value to '1' returns the current model, its owner(s), plus their associated models.
What I don't know how to do is display this in the view.
My approach has been to create a varialable in the controller holding the value of the associated model ID, but that hasn't work.
*I should also mention that I'm using a sluggable behavior for tournaments, so it's not $id that is used but $slug.
Here are the model view controller details:
Model
tournament - has many tournamentDetails
tournamentDetails - has many updates
updates - belongs to tournamentDetails
tournaments controller
action = view
class TournamentsController extends AppController
function view($slug = null) {
if (!$slug) {
$this->Session->setFlash(__('Invalid Tournament.', true));
$this->redirect(array('action'=>'index'));
}
$this->Tournament->recursive = 1;
$tournament = $this->Tournament->findBySlug($slug);
$updates = $this->Tournament->TournamentDetail->Update->find('all', array('conditions'=>array('update.tournament_detail_id' => $this->data['tournament_details'] ['id'] )) );
$this->set(compact('tournament','updates' ));
Tournament view. This is display the 'tournament details' and (ideally) related tournament detail 'updates'
<h2><?php echo $tournament['Tournament']['name']; ?></h2>
<?php foreach ($tournament['TournamentDetail'] as $tournamentDetail): ?>
<h1><?php echo $tournamentDetail ['title']; ?></h1>
<p><?php echo $tournamentDetail ['body']; ?></p>
<?php endforeach; ?>
<?php foreach ($updates['Update'] as $update): ?>
<h4>Update: <?php echo $update ['date']; ?></h4>
<p> <?php echo $update ['Update'] ['title']; ?></p>
<p><?php echo $update ['Update'] ['body']; ?></p>
<?php endforeach; ?>
when I debug $updates, this is all I see:
Array
(
)
I don't know what I'm doing wrong here.
Is it not correct to construct the find conditions by using:
('conditions'=>array('update.tournament_detail_id' => $this->data['tournament_details'] ['id'] )
Thanks for the help.
Paul

You can use the Containable Behavior to specify in detail what fields you want to obtain from associated models, associated models to associated models and so on. Then you will find all data inside the array $tournament, like in the examples in the link.
EDIT (in response the OP comment). I think that the problem may be using the magic findBy method. You would need to substitute that with the standard find, like in this example
$tournament = $this->Tournament->find('first', array(
'conditions' => array(
'slug' => $slug
),
'contain' => array(//Put here the settings for Containable
)
));

Related

wordpress loop with pagination only showing two pages

I've created a loop with pagination, to show three posts per page. The pagination is only showing two pages of posts, whereas it should be showing four, as there are 11 posts altogether. The code that I'm using is taken from the WordPress Codex. I'm only just starting out with WordPress development and PHP, so my knowledge is still quite basic. Any help would be appreciated. This is what I have at the moment:
<?php
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
'posts_per_page' => 3,
'paged' => $paged
);
$the_query = new WP_Query( $args );
?>
<?php if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<p><?php the_title(); ?></p>
<?php endwhile; ?>
<!-- pagination -->
<?php next_posts_link(); ?>
<?php previous_posts_link(); ?>
<?php else : ?>
<!-- No posts found -->
<?php endif; ?>
Try removing posts_per_page from the query and setting this in the "Blog pages show at most" section in the Reading area in Settings.
Then in your next_post_link(), add the following conditions so it looks like this:
next_posts_link( 'Next Page »', $the_query->max_num_pages );
Note that the first argument can say whatever you want it to say. The second argument is what allows the pagination to work properly. Hope this helps.

Using Wordpress, how can I display posts that are in multiple categories?

I am trying to retrieve posts in Wordpress that belong in two categories. Each post must belong in both categories.
Here is my query:
<?php $myPosts = new WP_Query('category_name=featured+news&posts_per_page=10'); ?>
<?php if($myPosts->have_posts()) : ?>
<?php while($myPosts->have_posts()) : $myPosts->the_post(); ?>
<article>
<h2><?php the_title(); ?></h2>
<?php the_content(); ?>
</article>
<?php endwhile; ?>
<?php endif; ?>
In this example, 'featured' and 'news' are the slugs of two categories. I am using the plus symbol (+) with the 'category_name' parameter in my query to indicate that posts must be in both categories, as suggested here.
For some reason, this isn't working and I'm not sure why. I am getting this error:
PHP Warning: urldecode() expects parameter 1 to be string
It's referencing the query.php file:
wp-includes/query.php
Why can the query not interpret featured+news as a string? I figure I must be missing something. Any help is very much appreciated.
I'm not sure why the plus symbol (+) isn't working but using category__and instead works.
$featuredID = get_category_by_slug('featured')->term_id;
$newsID = get_category_by_slug('news')->term_id;
$myPosts = new WP_Query(array('category__and' => array($featuredID, $newsID), 'posts_per_page' => 10));

pagination not working when clicked next button

Controler
public function search() {
$this->Paginator->settings = $this->paginate;
$this->loadmodel('Usermgmt.User');
if ($this->request -> isPost()) {
$this->User->set($this->data);
$keyword=$this->data['Doctors']['search'];
//$this->loadmodel('Usermgmt.User');
$cond=array('OR'=>array("User.username LIKE '%$keyword%'","User.email LIKE '%$keyword%'", "User.first_name LIKE '%$keyword%'", "User.last_name LIKE '%$keyword%'"));
//$result = $this->paginate('User',array('conditions'=>$cond));
$result = $this->paginate('User',array($cond));
$this->set('result', $result);
}
}
View
<?php
if (!empty($result)) { $sl=0;
foreach ($result as $row1) {
//print_r($row1);
$sl++; ?><div style="width:100%;display:inline-block;">
<div style="float:left">
<?php
//echo $row1['id'];
echo $this->Html->link($this->Html->image('../files/user/photo/'.$row1 ['User']['photo_dir'].'/'.$row1 ['User']['photo'], array('width' => '180', 'height' => '180')),
array('controller'=>'Profiles','action'=>'index',$row1['User']['id']),
array('escape' => false));
?>
</div>
<div>
<?php echo h($row1['User']['first_name'])." ".h($row1['User']['last_name'])."</br>";
echo h($row1['User']['username'])."</br>";
echo h($row1['User']['email'])."</br>";
echo h($row1['User']['mobile'])."</br>";
echo h($row1['UserGroup']['name'])."</br>";
?></div>
<div style="clear:both;"></div>
</div>
<?php }?>
<?php echo $this->Paginator->prev('previous'); ?>
<?php echo $this->Paginator->numbers(); ?>
<?php echo $this->Paginator->next('Next'); ?>
<?php }?>
here am search the user name or user details like fname, email like and display in view page
here i get output with pagination like 1 2 3 4 only first page displays when i click next page that shows empty pages may be $result getting unset how to solve this ??
The variable result is only sometimes set
if ($this->request->isPost()) {
...
$result = $this->paginate('User',array($cond));
$this->set('result', $result);
}
The variable result is only set for POST requests - clicking a link is not a post request, therefore the result variable is undefined.
Ensure you are paginating a GET request
There are several solutions, but the simplest solution to "How to paginate post data" is to not do so. Change your search form to use GET, and ensure the get parameters persist when paginating a request.
At the very least the controller code needs to call paginate and set for the variables in the view to exist irrespective of how the controller action was reached.

cakephp $this->request-is("post") return false for just one form, so strange?

I have many forms in the website. They are all created in the similar way like
<?php echo $this->Form->create('SysUser');?>
<fieldset>
<legend><?php echo __('Edit Basic Information'); ?></legend>
<?php
echo $this->Form->input('SysUser.first_name');
echo $this->Form->input('SysUser.family_name',array('label'=>__("Last Name")));
echo $this->Form->input('SysUser.mobile_phone_number');
echo $this->Form->input('SysUser.user_name',array('label'=>__("Screen Name")));
echo $this->Form->input('action', array('type'=>'hidden','value'=>'edit_basic_info'));
echo $this->Form->input('SysUser.id', array('type'=>'hidden','value'=>$user["id"]));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit'));?>
But the type of one form becomes "put" , not "post". I never explicitly set the type to "post" when I create these forms. I gather CakePHP sets the default value to post. Now it seems something wrong about the way I create this new special form. Oddly, this was working days ago!
I don't know what's wrong. Here is it:
<?php echo $this->Form->create('Member'); ?>
<fieldset>
<legend><?php echo __('Basic Profile Setup'); ?></legend>
<?php
echo $this->Form->input('Member.gender_id');
$w = array();
for ($i = 40; $i < 120; $i++) {
$w[$i] = $i . " kg";
}
$h = array();
for ($i = 120; $i < 230; $i++) {
$h[$i] = $i . " cm";
}
echo $this->Form->input('Member.height', array(
'options' => $h,
'empty' => __("choose one")
));
echo $this->Form->input('Member.weight', array(
'options' => $w,
'empty' => __("choose one")
));
$options['minYear'] = date('Y') - 78;
$options['maxYear'] = date('Y') - 18;
echo $this->Form->input('Member.birthdate', $options);
echo $this->Form->input('Member.residential_location_id', array('label' => __("City/Location")));
echo $this->Form->input('Member.occupation_id',array('id'=>'MemberOccupationId'));
echo $this->Form->input('action', array('type' => 'hidden', 'value' => 'create_member'));
?>
</fieldset>
<?php
echo $this->Form->end(array("label" => __('Save')));
When the Request data contains a Model.id CakeRequest::method() is set to put. The preferred way to handle this in cakephp would be as follows.
if ($this->request->is(array('post', 'put'))) {
// Code
}
You can see this in baked controller, edit actions.
Not sure why it is happening, but you can set the form type this way:
<?php echo $this->Form->create('Member', array('type' => 'post')); ?>
I had this problem as well. In my situation this was happening when I had validation errors. So for the second run, the script thought it was a PUT request instead of a POST request. Now, because it was a PUT, it didn't even get inside the if-clause where I checked if it was a POST, so it would return to the input and try to create a POST request. This was looping forever.
The solution? Checking for a NOT GET.
So you would get something like this:
if (!$this->request->is('get')){
//Save logic here
}
I have seen an example like this in the Cookbook, but I can not find it. So I have a feeling it has been updated, but as far as I am concerned you have to use this method. So you will cover a PUT, as well as a POST request.
UPDATE
It is not recommended to use this approach. It is a PUT/POST based on if the id is set in the form. Since I was setting the id based on the type of request, instead of if it actually exists, it was switching over and over again. I am using 1 form for the add and the edit action. They both use the edit.ctp which is just set up more flexible.
From the Cookbook:
If $this->request->data contains an array element named after the form’s model, and that array contains a non-empty value of the model’s primary key, then the FormHelper will create an edit form for that record.
Is that the case, perhaps? What's Member's primary key?
I had the same issue and after 4 hours searching I just resolved it appending the Model name to the fields in the view like this:
<?php echo $this->Form->create('User');?>
<?php
echo $this->Form->input('User.id');
echo $this->Form->input('User.username', array('readonly' => true));
echo $this->Form->input('User.email', array('readonly' => true));
echo $this->Form->input('User.name');
echo $this->Form->input('User.phone');
echo $this->Form->input('User.gender');
echo $this->Form->input('User.locale', array('id' => 'locale_select', 'options' => array('es' => __('Spanish'), 'en' => __('English'))));
echo $this->Form->input('User.birthday', array('type' => 'date', 'dateFormat' => 'DMY', 'minYear' => date('Y') - 100, 'maxYear' => date('Y')));
?>
<?php echo $this->Form->end(__('Save', true));?>
Well, I have to say that this code is in a plugin, so I don't know if there could be any other problems. But other forms in that plugin work perfect and this one needs to have the Model name.
One of the ways I've handled this situation is to create my own detector that defines the context of post OR put. This goes in the beforeFilter() method in AppController:
// add a simple form post detector
$this->request->addDetector('formPosted', array(
'env' => 'REQUEST_METHOD',
'options' => array('post', 'put')
));
Then when you need to check if a form has been posted (or "putted"), then:
if ($this->request->is('formPosted')) { ... }
Since the detector is added in AppController, the condition can be checked from within any controller method.

Disable specific divs in CakePHP based on page selected

I'm new with CakePHP and I need your assistance. I need to display a specific widget which is in the form of a div on a specific page i.e. my homepage and disable on the rest of the pages. Essentially I have been able to specifically display specific divs based on log in status as indicated below:
<?php if (!$this->Session->read('Auth.User.id')): ?>
<div class="register link right <?php if ($active == 'register') echo 'active'; ?>"><?php echo $html->link('Register', array('controller' => 'users', 'action' => 'register')); ?></div>
<div class="login link right <?php if ($active == 'login') echo 'active'; ?>"><?php echo $html->link('Login', array('controller' => 'users', 'action' => 'login')); ?></div>
<?php else: ?>
<div class="logout link right"><?php echo $html->link('Logout', array('controller' => 'users', 'action' => 'logout')); ?></div>
<div class="myaccount link right <?php if ($active == 'myaccount') echo 'active'; ?>"><?php echo $html->link('My account', array('controller' => 'account', 'action' => 'summary')); ?></div>
<?php endif; ?>
I was asking for any help with regards to displaying a specific div based on the selection of my homepage.
The pseudocode below indicates my the line of thinking I'm taking to solve this issue:
<?php if (the selected page is homepage or default.ctp)?>
// set the display property for the desired div to none
<?php else: ?>
// do not set the display property for the desired div to none
<?php endif; ?>
In cakephp you cannot use directly $this->Session->read('Auth.User.id') in your view is bettere to do this into your controller:
$this->set('authUser', $this->Auth->user());
and into your view
if (!$authUser)
{
//not logged
}
else{
//logged
}
And if you wanna check which is the page you can try something like that
echo Router::url($this->last, true);
Is what you want?
In your controller you can define something like:
$this->set('pageName', $pageName);
Then you can do in your view:
$class='';
if($pageName=='homepage') {
$class=' hide';
}
echo $this->Html->div($class, 'your content here');
Also think about why you need a structure of this in your view. Maybe you can just not supply the content if it is not needed to the view? So you make the decision in your controller. That makes most of the time more clean views and the smallest amount of data needed in your view.

Resources