This is my first question.
I'm building a simple dynamic menu using <li>
I'm working on a PHP based CMS (Kirby)
Kirby has predefined PHP functions (helpers)
I'm trying to output a <li> for each page on the website:
<li class='active'><a href='page1'></a></li>
<li><a href='page2'></a></li>
<li><a href='page3'></a></li>
...
Im using a PHP function e($condition, $value) to style the menu item only if that page isOpen()
// I need help here
<?php
foreach ($pages->visible() as $p):
echo "<li" . e($p->isOpen(), ' class="active"') . "><a href='" . $p->url() . "'></a></li>";
endforeach;
?>
The function is working but the css part class="active" is printing OUTSIDE the <li> on the final code
class="active"
<li>...</li>
<li>...</li>
<li>...</li>
I had this previous code that worked fine, but since i'm using display: inline-block the menu had spaces betwes each block, since the following code was placing each <li>in a new line.
// This code works
<?php foreach($pages->visible() as $p): ?>
<li <?php e($p->isOpen(), ' class="active"') ?> ></li>
<?php endforeach ?>
The reason i'm rewrinting the code is to remove the white space between the inline: blockelements.
I'm failing to concatenate the string in a way that the function works and print its results inside the <li>tag.
I've searched here and also have read lots of Docs in php.net but nothing worked to me, I'm struggling with this for 2 days.
I'm expecting to learn better how and when to use concatenation and string operators.
The problem is that Kirby's e() function already has the echo in the routine, instead of just simply returning the value.
http://getkirby.com/docs/cheatsheet/helpers/e
If you were to change your output loop to something more like this, echoing separately, you'll get the results in the desired order:
foreach($pages->visible() as $p)
{
echo "<li";
e($p->isOpen(), ' class="active"');
echo "> and the rest of your line </li>";
}
That said, perhaps using e() isn't the most elegant in this case. Maybe try the r() function instead:
http://getkirby.com/docs/cheatsheet/helpers/r
foreach($pages->visible() as $p)
{
echo "<li ".r($p->isOpen(), ' class="active"').">more text</li>";
}
I'm trying to put a menu together where it will sense what page is loaded. This site is not done in a CMS and is straight PHP/HTML code.
I currently have the navigation working for the primary links. There is a dropdown where I am having problems. I need to be able to see if the parent or any dropdown children are active. If one of the children are active. In the example below this is "FAQ" and the children are "FAQ1," "FAQ2," and "FAQ3."
For this example I'm using a CSS state called "active."
<style>
a{color:red;}
.active{color:blue;}
</style>
Here is the script used for the menu. The links for Home, Products, and Contact are working as expected.
<ul>
<li><a href="index.php" id="homenav" <?php if (strpos($_SERVER['PHP_SELF'], 'index.php')) echo 'class="active"';?>>Home</a></li>
<li><a href="products.php" id ="prodnav" <?php if (strpos($_SERVER['PHP_SELF'], 'products.php')) echo 'class="active"';?>>Products</a></li>
<li><a href="faq.php" id ="faqnav" <?php if (strpos($_SERVER['PHP_SELF'], 'faq.php, faq1.php, faq2.php, faq3.php')) echo 'class="active"';?>>FAQ</a>
<ul>
<li>FAQ1</li>
<li>FAQ2</li>
<li>FAQ3</li>
</ul>
</li>
<li><a href="contact.php" id ="connav" <?php if (strpos($_SERVER['PHP_SELF'], 'contact.php')) echo 'class="active"';?>>contact us</a></li>
</ul>
Can I please get some help on how I should be writing this line to let it work the way the others are?
<li>
<a href="faq.php" id ="faqnav"
<?php
if (strpos($_SERVER['PHP_SELF'], 'faq.php, faq1.php, faq2.php, faq3.php'))
echo 'class="active"';
?>
>FAQ</a>
</li>
strpos() only accepts one string per parameter, you can not give it a list.
Try this:
<?php if (in_array(basename($_SERVER['PHP_SELF']), array('faq.php', 'faq1.php', 'faq2.php', 'faq3.php'))) echo 'class="active"';?>
basename() strips the path from the filename, so you only have the pure file name
in_array() then checks if this path is in an array
array() generates an array of strings to be handed over to in_array(). Note that there are 4 separate strings, not one long one as in your code.
Use in_array for this purpose:
if (in_array($_SERVER['PHP_SELF'], array('faq.php', 'faq1.php', 'faq2.php', 'faq3.php')) echo 'class="active"';
http://php.net/manual/de/function.in-array.php
If you don't have any other pages that contain faq, you can simply use:
if (strpos($_SERVER['PHP_SELF'], 'faq') !== false)
Note that I am using !== false as strpos can return 0 when faq is found at the beginning of your string. You should probably use that for your other comparisons too.
Otherwise, go with the in_array solution of #MrTweek.
Im just learning open cart, but I think this question could be answered by anyone with good php knowledge.
I am simply attempting to highlight the a link when only on that page, but it doesnt seem to work
<?php $tickets = 'index.php?route=product/category&path=600'; ?>
<ul>
<li>Limerick FC</li>
<li><a href="<?php echo $tickets; ?>" <?php
if (strpos($_SERVER['PHP_SELF'], $tickets )) echo "class=\"current\" ";
?> > Tickets </a></li>
<li>Shop</li>
</ul>
I know the variable $tickets is fine because the link goes to where its supposed to go, and I know the class current is fine because it works for the third li which is shop.
Am I using strpos correctly?
I think you should use basename($_SERVER['REQUEST_URI']);.
<a href="<?php echo $tickets; ?>" <?php echo (basename($_SERVER['REQUEST_URI']) == $tickets) ? '"class=\"current\"' : ""; ?>>Tickets</a>
it would be more better if you declare basename($_SERVER['REQUEST_URI']) in variable.
strpos() returns false if the string matches at char 0 - which the above does.
Use indentical comparisons === for a true outcome.
As a note, i've used substr_count() in the past for similar circumstances without needing identical comparison!
I have a small php website that has a menu that is included via include_once. I need an HTML class added to the current menu item for each page.
So if a user clicks on a link and goes to that page the new page will load with the new menu item with class="current". How can I go about doing this?
Let's say you write your menu like this:
<ul>
<li> Link1 </li>
<li> Link2 </li>
<li> Link3 </li>
</ul>
Here is a good old php4 style solution :-p
<?php
//you get which link was clicked
if(isset($_GET['menu']) $menu = $_GET['menu'];
else $menu = 1;
$1 = $2 = $3 = ""; //you create 3 empty strings
switch($menu){ //you assign the correct string with your css class name
case "1": $1 = 'class="current"';break;
case "2": $2 = 'class="current"';break;
case "3": $3 = 'class="current"';break;
}
?>
//echo the variables into the menu anchors ( <?=$1?> is equivalent to <? echo $1; ?> )
<ul>
<li><a href="link1.com?menu=1" <?=$1?> >Link1</a></li>
<li><a href="link2.com?menu=2" <?=$2?> >Link2</a></li>
<li><a href="link3.com?menu=3" <?=$3?> >Link3</a></li>
</ul>
You can also place the <?=$1?> into the <li> or anywhere else wanted...
If you're using javascript in your project, you could also give an id to your anchors (like Link1), get the menu value like above with $_GET, and then use javascript to add the class to the desired link.
I gave you this answer because from what you're writing I guess you're not using any PHP framework but coding you app the old way... there's plenty of nice PHP framework around here that will have pre-made solution for this... might be hard at the beginning but it's worth it...
Good luck!
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
What's the most elegant templating (preferably in pure PHP!) solution you've seen?
Specifically i'm interested in handling:
Detecting in a repeating block whether it's the first or last element
Easy handling of odd/even cases, like a zebra striped table, or similar
Other modulos logic, where you'd do something every n'th time.
I'm looking for something that makes this less of a pain:
<?php
$persons = array('John', 'Jack', 'Jill', 'Jason');
?>
<?php $i = 0; ?>
<?php if (isset($persons)): ?>
<ul>
<?php foreach ($persons as $name): ?>
<li class="<?= ($i++ % 2 === 0) ? 'odd' : 'even' ?>"><?= $name ?></li>
<?php endforeach ?>
</ul>
<?php endif ?>
Does it really take the mess above to create something like this below?
<ul>
<li class="odd">John</li>
<li class="even">Jack</li>
<li class="odd">Jill</li>
<li class="even">Jason</li>
</ul>
Is it only me that find the above near hideous?
All those starting and closing of php-tags makes me cringe.
You don't need to open the tags more than once. You can also make a function out of it if you do the same thing multiple times:
<?php
function makeul($items, $classes) {
$c = count($classes);
$out = "";
if (isset($items) && count($items) > 0) {
$out = "<ul>\n";
foreach ($items as $item) {
$out .= "\t<li class=\"" . $classes[$i++%$c] . "\">$item</li>\n";
}
$out .= "</ul>\n";
}
return $out;
}
?>
other page content
<?php
$persons = array('John', 'Jack', 'Jill', 'Jason');
$classes = array('odd', 'even');
print makeul($persons, $classes);
?>
Also, if you don't mind using Javascript, Jquery makes things done mod 2 pretty easy (e.g., for zebra striping a table):
$("tr:odd").addClass("odd");
$("tr:even").addClass("even");
Tiny But Strong
www.tinybutstrong.com
It doesn't make the smarty mistake of embedding another macro language in the page, but does allow you to handle every practical web display issue I've ever thrown at it. In particular the above odd/even constructs are a doddle. For something like your code selecting from a database table
In the PHP file
$TBS->MergeBlock('blk1',$sqlconnect, "SELECT name from people ");
And in the HTML file
<ul>
<li class="odd">[blk.name;block=ul]</li>
<li class="even">[blk.name;block=ul]</li>
</ul>
And that's it. Notice that the HTML is completely Dreamweaver compatible. Furthermore if I wanted to make that alternate over three line styles all I'd need to do is add the extra line, maybe with different classes, so
<ul>
<li class="linestyle1">[blk.name;block=ul]</li>
<li class="linestyle2">[blk.name;block=ul]</li>
<li class="linestyle3">[blk.name;block=ul]</li>
</ul>
A small help on the looping:
<? $b=false; foreach($MyList as $name) { ?>
<li class="row<?= $b=!$b ?>"><?= htmlspecialchars($name); ?></li>
<? } ?>
By saying $b=!$b, it automatically alternates between true and false. Since false prints as "", and true prints as "1", then by defining css classes row and row1, you can get your altering rows without any trouble.
consider using :first-child css to style the first one differently.
It ain't pure PHP (the templating syntax then), but it works realy nice; Smarty.
For loops you can do:
<ul>
{foreach from=$var name=loop item=test}
{if $smarty.foreach.loop.first}<li>This is the first item</li>{/if}
<li class="{cycle values="odd,even"}">{$var.name}</li>
{if $smarty.foreach.loop.last}<li>This was the last item</li>{/if}
{/foreach}
</ul>
have you considered phptal?. one main benefit of it (or something similar) is that you get templates which can pass validation. most php template engines seem to ignore this.
I use PHPTAL for templating because it is written in 100% actual HTML with placeholder data, so it even works in a WYSIWYG editor for a web designer. That and it's just way easy to understand.
Here's what it would look like for me. Please forgive the markup, I'm new here and the four spaces block wasn't working right for me (the list was a list, not the markup).
PHP Code:
$tal = new PHPTAL;
$tal->setTemplate('people.htm')
->set('people', array('John', 'Jack', 'Jill', 'Jason'));
echo $tal->execute();
Template:
<ul>
<li tal:repeat="person people" tal:content="person">John Doe</li>
</ul>
Output:
JohnJackJillJason
Now obviously I wouldn't make a template for this little, but I could use a macro for it or build a whole page and include that variable. But you get the idea. Using PHPTAL has just about tripled my speed at templating and programming, just by the simplicity (no new syntax to learn like smarty).
How's about XSLT? The only template system that has a standards body behind it. Works the same across programming languages. Learn it once, use it everywhere!
Symfony Components: Templating
(source: symfony-project.org)
Symfony intends on moving to a new templating system based on the lightweight PHP templating system twig.
The lead developer Fabien Potencier, explains the decision here: http://fabien.potencier.org/article/35/templating-engines-in-php-follow-up
Symfony can usually be replied upon to make very informed decisions on such matters, so this framework should be something to look into.
The component is here: http://components.symfony-project.org/templating/
I've used Smarty Template Engine in the past. It's Pretty solid. And as you can probably tell from the website; it has quite the large user-base and is updated regularly.
It's in pure PHP as well.
Savant is a lightweight, pure PHP templating engine. Version 2 has a cycle plugin similar to the Smarty one mentioned earlier. I haven't been able to find a reference to the same plugin in version 3, but I'm sure you could write it fairly easily.
If is just to apply a CSS style, why don't you use the :nth-of-type(odd) selector.
For example:
li:nth-of-type(odd) {
background: #f2f6f8;
background: linear-gradient(top, #f2f6f8 0%, #e0eff9 100%);
}
http://jsfiddle.net/melonangie/nU7qK/enter code here
I use Modulo like you did in your example all the time.
If what cringes you is the opening and closing tags, write a function that creates the html string and then have it return it. At least it will save you some tags.
I have been a fan of HAML for quite a while, it looks like PHP folk have HAML now: see http://phphaml.sourceforge.net/
<?= ($i++ % 2 === 0) ? 'odd' : 'even' ?>
You're doing it the other way around. Your first item is now called even instead of odd. Use ++$i.
I'm having the same problem. But I think your original solution is the neatest. So I'll go with that.
I created a simple templating system in PHP to solve this problem a while ago:
http://code.google.com/p/templatephp/
It takes a multidimensional array, and requires the addition of some extra tags to the HMTL to create the combined template.
It's not as complicated (albeit powerful) as Smarty and some other solutons, but wins out in simplicity a lot of the time. A demo of the menu creation:
<p>Main Menu</p>
<ul>
{block:menu_items}
<li>{var:name}</li>
{/block:menu_items}
</ul>
Merged with...
array (
'menu_items' => array (
array (
'link' => 'home.htm',
'name' => 'Home'
),
array (
'link' => 'about.htm',
'name' => 'About Us'
),
array (
'link' => 'portfolio.htm',
'name' => 'Portfolio'
),
array (
'link' => 'contact.htm',
'name' => 'Contact Us'
)
)
);
Will create the menu...
<p>Main Menu</p>
<ul>
<li>Home</li>
<li>About Us</li>
<li>Portfolio</li>
<li>Contact Us</li>
</ul>
<?php
define ('CRLF', "\r\n");
$persons = array('John', 'Jack', 'Jill', 'Jason');
$color = 'white'; // Init $color for striped list
$ho = '<UL>' . CRLF; // Start HTML Output variable
foreach ($persons as $name)
{
$ho .= ' <li class="' . $color . '">' . $name . '</li>' . CRLF;
$color = ($color == 'white') ? 'grey' : 'white'; // if white, make it grey else white
}
$ho .= '</ul>' . CRLF;
echo $ho;
?>