How Do I Retain Output Indentation? - php

I have some PHP code like the following (simplified):
<ul>
<?php
for ($Index = 1; $Index <= 10; $Index++)
{
echo("<li>" . $Index . "</li>\n");
}
?>
</ul>
The problem is that for all lines after the first, the output is without indentation. I want to keep my code neat, so I'd like all the <li> elements to be aligned properly.
I tried outputting tabs before each element with \t, but then the first line is indented more than intended. Outputting the tab after the element means the trailing </ul>'s placement will be messed up.
\r does not work at all.
Are there any tricks to keeping output properly formatted, or do I have to live with messy code?

The first line is more indented than you want it to be because of the extra whitespace at the beginning of this line:
<?php
Since that white space is outside the PHP tags, it is output directly. But because it is outside the PHP tags, it is not included in the loop, and will only affect the first line.
You could do this to help avoid it:
<ul>
<?php
for ($Index = 1; $Index <= 10; $Index++) {
echo "\n <li>$Index</li>";
}
?>
</ul>
...and align the <?php ?> tags at the beginning of the lines, or you could do this:
<ul><?php for ($Index = 1; $Index <= 10; $Index++) { ?>
<li><?php echo $Index; ?></li>
<?php } ?></ul>
...but as ridiculous as it seems, this:
<ul><?php for ($Index = 1; $Index <= 10; $Index++) echo "\n <li>$Index</li>"; ?>
</ul>
...is probably the best way to acheive what you are talking about leaving the least room for ambiguity (different PHP versions seem to handle this slightly differently - for instance in PHP 4.3.10 at least, there is an implicit line break after a ?> tag which does not exist in PHP 5 (I think this may have been a bug). That is one of the reasons I don't use mixed HTML and PHP (although I know many people disagree with me on this point) but what I would rather do is this:
<?php
$out = "<ul>\n";
for ($Index = 1; $Index <= 10; $Index++) $out .= " <li>$Index</li>\n";
$out .= "</ul>";
echo $out;
?>

Use spaces. " " * 8, 16, 20, etc...
Or still use \t in your php, then at the very end echo it all out after replacing \t with spaces ,
echo preg_replace('/^\t/', '4_SPACES_HERE', $output_html);

Related

More elegant solution to this nested loop, anyone?

I have a php procedure that scans a directory where its content is thumbnail images of pdf files. The thumbnails are then displayed in a table, and included in an iframe of a parent web page. Each thumbnail is itself a hyperlink when clicked will open the actual pdf file. To avoid having a horizontal scroll bar, 9 images in a table row is perfect. I wrote a nested loop that in effect acts like a word wrap, where it displays 9 images and then begins another row. The actual code is much more entailed, so I have it pared down to a bare minimum example. It seems almost counter intuitive on first glance, decrementing $i on the second line of the outer loop, but it works. I wonder if anyone has a more elegant solution?
$ary = array(1,2,3,4,5,6,7,8,9,10);
for ($i=1; $i<(count($ary)+1); $i++) {
$i = $i-1;
for($j=0; $j<9; $j++) {
if ($i === count($ary)) break;
echo ($ary[$i].", ");
$i+=1;
}
echo "<br>";
}
The completed code now where $ndx is the count of the array, $dir is the scanned directory containing the png images, and $rtDir is the directory where the pdf's are saved:
if ($ndx > 0) {
$tbl = '<div id="draggable" class="ui-widget-content">
<ul>
<table><tr>';
/* place 9 images on one row */
foreach ($myfiles as $index => $image) {
$pdf = basename($image, ".png");
$pdf = $pdf . ".pdf";
$pdf = $rtDir.$pdf;
$tbl .= '<td>
<span class="zoom">
<a href="'.$pdf.'" target="_blank">
<li><img id="pdfthumb'.$index.'" class="myPhotos" alt="pdf'.$index.'" src="'.$dir.$image.'" ></li>
</a>
</span>
</td>';
if ($index % 9 == 8) {
/* end the current row and start a new one */
$tbl.= "</tr></table><br><br><table style='margin-top:-40px'><tr>";
}
}
$tbl .= "</tr></table></ul></div>";
printf($tbl);
unset($myfiles);
}
Thanks everyone for your suggestions.
So you want 9 images on each row? There are usually two logical choices:
Alternative 1: You use array_chunk(), e.g. like this:
$chunks = array_chunk($images, 9);
foreach ($chunks as $chunk) {
foreach ($chunk as $image) {
// image printing goes here
}
echo '<br'>;
}
Alternative 2: You use the modulo operator, e.g. like this:
foreach ($images as $index => $image) {
// images printing goes here
if ($index % 9 == 0) { // or 8, since it's a 0-index array... I don't remember
echo '<br>';
}
}
I mostly use the second version, myself, if I have to - or I ask one of our designers to make it fit to a proper width through css. Do note also that the second version won't work if your images array is associative.
$b = count( $ary ) - 1 ;
for( $i = 0 ; $i <= $b ; $i++ ) :
echo $ary[$i] ;
if( ( $i + 1 ) % 9 == 0 ) :
echo "<br>" ;
endif ;
endfor ;
like the above comment i like modulus but i also prefer the for loop, hope this helps.

PHP strpos does not locate "<"

I am encountering a rather peculiar behavior of PHP's strpos() function. I need to loop through a string of keywords and output URLs to each keyword..
Lets take the following example string :
$elementText = "Bluffs, Cliffs, Grasses, Oceans, Rocks < Materials";
And here is the function:
<?php
$i = 0;
$hierarchySeparator = " < ";
$subjects = explode(", ", $elementText);
// loop through keywords
foreach ($subjects as $subject) :
// look for hierarchical keywords
$found = strpos($subject, $hierarchySeparator);
if($found !== false) :
// extract and loop through hierarchical list
$subSubjects = explode($hierarchySeparator, $subject);
$j = 1;
foreach ($subSubjects as $subSubject) : ?>
<?php echo $subSubject; ?>
<?php
// Re-ouput all relevant < signs
if($j < count($subSubjects)) {
echo " < ";
}
$j++;
endforeach;
else : ?>
<?php echo $subject; ?>
<?php endif;
// output commas to "nicefy" list output
$i++;
if($i < count($subjects)) {
echo ",";
}
endforeach; ?>
However, on my server, PHP fails to detect the "<" symbol, therefor does not separate the hierarchical keywords correctly. Even when I try to explode using < as a delimiter, it does not work.
The odd thing is that I can create a test file and run it manually from command line, which executes exactly as desired, but when I try to run it on my server it does not.
Any idea on how to get this resolved?
Are you sure it's really a < in there, and not something like <? Remember that your browser will essentially "lie" to you, if it's rendering html.
e.g.
php > var_dump(strpos('Rocks < Materials', ' < '));
int(5)
php > var_dump(strpos('Rocks &lgt; Materials', ' < '));
bool(false)
php > var_dump(strpos('Rocks < Materials', ' < '));
bool(false)

using php to add classes to li then alternate after every third item?

this may be stupidly simple but I'm trying to figure out a way to add a class to an unordered list, then alternate that class after every third item..
I've only mananged to add a class on every third item (which is not what I want), but here's my code:
<?php $i=1; foreach($this->items as $item) : ?>
<li class="<?php if ($i % 3 == 0) : ?>odd<?php endif; ?>">xxx</li>
<?php $i++; endforeach; ?>
Which spits out:
<li class="">xxx</li>
<li class="">xxx</li>
<li class="odd">xxx</li>
<li class="">xxx</li>
<li class="">xxx</li>
<li class="odd">xxx</li>
But what I'm hoping to get is:
<li class="odd">xxx</li>
<li class="odd">xxx</li>
<li class="odd">xxx</li>
<li class="even">xxx</li>
<li class="even">xxx</li>
<li class="even">xxx</li>
and so forth.. Normally I'd use jquery to do something like this, but I have to use php in this case.. Any help would be greatly appreciated :)
Use a boolean flag which is flipped (negated) every time $i % 3 == 0:
// Start with 0 instead of 1
$i=0;
// Flag starts TRUE
$state = TRUE;
foreach ($this->items as $item) {
if ($i % 3 === 0) {
// Flip to opposite state
$state = !$state;
}
?>
<li class="<?php if ($state) : ?>odd<?php else: ?>even<?php endif; ?>">xxx</li>
<?php
$i++;
}
Here is a demonstration. Though you'll need to inspect the output to see the classes change.
You're using the wrong operator.
if ($i % 3 == 0)
means "If the remainder of $i divided by 3 is 0".
What you want is
if (floor($i/3) == 0).
Give it a try and see how it goes.
EDIT: You also seem to be missing the 'else' code. If you don't have that, it won't write 'even' for the non-'odd' classes.
EDIT EDIT: If you want the pattern to continue, use:
if ((floor($i/3) % 2) == 0).
I assume you want the 7th item to be "odd"? I wrote JavaScript, but should easily convert to PHP
Demo
for (var i = 0; ​i < 15; i++) {
if(i%6 < 3) {
document.write("odd<br>");
}
else {
document.write("even<br>")
}
}​
Changing your code to:
<?php $i=0; foreach($this->items as $item) : ?>
<li class="<?php if ($i % 6 < 3) : ?>odd<?php else: ?>even<?php endif; ?>">xxx</li>
<?php $i++; endforeach; ?>
Another way to do this is to use the new CSS3 selectors that allow you to target odd and even childs.
Here is a link with an example. Basically, you'd have your list just as normal.
<ul>
<li></li>
<li></li>
</ul>
Then rather than having a class called odd and even with the different styles, you can use the new selectors like this...
li:nth-child(even) { background: #fff; }
li:nth-child(odd) { background:#000; }
This will make all even list items have a background of #fff and all odd list items with a background of #000.
Edit: You can use a couple other CSS3 selectors to only target the even and odds after the first two using 1st-child and 2nd-child.
The reason you are only printing every three iterations of your loop is that you are using the modulus operator "%" to test if i is divisible by three ($i % 3 == 0). This results in only printing when $i is divisible by 3.
To solve your problem:
<?php
$odd = "<li class='odd'>";
$even = "<li class='even'>";
$i = 0;
foreach($this->items as $item)
{
if($i < 3)
echo $odd . $item . "</li>";
else if($i >= 3)
echo $even . $item . "</li>";
$i++;
if($i > 5)
$i = 0;
}
?>
Note that since $i begins at 0, the first 3 items will be indexed 0 - 2, and the subsequent 3 will be indexed 3 - 5.
Try nesting a for each loop within a for loop. With the outer loop telling how many times to iterate and the inner loops telling how many times to put odd and even.

How to print php info inside <a> tags, etc?

Is there a way to print php variables inside a HTML tag?
Like this:
<?php
for ($e = 1; $e <= 30; $e++) {
for ($i = 1; $i <= 40; $i++) {
print ('<div id="map"><a>$i</a></div>'); // <----I'm adding the divs here, but I want to add a text inside each of them
}
}
?>
Your call:
echo ''.$title.'';
or
echo "<a href='$href'>$title</a>";
or
<?= $title ?>
I prefer the first one, because I think it is the most readable. But it is up to you.
Using your example:
print ('<div id="map"><a>'.$i.'</a></div>');
or
print ("<div id=\"map\"><a>$i</a></div>"); // note the double quotes to allow PHP to parse the string
or
<div id="map"><a><?= $i ?></a></div> // but you really should do this!
To better clarify you SHOULD NEVER rely on short tags (the last option). Every time you do that god will kill a kitten and abuse a unicorn.
In this case take the variable out of the string and concatenate it inside.
print ('<div id="map"><a>'.$i.'</a></div>');
This is pretty basic stuff so I suggest you go through some tutorials or read the manual again.
I'm not sure what text you want to add there, you can have any other variables in there, same how you're printing the $i .. except that single quotes do not evaluate variables inside the string, only double quotes do ..
so:
$foo = "bar";
print "$foo" => "bar"
print '$foo' => "$foo"
You're using single quotes to output your variable. using double quotes may work instead, but I prefer using string concatenation(. operator)
print ("<div id=\"map\"><a>$i</a></div>");
Or
print ('<div id="map"><a>' . $i . '</a></div>');
Use " instead of ' when you want to use variables in a string.
<a href='<?php echo "http://www.stackoverflow.com"; ?>' target='_blank'>test</a> (Syntax maybe off)
EDIT
<?php
for ($e = 1; $e <= 30; $e++) {
for ($i = 1; $i <= 40; $i++) {
print ('<div id="map"><a>'. $i .'</a></div>');
}
}
?>
Note the '. $i .' part.

What is wrong with my syntax here?

The goal is to count the number of paragraphs in a group of users text...
(I will assume its always bigger than 5 paragraphs for this exercise)
Then I want to 1/2 the number of paragraphs, round it down and enter some content(echo "yehhoo") in between.
I do understand the way I have gotten my $newvalue is not very good, would also like help on that...
<?php
$choppedup = explode("<p>",$node->field_long_body[0]['safe']);
$choppedpos = count($choppedup);
$choppedpos2 = $choppedpos/2;
$newvalue = floor($choppedpos2);
//I know this is working to here... the rest not so sure.
for($j = 0; $j < $choppedup; $j ++):
print $choppedup[$j];
if ($j == $newvalue):
echo "yehhoo" ;
endif;
endif;
?>
Thank you
for
...
endfor; # not endif
your $newvalue calculation is not terrible, for the array iteration I'd rather suggest foreach loop (using curly braces):
foreach($choppedup as $ind => $p) {
echo $p;
if ($ind == $newvalue) {
echo 'yehoo';
}
}
"Yehhoo" for curly brackets!
for($j == 0; $j < $choppedup; $j ++) {
print $choppedup[$j];
if ($j == $newvalue) {
echo "yehhoo";
}
}
Why do such a complex loop to count the number of paragraph tags?
You can do something like this:
$sInput = '<p>Hello World</p><p>What is going on</p><p>Blah</p>';
if(preg_match_all('/<p>/', $sInput, $arMatches)!==false)
print count($arMatches[0]) . ' paragraphs<br/>';
Of course the above needs some work to make sure there are text between the paragraph tags, but this should work for you need.

Categories