How to format long echo expressions in PHP? - php

I'm writing my function in PHP for listing post categories (just look at code style, not logic):
function list_categories() {
// $html = '';
echo '<div class="post-categories post-items__categories">';
echo '<span class="post-categories__title">Categories:</span>';
echo '<ul class="post-categories__list">';
echo '<li class="post-categories__item"><a class="post-categories__link">All categories</a></li>';
$categories = get_categories([
'taxonomy' => 'category',
'type' => 'post',
'orderby' => 'name',
'order' => 'DESC',
'hierarchical' => false,
]);
foreach ($categories as $category) {
$cat_class = ($category->term_id == get_queried_object_id()) ? 'active' : '';
echo '<li class="post-categories__item">
<a class="post-categories__link" href="'.get_category_link($category->term_id).'">'.
$category->name.
'</a>
</li>';
}
echo '</ul></div>';
}
And I want my tag echoing expressions to be more readable, not just in one line like here:
echo '<li class="post-categories__item"><a class="post-categories__link">All categories</a></li>';
I'm using new lines in foreach loop, but it's still ugly.
I found out about heredoc syntax, but I can't call functions inside it.
How do you write this kind of things? I really don't want to write all in one line

If you just need to echo HTML why not break out of PHP, then back into it so
function list_categories() {
// $html = '';
echo '<div class="post-categories post-items__categories">';
echo '<span class="post-categories__title">Categories:</span>';
echo '<ul class="post-categories__list">';
echo '<li class="post-categories__item"><a class="post-categories__link">All categories</a></li>';
$categories = get_categories([....
becomes...
function list_categories() {
// $html = '';
//break out of php
?>
<div class="post-categories post-items__categories">
<span class="post-categories__title">Categories:</span>
<ul class="post-categories__list">
<li class="post-categories__item"><a class="post-categories__link">All categories</a></li>
<!--carry on with php-->
<?php
$categories = get_categories([....
And if you need to call a variable in the middle of html code you can like so..
<?php $demo = "hello"; ?>
<span><?php echo $demo; ?> World</span>
HTML in a variable...
<?php $html = ' ?>
<!--HTML HERE-->
<?php '; ?>

Related

How to refactor similar foreach loops to follow DRY approach

If you have foreach loops of multiple arrays, and you need to run one of them inside another - Is it possible to refactor the following code to only have one loop to stop duplicating code:
<?php
$apples = array(
'red',
);
$bananas = array(
'yellow',
);
foreach ( $apples => $apple ) {
echo '<div class="apple">' . $apple . '</div>';
}
foreach ( $bananas => $banana ) {
echo '<div class="banana">';
echo $banana;
echo '<div class="child">';
foreach ( $apples => $apple ) {
echo '<div class="apple">' . $apple . '</div>';
}
echo '</div>';
echo '</div>';
}
/*
output:
<div class="apple">red</div>
<div class="banana">
yellow
<div class="child">
<div class="apple">red</div>
</div>
</div>
*/
This code logic that is duplicate is the one that outputs the <div class="apple">red</div>:
foreach ( $apples => $apple ) {
echo '<div class="apple">' . $apple . '</div>';
}
I'm not sure if it's much improvement without being given better context, but using a function for generating the list should help reduce duplicate code.
<?php
$apples = array(
'red',
);
$bananas = array(
'yellow',
);
function getFruitListHTML(array $fruitList, string $class, string $child = ''): string {
$out = '';
foreach ( $fruitList as $fruitItem ) {
$out .= "<div class=\"$class\">";
$out .= $fruitItem;
$out .= $child;
$out .= '</div>';
}
return $out;
}
$applesHTML = getFruitListHTML($apples, 'apple');
echo $applesHTML;
echo getFruitListHTML($bananas, 'banana', "<div class=\"child\">$applesHTML</div>");

Traverse an array or cross an array

I am fairly new to php and trying to get echo "<p>" .get_the_tags($author_post). "</p>"; to echo out the tags associated with the post its listing in the loop.
I was told to "you need to traverse the array" and "This returns an array of tags. Then you have to cross the array if you want to echo it out."
but was not told how to accomplish this. I am unsure how to proceed.
Here is the full code.
if ($author_posts) {
echo '<ul>';
$i = 0;
foreach ($author_posts as $author_post) {
/* excluded categories */
if (has_category(explode(',', $atts['exclude']), $author_post->ID)) :
continue;
endif;
$postdate = date_i18n( get_option( 'date_format' ), strtotime($author_post->post_date)).' - ';
echo '<li>';
echo ($atts['postdate'] ? $postdate : ''). ''.$author_post->post_title.'';
$categories = get_the_category( $author_post->ID );
$list_cats =null;
foreach ($categories as $cat) :
$list_cats .= $cat->name.", ";
endforeach;
$list_cats = substr($list_cats, 0, -2);
echo "<p>" .get_the_tags($author_post). "</p>";
echo '</li>';
$i++;
if ($atts['postsperauthor'] > -1) :
if ($i >= $atts['postsperauthor']) :
break;
endif;
endif;
}
}
Thanks for any help you can provide
I guess your get_the_tags() return an array
try this:
$tags = get_the_tags($author_post);
$tagNames = [];
foreach ( $tags as $tag ) {
$tagNames[] = $tag->name
}
echo implode(',',$tagNames)
echo '</div>';
echo '</li>';
BTW , this syntax is a bit old...

Get current url in ci

I am making a breadcrumb for my codeigniter using bootstrap but would like to know how to get the current url and so it show the page on my breadcrumbs current_url() not sure how to use this
Displayed On Controller Index
$data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array(
'text' => $this->lang->line('language_key'),
'href' => $this->url->link
);
Displayed On View
<div class="breadcrumb">
<?php foreach ($breadcrumbs as $breadcrumb) { ?>
<li><?php echo $breadcrumb['text']; ?></li>
<?php } ?>
</div>
Working now
Controller file
$data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array(
'text' => $this->lang->line('heading_title'),
'href' => $this->uri->uri_string()
);
View File
<div class="breadcrumb">
<?php foreach ($breadcrumbs as $breadcrumb) { ?>
<li><?php echo $breadcrumb['text']; ?></li>
<?php } ?>
</div>
yep for example what i would do is create a helper "breadcrumb_helper.php" and place it in your helpers folder (application/helpers/breadcrumb_helper.php). Load it with the auto load config file so that it is loaded via the entire site and can be called inside a view file.
<?php
/* This is breadcrumb_helper.php */
function breadcrumbs() {
//get codeigniter instance as object
$ci =& get_instance();
$linkBuild = '';
$breadcrumbs = '';
//http://ellislab.com/codeigniter/user-guide/libraries/uri.html
//the uri class is loaded by the system automatically
$count = 1;
$segs = $ci->uri->segment_array();
//no need to run this on the main page and only show a link to the main page.
if(count($segs) >= 1) :
$breadcrumbs .= '<ol class="breadcrumb">';
$breadcrumbs .= '<li class="home"><i class="fa fa-home"></i></li>';
foreach ($segs as $segment)
{
$linkBuild .= $ci->uri->segment($count) . '/';
if($count <= count($segs)) :
$breadcrumbs .= '<li>' . $segment . '</li>';
else :
$breadcrumbs .= '<li>' . $segment . '</li>';
$count++;
endif;
}
$breadcrumbs .= '</ol>';
endif;
return $breadcrumbs;
}
Then in your view file you would just need to run the function like this:
<?= breadcrumbs(); ?>
And this will give you the current breadcrumb to the page you are on.

Current menu item - foreach

Consider this:
$menuItems = array (
"page1" => "1.php",
"page2" => "2.php",
"page3" => "3.php",
"page4" => "4.php",
"page5" => "5.php",
);
and now I create the menu like this:
<ul class="menu">
<?php
foreach($menuItems as $name => $url) {
echo "<li><a href='$url' class='$class'>$name</a></li>";
}
?>
</ul>
Works great. But now I need to add a class .current on the current page.
To get the current page I do this:
<?php
function curPageName() {
return substr($_SERVER["SCRIPT_NAME"],strrpos($_SERVER["SCRIPT_NAME"],"/")+1);
}
$curpage = curPageName();
?>
And it also works great.
SO I guess the question is how do I assign $curpage to the ... current page? :)
Thank you.
Alex
<ul class="menu">
<?php
foreach($menuItems as $name => $url) {
if ($url === $curpage){
$class.=' .current';
}
echo "<li><a href='$url' class='$class'>$name</a></li>";
}
?>
</ul>
Easy, inside your loop, check if $url == $curpage, and append appropriately.
Example:
<?php
$menuItems = array(
"page1" => "1.php",
"page2" => "2.php",
"page3" => "3.php",
"page4" => "4.php",
"page5" => "5.php",
);
$current_item = "2.php"; //Assume we got this from the function
?>
<ul class="menu">
<?php
foreach ($menuItems as $name => $url) {
echo "<li><a href='$url'";
if ($url == $current_item) {
echo " class='current'";
}
echo ">$name</a></li>\n";
}
?>
</ul>
<ul class="menu">
<?php
foreach($menuItems as $name => $url) {
$class = 'default';
if (curPageName() == $name) {
$class.='.current';
}
echo "<li><a href='$url' class='$class'>$name</a></li>";
}
?>
</ul>
So I made it work with your help! Thanks guys.
Special thanks for Adel - although you had a mistake there I fixed it like this:
foreach($menuItems as $name => $url) {
$class = 'default';
if (curPageName() == $url) {
$class.=' \. current';
}
echo "<li><a href='$url' class='$class'>$name</a></li>";
}
Awesome! Thanks again!
<?php
$menuItems = array(
'page1' => '1.php',
'page2' => '2.php',
'page3' => '3.php',
'page4' => '4.php',
'page5' => '5.php',
);
$current_page = curPageName();
?>
<ul class="menu">
<?php
foreach ($menuItems as $name => $url) {
?>
<li><a href="<?php=$url?>"
<?php
if ($url == $current_page) {
?>
class="current"
<?php
}
?>
><?php=$name?></a></li>
<?php
}
?>
</ul>
Why use the curPageName () at each iteration?
You can use a ternary syntax to solve your problem. It consists in this syntax:
(if condition ? true : false)
So we can use this way on your answer comparing the curPageName with the url inside the foreach loop.
$url == curPageName() ? 'current' : 'notCurrent'
Now you just need to use this in your favor.
I like the syntax of printf. So the code is more clean. Try this:
<?php
/**
* curPageName() is defined in question
* my_links() is a shortcut to array defined in question
*/
$template = "<li%s>%s</li>";
$links = my_links();
$current = curPageName();
print '<ul class="menu">';
foreach ($likns as $name => $url) {
$class = $current == $url ? ' class="current"' : '';
printf($template, $class, $url, $name);
}
print '</ul>';
Each %s item in $template will be changed by sequential variable. So, if you need to change the template the code is clean and easyest to give a maintance.
Or, if you want another easiest template way, use the php template syntax. Note the use of : after the foreach statement and the use of endforeach. You can see that I am using the short code of echo <?=$var?> that is more compreensible than <?php echo $var ?>.
<?php
/**
* curPageName() is defined in question
* my_links() is a shortcut to array defined in question
*/
$links = my_links();
$current = curPageName();
?>
<ul class="menu">
<?php foreach ($links as $name => $url): ?>
<li<?=($current == $url ? ' class="current"' : '')?>>
<?=$name?>
</li>
<?php endforeach ?>
</ul>

Better dynamic navigation menu

I have this approach for now:
ctop = $cnew = $cmine = '';
if($actual == 'top') $ctop = 'class="active"';
if($actual == 'last') $new = 'class="active"';
if($actual == 'mine') $cmine = 'class="active"';
$html = '<aside class="panel_derecho">
<div class="tabs"><h4>$donde</h4>
<ul>';
$js = "refrescar_submenu('last_$donde')";
$js_t = "refrescar_submenu('top_$donde')";
$js_r = "refrescar_submenu('mine_$donde')";
$html .= '<li '.$ctop.'>top</li>';
$html .= '<li '.$cnew.'>ultimos</li>';
$html .= '<li '.$mine.'>like</li>';
$html .= ' </ul>
</aside>';
return $html;
wich works as expected:
It generates a list with the desired copy, the desired javascript function parameter, and the active class (for the wanted one)
But i feel it could be less repetitive; and i can already see that it will be expensive to add/edit/remove copys, params, elements, etc.. i just don't know where to beggin..
In case it helps:
$donde represents the type of data (articles, songs, videos, ..)
$actual represents one atribute (new articles, top articles,
articles i like)
// Menu: link => text
$menu = array(
"top" => "top",
"last" => "ultimos",
"mine" => "like"
);
$html = '<aside class="panel_derecho">
<div class="tabs"><h4>$donde</h4>
<ul>';
foreach ($menu as $link => $text)
{
$html .= '<li '.( $link==$actual ? 'class="active"' : '').'>'.$text.'</li>';
}
$html .= ' </ul>
</aside>';
return $html;
$attributes = array("top" => "top", "last" => "ultimos", "mine" => "like");
$html = "<aside class=\"panel_derecho\">
<div class=\"tabs\"><h4>{$donde}</h4>
<ul>";
foreach ($attributes as $key=>$value)
$html .= " <li ". ($actual == $key ? "class=\"active\"" : "") .">{$value}</li>";
$html .= " </ul>
</div>
</aside>";
return $html;

Categories