Group records in CakePHP based on first letter? - cakephp

I'm wanting to fetch and group records from a database table by the first letter. So for example:
A
Alfred
B
Brian
C
Christopher
...
Ideally, I'd like my data structure to come out as follows:
Array
(
[A] => Array
(
[0] => Array
(
[Person] => Array
(
[id] => 12
[name] => Alfred
)
)
)
)
I could do this with a raw MySQL query, but not sure if CakePHP supports this out of the box. I'm just literally wanting records grouped so I can iterate over them and create an unordered list for each letter:
<h2>A</h2>
<ul>
<li>Alfred</li>
</ul>
<h2>B</h2>
<ul>
<li>Brian</li>
</ul>
<h2>C</h2>
<ul>
<li>Christopher</li>
</ul>
...

What i would do is: order them by name and then sort them in a loop:
$people = $this->Person->find('all', array(
'order' => 'Person.name ASC'
));
And then you could do:
$letter = '';
foreach($people as $person) {
$firstLetter = strtolower(substr($person['Person']['name'], 0, 1));
if ($firstLetter !== $letter) {
$letter = $firstLetter;
}
$_people[$letter][] = $person;
}
$people = $_people;
Or just do it directly in the view so you don't need to loop it twice:
<ul>
<?php $letter = 'first'; ?>
<?php foreach ($people as $person) : ?>
<?php $firstLetter = strtolower(substr($person['Person']['name'], 0, 1)); ?>
<?php if ($firstLetter !== $letter) : ?>
<?php if ($letter !== 'first') : ?>
</ul></li>
<?php endif; ?>
<?php $letter = $firstLetter; ?>
<li><h2><?php echo $firstLetter; ?></h2><ul>
<?php endif; ?>
<li><?php echo $person['Person']['name']; ?></li>
<?php endforeach; ?>
</ul></li></ul>
I wouldn't know how to get this structure just by using a find call (except for making 26 calls or creating a db table containing all letters) and I don't see why that would be neccesairy.
Hope that helps! (ps code isn't tested... but you get the point. should there be any typos)

Try this:
$peoplebyletter = array();
foreach($people as $person){
$peoplebyletter[strtolower(substr($person['Person']['name'], 0, 1))][] = $person;
}
debug($peoplebyletter);
Not tested. Let me know if it works.

Related

Loop to display one product / several products by sku on Woocommerce?

I'm attempting to display one or more specific product(s) on my home page on Woocommerce, in a very simple fashion :
name of the product;
short description of the product;
price of the product;
quantity selector;
add to cart button;
Now, i've created a custom loop for doing so:
<?php
$args = array(
'post_type' => 'product',
'sku' => 'lundivegetarien',
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
echo the_title();
echo woocommerce_template_single_excerpt();
echo woocommerce_template_single_price();
echo woocommerce_template_single_add_to_cart();
endwhile;
} else {
echo __( 'No products found' );
}
wp_reset_postdata();
?>
Main problem here is that this loop displays all my products, irrespectively of the sku i'm trying to call. I would like to be more specific, and be able to choose to display one or several products i'd call by their specific sku.
What am i doing wrong?
Any pointers?
Help appreciated!
Sorted out the problem myself eventually, so dumb i was! Just turned to using categories and it works pretty fine!
Here's the updated code in cas anybody needs it!
<?php
$args = array( 'post_type' => 'product', 'product_cat' => 'name_of_the_category', 'posts_per_page' => 1 );
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post(); global $product;
?>
<p>
<?php
the_title();
?>
</p>
<?php
echo woocommerce_template_single_excerpt();
echo $product->get_price_html();
?>
<div class="order_form close">
<p>
<?php
woocommerce_template_loop_add_to_cart( $loop->post, $product );
?>
</p>
</div>
<br>
<?php
endwhile;
?>
Hope this will help someone!

Create a custom loop with post IDs taken from Magic Fields 2 duplicate text fields

I'm trying to create a custom loop with content related to specific post IDs whose numbers I'm getting from a Magic Fields duplicate text field called "reference_posts".
When I echo $testvalue; it outputs the correct listing of posts "20432,43242,34253," but when I try to output it inside the array I only get the first value repeated over and over "20432,20432,20432,".
I'm guessing the problem is that I have to envelope the second foreach within the first but I'm not managing to do that.
Can anyone help me out?
<?php
$value = get_field ('reference_posts') ;
foreach ( $value as $my_val ) {
$testvalue = $my_val . ",";
echo $testvalue;
$post_idarray = array( 'post__in' => array( $testvalue ) );
$postspecial = get_posts($post_idarray);
}
foreach( $postspecial as $post ) :
setup_postdata($post);
?>
<div>my content</div>
<?php endforeach; ?>
Thanks in advance!
Got it with:
<?php
$value = get_field ('reference_posts') ;
foreach ( $value as $my_val );
$args = array( 'include' => $value );
$myposts = get_posts( $args );
foreach( $myposts as $post ) : setup_postdata($post); ?>
<div>my content</div>
<?php endforeach; ?>

cakephp: how to render related models in the view

My objective is to display records for a related child model (once removed) in the view. My problem is that I receive a 'Notice (8): Undefined index:' error message when I try to output the following query.
Tournaments have many tournamentDetails, and tournamentDetails have many updates. I'm trying to display all the updates for each tournamentDetail that is displayed on the tournaments view.
So my question is how to properly resolve the error message and display the updates for each tournamentDetail on the tournaments view page.
My find data in the 'tournaments' controller view action is:
$updates = $this->Tournament->TournamentDetail->Update->find('all', array( 'tournament_details.tournament_id'=> $this->data['Tournament']['id']));
In the view, I have this code.
<?php foreach ($tournament['Update'] as $update): ?>
<h3>Updates</h3>
<h1><?php echo $update ['title']; ?></h1>
<p><?php echo $update ['body']; ?></p>
<hr/>
<?php endforeach; ?>
This is the same 'foreach' code the I use for the other related child records without problem. I did use the debug() function to investigate but didn't see what I was missing.
The output of the $updates array from the debug function looks like this:
Array
(
[0] => Array
(
[Update] => Array
(
[id] => 1
[title] => first round matches start today
[date] => 2010-03-19
[body] => this tournament's first round matches start today.
[tournament_detail_id] => 4
[homeStatus] => no
)
Is there a special way to display records this deep?
As always, thanks in advance.
Paul
Update: Feb 23/11
After some testing the problem I seem to have is finding and passing the correct value to the $updates variable;
To summarize, I want the $updates variable to hold the current 'tournament_details_id'. This will then display the related update records in the 'tournaments' view.
I'm still a beginner and most likely overlooked the obvious.
Here is the model info:
class Tournament extends AppModel {
var $name = 'Tournament';
var $hasMany = array(
'TournamentDetail' => array(
'className' => 'TournamentDetail',
'foreignKey' => 'tournament_id',)
class TournamentDetail extends AppModel {
var $name = 'TournamentDetail';
var $belongsTo = array(
'Tournament' => array(
'className' => 'Tournament',
'foreignKey' => 'tournament_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
class Update extends AppModel {
var $name = 'Update';
var $belongsTo = array(
'TournamentDetails' => array(
'className' => 'TournamentDetails',
'foreignKey' => 'tournament_detail_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
Controller data:
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( 'tournament_details_id' => $this->data['TournamentDetails']['id'] )));
$this->set(compact('tournament','updates', $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; ?>
I've tested this by adding in the tournament details 'id' as an integer and it pulls up the correct 'update' record. However I seem to have problems configuring the find operation to do the same.
As always I appreciate the help.
Thanks
Paul
Based on your debug output, it seems that your $tournaments variable consists of an array (instead of the associative array) so you might want to use the foreach to access each of those elements:
foreach ($tournaments as $update):
?>
<h3>Updates</h3>
<h1><?php echo $update ['Update']['title']; ?></h1>
<p><?php echo $update ['Update']['body']; ?></p>
<hr/>
<?php endforeach; ?>
It appears that you be using the wrong variable, you talk about the $updates variable but you're using the $tournament variable in your view.
<?php foreach ($updates['Update'] as $update): ?>
<h3>Updates</h3>
<h1><?php echo $update ['title']; ?></h1>
<p><?php echo $update ['body']; ?></p>
<hr/>
<?php endforeach; ?>
Additionally you haven't posted the whole controller method, which includes that find but you might not have sent the data to the view yet either
$this->set(compact('updates'));

CakePHP find('neighbors') use [next] and [prev] from array

I am trying to get the neighbors Ids of the current Id.
What I have below works, but I cannot separate the [prev] from the [next] link.
The function in the controller looks as follows:
function prevNext() {
return $this->System->find('neighbors', array('fields' => 'name', 'value' => 3));
}
Which will output something like this:
Array
(
[prev] => Array
(
[System] => Array
(
[name] => Aegerter
[id] => 4004
)
)
[next] => Array
(
[System] => Array
(
[name] => Canonica
[id] => 4006
)
)
)
This gets passed as a requestAction -
<?php $systems = $this->requestAction('systems/prevNext'); ?>
<?php foreach($systems as $system): ?>
<?php echo $html->link($system['System']['id'],array('action'=>'view', $system['System']['id']));?>, <?php echo $system['System']['name'];?>
<?php endforeach; ?>
into the view as an element:
<?php echo $this->element('systems'); ?>
How do you call the [prev] and [next] link separately (not a foreach output)?
Tia
If i understand correctly:
<?php echo $html->link($systems['prev']['System']['id'],array('action'=>'view', $systems['prev']['System']['id']));?>, <?php echo $systems['next']['System']['name'];?>
<?php echo $html->link($systems['next']['System']['id'],array('action'=>'view', $systems['next']['System']['id']));?>, <?php echo $systems['next']['System']['name'];?>

WordPress: How to merge custom post type array?

i try to setup a yearly (grouped by month) archive for custom post types in WordPress. But my code did not work as aspected. Maybe it is obiviously for someone who is more familar with WordPress and PHP but i can't get it work.
The code below is grouping by month but each post type by itself. Maybe i need to merge booth. But how?
<?php query_posts (array ('post_type' => array('images', 'articles')));?>
<?php
if (have_posts()) : while (have_posts()) : the_post();
// save month to a variable
$month = the_date('M', '', '', FALSE);
// If not used before print it
if ($month != $m_check) {
echo "<h2>" . $month . "</h2>";
}
// save month to check variable
$m_check = $month;
?>
<?php the_title(); ?><br/>
<?php endwhile; ?>
<?php endif; ?>
<?php wp_reset_query();?>
Regards, Steve
You will need this: http://wordpress.org/extend/plugins/posts-to-posts/ to achieve what you want with custom posts.
Ok... after a cup of tea i got it with an other (probably better) approach.
Solution
<?php
$args = array(
'post_type' => array('images', 'articles'),
'numberposts' => -1,
'post_status' => null,
'post_parent' => null,
);
$posts = get_posts($args);
if ($posts) {
foreach ($posts as $post) {
setup_postdata($post);
$month = mysql2date('m', $post->post_date);
if ($month != $check) {
echo "<h2>" . $month . "</h2>";
}
// save month to check variable
$check = $month;
echo $post->post_title;
echo '<br/>';
}
}
?>
Output
07
Eagle creek
Lorem Ispum dolor
Vancouver Island
Ottawa
Vancouver
06
Losabim oxygenium
Now it needs just a bit beautifying and i am done. By the way #negatif, thank you for your suggestion.
Easy and correct way to merge our custom loop argument in default wordpress loop.
$argss = array(
'paged' => $paged,
'posts_per_page' => 9,
'meta_query' => array(
'relation' => 'OR',
array (
'key' => '_expiration-date',
'value' => $tode, // custom values
'compare' => '>='
),
array (
'key' => '_expiration-date',
'compare' => 'NOT EXISTS'
),
),
);
global $wp_query;
// Merge custom query with $wp_query
$merged_args = array_merge( $wp_query->query, $argss );
// Query posts using the modified arguments
query_posts( $merged_args );
if ( have_posts() ) : while (have_posts()) : the_post();
.
.
.
.
.
..
else : ?>
<p><?php _e('Apologies, but no entries were found.', 'tb'); ?></p>
<?php endif;
//wp_reset_query();
?>

Resources