I have the code below. $related is array result of db query and contains data.
Queried data consist of posts belonging to different groups (post_type). I want to group the queried objects within their post_type. The code below works BUT... what I want is create different ULs for each post_type. As it is below, there will be a UL element foreach post found in the query. So UL should stay out of foreach, but on the other hand how can i get post_type out of foreach? I am a bit lost here :(
$related = p2p_type( 'accommmodation-to-places' )->get_connected( get_queried_object_id() );
foreach($related->posts as $post) {
echo '<ul class="related-'.$post->post_type.'">'; // this shouldn't be here
if($post->post_type == 'hotels') {
echo '<li>'.get_the_post_thumbnail($post->id, '48').$post->post_title.'</li>';
}
echo '</ul>'; // this shouldn't be here
}
wp_reset_query();
So first, group the posts by their type:
$groups = array();
foreach ($related->posts as $post) {
$groups[$post->post_type][] = $post;
}
Then loop through the groups and output the lists:
foreach ($groups as $type => $posts) {
printf('<ul class="%s">', htmlspecialchars($type));
foreach ($posts as $post) {
printf('<li>...</li>', ...);
}
echo '</ul>';
}
Related
I have two databases tables called article_category and article_case. They are supposed to be combined in a webpage as below:
Article category[title]
Article category[description]
Article case[title]
Article case[contents]
Article case[title]
Article case[contents]
This should repeat itself using foreach until all article categories are populated on the page.
Each article_case will also use foreach, but it has to respect its 'category_id' value which matches the 'id' in article_category .
I'm having trouble filtering the article_case table so that it only picks up rows from its parent 'category_id'.
This is my current php code (which only makes an array of each table):
$this->db->select( "id,title,description" );
$this->db->from( 'article_category' );
$query_article_category = $this->db->get_compiled_select();
$query = $this->db->query( $query_sustainability_category . 'ORDER BY sort ASC ' );
foreach ($query->result_array() as $val) {
$data['article_category_posts'][$val['id']] = $val;}
$this->db->select( "id,category_id,title,contents" );
$this->db->from( 'article_case' );
$query_article_case = $this->db->get_compiled_select();
$query = $this->db->query( $query_article_case);
$data[ 'article_cases' ] = $query->result_array();
And here is my html:
<?php foreach ($article_category_posts as $key => $val) { ?>
<section>
<h2><?php echo $val['title']; ?></h2>
<p><?php echo $val['description']; ?></p>
</section>
<?php foreach ($article_cases as $key => $val) { ?>
<section>
<h3><?php echo $val['title']; ?></h3>
<p><?php echo $val['contents']; ?></p>
</section>
<?php } ?>
<?php } ?>
The current setup will input all article_cases disregarding the category_id.
How can I use foreach while assigning each article_case to their respective article_cateogry?
This would generate unnecessary amount of queries to the DB server.
The rly basic approach would be:
select all categories (as you have) SELECT * FORM a_category
for each category select cases SELECT * FROM a_case WHERE category_id = {$category['id']}
The second one is to combine the categories and cases right in the query with join and adjust the resulting data in php:
SELECT cat.title, cat.description, case.id AS case_id, case.category_id, case.title, case.content
FROM a_case case
INNER JOIN a_category cat ON cat.id = case.category_id
You can use a query to get all the records of article_case with related article_category.
group the query result by category_id.
$this->db->select("cat.title,cat.description,case.category_id,
case.title AS case_title, case.contents" );
$this->db->from( 'article_category cat');
$this->db->join('article_case case','case.category_id=cat.id');
$result=$this->db->get()->result_array();
$result_group = array_group_by($result, 'category_id');
array group by function
function array_group_by(array $array, $key)
{
if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key)) {
trigger_error('array_group_by(): The key should be a string, an integer, or a callback', E_USER_ERROR);
return NULL;
}
$func = (is_callable($key) ? $key : NULL);
$_key = $key;
// Load the new array, splitting by the target key
$grouped = [];
foreach ($array as $value) {
if (is_callable($func)) {
$key = call_user_func($func, $value);
} elseif (is_object($value) && isset($value->{$_key})) {
$key = $value->{$_key};
} elseif (isset($value[$_key])) {
$key = $value[$_key];
} else {
continue;
}
$grouped[$key][] = $value;
}
// Recursively build a nested grouping if more parameters are supplied
// Each grouped array value is grouped according to the next sequential key
if (func_num_args() > 2) {
$args = func_get_args();
foreach ($grouped as $key => $value) {
$params = array_merge([$value], array_slice($args, 2, func_num_args()));
$grouped[$key] = call_user_func_array('array_group_by', $params);
}
}
return $grouped;
}
in view you can show as below
<?php foreach ($result_group as $key => $cat_result) { ?>
<section>
<h2><?php echo $cat_result[0]['title']; ?></h2>
<p><?php echo $cat_result[0]['description']; ?></p>
<div class="box-bd-doted">
</section>
<?php foreach ($cat_result as $key => $val) { ?>
<section>
<h3 style="color:red"><?php echo $val['case_title']; ?></h3>
<p><?php echo $val['contents']; ?></p>
</section>
<?php }
}
?>
I am trying to fetch data from another custom post type books into the readers. I have written the code and the data shows up.
The challenge is that I want to check the echoed data $c[0] against the title of the current page.
Whenever I call the get_the_title() function I am instead getting the title of the other custom post type books. So there is no way I can add an if like so:
if (get_the_title()===$c[0]) {
//The echo code - see echo part of my code
}
When I echo the code, it goes into the top part of the page instead of inside the content area. I am suspecting this is the reason why I can't get the page title. I have tried researching on hooking to the content area and tried but I instead get a bunch of errors.
<?php
$posts = get_posts(array(
'numberposts' => 10,
'post_type' => 'fixtures-results'
));
if($posts)
{
foreach($posts as $post)
{
setup_postdata( $post );
$matches = str_replace("|% ","|%",get_field('fixtures_results'));
preg_match_all("#[A-z0-9 ./'áàâäãåǻăāąấấặắǎȧạàãáćĉċčççďđḑḋḍdéèêëĕěēęėềẽȩẹéĝ
ğġģǧǵḡĥħȟḣḥḩíìîïĭїĩīįǐĪỊ̣iỊǏĨị̣ịıíĵķǩḱḳļľŀĺĺóòôöõðőŏōỏǒǫȯoøồớòóõöñńņňʼnŋǹṅṇ
ŕŗřṙṛśŝşšṡṣşșţťŧțṫṭtúùûüůūűųũŭǔǘǚǜụuưüúŵŷýÿўỹẏỳỵyẙȳẙźżžẑẓḅḟḿṁṃṕṗṽṿḷẁẃẅẉẘ
ẘẋẍÒÓÔÕÖŐǑǪŌȮØÙÚÛǓǗǙǛŨŮŰŲÜỤŪĆĈČÇÀÁÂÃÄÅẠĄĀȦǍÈÉÊËĖĘĚẸẼĒȨḾṀṂŚŜŞŠṠṢŹŻŽẐẒŃŅŇ
ṄṆÑǸḢḤḨĤȞĹĻĽĿŢŤṪṬŖŘṘṚĜĠĢǦǴḠẀẂẄẈŴḊḌḐĎĐÐṔṖĶǨḰḲẊẌṼṾỴỸỲẎŸȲŶÝĴȷḄḞḶŁłÏÎÍÌıİ
ßıs-]+#[^#]+#", $matches, $countries);
$results = [];
foreach ($countries[0] as $c) {
$c = explode("#", $c);
$country_name = $c[0];
$results[$country_name] = [];
$params = explode("%", $c[1]);
foreach ($params as $key) {
if (!empty($key)) {
$test = explode("|", trim($key, '|'));
echo get_the_title($postID);
//echo $c[0] . $test[0] . $test[1] . $test[2].'<br>';
}
}
}
}
wp_reset_postdata();
}
?>
I have tried but can't get past that point. Thanks.
I have an array with products, filled by the API.
I want to extend it and add some values like categories, price. I tried to add & before the array when looping to use it by reference row. But when I added another while loop to add categories, the $row wasn't extended.
$products = array('id_product'=>12,'link'=>'test.html','description'=>'desc');
foreach($products as &$row) {
$row['price'] = 12;
$product = new Product($row['id_product'];
$categories = $product::getCategories();
$k = 1;
while ($cat = current($categories)){
$row['categoryid'.$k] = $cat['name'];
$k++;
}
}
$product::getCategories() return
array(1) { [0]=> array(1) { ["name"]=> string(8) "T-shirts" } }
The problem is that the array key with categoryid.$k is never created, I tried with foreach on categories but it didn't work.
In provided example in foreach loop $row will contains values 12, 'test.html' and 'desc'. So you can't use them as array.
Valid code:
$products = array();
$products[] = array('id_product'=>12,'link'=>'test.html','description'=>'desc');
Also you have invalid while loop, replace current function with array_shift, or use proper foreach loop
Edited:
Replace while with this code:
if (!empty($categories)) {
foreach ($categories as $key => $category) {
$row['categoryid' . $key] = $category['name'];
}
}
I fixed my problem by adding a function and pass by value the row parameter
private function addCategories(&$row){
$categories = $this->getProductCategoriesFull((int)$row['id_product']);
if (!empty($categories)) {
$k = 2;
foreach($categories as $category) {
if($k!= 2)
$row['categoryid' . ($k-1)] = $category['name'];
$k++;
if($k>5) exit;
}
}
}
And call it in the loop
$this->addCategories($row);
OK, I have a very specific question that I hope someone can shed some light on.
I have a page that lists authors outputting using the following code
<?php
$display_admins = false;
$order_by = 'post_count'; // 'nicename', 'email', 'url', 'registered', 'display_name', or 'post_count'
$role = ''; // 'subscriber', 'contributor', 'editor', 'author' - leave blank for 'all'
$hide_empty = true; // hides authors with zero posts
if(!empty($display_admins)) {
$blogusers = get_users('orderby='.$order_by.'&role='.$role);
} else {
$admins = get_users('role=administrator');
$exclude = array();
foreach($admins as $ad) {
$exclude[] = $ad->ID;
}
$exclude = implode(',', $exclude);
$blogusers = get_users('exclude='.$exclude.'&orderby='.$order_by.'&role='.$role.'&order='.'DESC');
}
$authors = array();
foreach ($blogusers as $bloguser) {
$user = get_userdata($bloguser->ID);
if(!empty($hide_empty)) {
$numposts = count_user_posts($user->ID);
if($numposts < 1) continue;
}
$authors[] = (array) $user;
}
echo '<ul class="contributors">';
foreach($authors as $author) {
$display_name = $author['data']->display_name;
$avatar = get_wp_user_avatar($author['ID'], 'medium');
$author_profile_url = get_author_posts_url($author['ID']);
$filter = get_userdata($author['ID'])->yim;
echo '<li><div class="home ', $filter,' "><div class="feature-image">', $avatar , '</div>
<div class="post-title"><h3>', $display_name, '</h3></div>
</div>
</li>';
}
echo '</ul>';
?>
(I got this from another support topic and tweaked it, although I can't remember where)
At the moment, the $filter variable is just a string I enter in the 'Yahoo IM' profile box (a dirty fix to test the filter). I'd like this to actually be a list of the categories (as slugs that I will output in to the class="" part of the loop) that the author has posted in.
I essentially want to be able to filter the authors by category that they have posted in, and the filter I'm using (Isotope) operates using the class, so outputting the categories in to the class of the markup is what I'm after.
Any suggestions gratefully received!
// Returns the posts made by the author
$authorPosts = get_posts("author={$author['ID']}");
$categoryList = array(); // reset previous values
foreach ($authorPosts as $post) {
$postCategories = get_the_category($post->ID);
// Add to the categories the author has posted in
foreach ($postCategories as $category)
$categoryList[] = $category->slug;
}
// Removes duplicate categories
$categoryList = array_unique($categoryList);
You can then use $filter = implode(' ', $categoryList); and add it to your html.
RE not storing the array from the other answer, you can just echo out the slugs there and then like this:
$authorPosts = get_posts("author={$author['ID']}");
foreach ($authorPosts as $post) {
$postCategories = get_the_category($post->ID);
// Add to the categories the author has posted in
foreach ($postCategories as $category)
echo($category->slug);
}
otherwise if you want to put your PHP at the top and echo out the slugs further down the page pop there where ever you want to echo them:
$i = 0;
foreach($categoryList as $category) {
echo($categoryList[$i]);
$i++;
}
I've got a little sidebar that displaying in the code before the main page content. I wrote this (janky) function to pull in recent posts and comments. Works great, however, its screwing with all my pages and putting posts on all of them. How do I reset/rewind the query or make a new one so all my pages display the correct content?
<?php rewind_posts(); ?>and<?php wp_reset_query(); ?> arent doing the trick for me
Here is my query:
$comments = get_comments('number=10');
$posts = get_posts('posts_per_page=10&category=6');
$most_recent = array();
foreach ($comments as $comment)
$most_recent[strtotime($comment->comment_date_gmt)] = $comment;
foreach ($posts as $post)
$most_recent[strtotime($post->post_date_gmt)] = $post;
unset($comments, $posts);
krsort($most_recent);
$most_recent = array_slice($most_recent, 0, 10);
foreach ($most_recent as $post_or_comment) {
$is_post = isset($post_or_comment->post_date_gmt);
$comment_id = $post_or_comment->comment_ID;
$post_id = $post_or_comment->ID;
$comment_post_id = $post_or_comment->comment_post_ID;
if ($is_post == 1)
{ ?> <li><?php echo $post_or_comment->post_title; ?><span class="tag"><?php echo the_category($post_id); ?></span></li><?php }
else
{ ?><li> <?php echo get_the_title($comment_post_id); ?><span class="tag">Comment</span></li><?php }
// output comments and posts
}
output comments and posts
}
Try using $my_posts and $my_comments instead, just in case WP is using samely-named globals (though I don't think it is).
Also, in your foreach loop, you should only be casting variables when you know the object type, otherwise you're accessing non-existent properties;
foreach ($most_recent as $post_or_comment) {
$is_post = isset($post_or_comment->post_date_gmt);
if ($is_post) {
$post_id = $post_or_comment->ID;
} else {
$comment_id = $post_or_comment->comment_ID;
$comment_post_id = $post_or_comment->comment_post_ID;
}
}
rewind_posts() will have no effect here. Just call wp_reset_query() right after the foreach loop ends.