OK.

I have a very long and pretty complicated function.

It looks almost like this one:

    <?php
            function hello() {

                    echo 'My Function!' ?>
                    <ul>
                    <li> Blablabla </li>
                    <ul>
                    (...)
    <?php } ?>

The HUGE problem here is that I'm UNABLE to echo anything.

My function HAVE to return it's contents instead of echoing or direct outputting (it has to be that way, it's a Wordpress shortcode and when I echo - the contents are getting displayed at the top of the page - ALWAYS, not in the place where I want them):

   <?php
                function hello() {

                        $output .= 'My Function!'; 
                        $output .= '<ul>';
                        $output .='<li> Blablabla </li>';
                        $output .='<ul>';
                        (...)

                        return $output;
         } ?>

I hope it's easy till now.

Now, the real problems are:

I have tons of direct input code like:

?> 

<div>
    <span>
        <p>Smth</p>
        <a>smth</a>
    </span>
</div>

<?php

Adding $output everywhere kills the nice paragraphs/whitespace and code is getting VERY HARD to read and understand (and all HTML elements are parts of variable now, so even my php editor is not treating them well and coloring them as PHP elements).

And another thing, I have tons of lines like this one:

<a href="<?php bloginfo('template_directory');  ?>/includes/php/timthumb.php?src=<?php echo $url; ?>&h=<?php if($items=="one") echo 320; elseif($items=="two") echo 230; elseif($items=="three") echo 180; elseif($items=="four") echo 130; ?>&w=<?php if($items=="one") echo 600; elseif($items=="two") echo 420; elseif($items=="three") echo 277; elseif($items=="four") echo 203; ?>" title="<?php the_title(); ?>" class="link">

(yes, this is a single line)

And I have absolutely no idea how to add such lines to $output.

$output .= '<a href="<?php bloginfo('template_directory');  ?>/includes/php/timthumb.php?src=<?php echo $url; ?>&h=<?php if($items=="one") echo 320; elseif($items=="two") echo 230; elseif($items=="three") echo 180; elseif($items=="four") echo 130; ?>&w=<?php if($items=="one") echo 600; elseif($items=="two") echo 420; elseif($items=="three") echo 277; elseif($items=="four") echo 203; ?>" title="<?php the_title(); ?>" class="link"> ';

Doesn't work of course (even with \'s before ' and ").

I believe there MUST be an easier way to attach all the code to return, but how? I've tried with ob_start(); before code and return ob_get_clean(); after, but it outputs shortcode name instead of contents.

share|improve this question

73% accept rate
3  
Your actual problem is not the lengthy explanation of where you can or cannot output, but actually your very first line, stating: "I have a very long and pretty complicated function." Functions should be short and easy to understand. They should do one thing. And they should be free from side-effects like echo'ing content. Try to describe what your function does in plain english. For every "and" make a new function and name it after what it does. Break down your code into small chunks. Once you have eliminate complexity, look at the sourcecode again. – Gordon Mar 1 '11 at 14:27
@Gordon you are right and you are not. All of my functions always do one thing. This one is Wordpress shortcode, it grabs set of items and displays them based on attributes. There are 10 attributes and around 10 if statements for each one. There's also while loop grabing posts etc. Breaking this to smaller functions looks pointless, since I have ~100 shortcodes, I will need approx. 10k separate functions for doing what they do. – anonymous Mar 1 '11 at 15:56
no offense, but that's just further proof that the design / wordpress is broken. – Gordon Mar 1 '11 at 15:59
@Gordon well, to be fair, the idea behind these Wordpress functions was to provide a "low-tech" scripting interface to people with little technical knowledge customizing their blog - the whole base of template functions is build that way, cf. the_loop(), the_title() etc... it's arguably still bad design, no question – Pekka Mar 22 '11 at 12:30
feedback

3 Answers

up vote 1 down vote accepted

I agree with symcbean, but this might be a more practical approach at integrating with Wordpress: if you now have a single function called hello( ) which displays HTML, you might want to consider renaming that function to hello_content( ) (or something similar) and replace the hello( ) function with the suggestion symcbean gave you:

function hello_content( ) {
   echo "foo";
}

function hello( ) {
   ob_start( );
   hello_content( );
   return ob_get_clean( );
}

That should fix your immediate issue.

share|improve this answer
this approach seems good, but my code is a little more complicated, every shortcode has it's attributes so it looks like hello( $atts) { <array of atts> my code }. When I use your code the attributes doesn't seem to work. But the rest is fine! Argh :( – anonymous Mar 1 '11 at 14:47
Well, it finally works! With small glitch: stackoverflow.com/questions/5161626/output-buffer-shows-1 – anonymous Mar 1 '11 at 23:23
feedback

Its very hard to imagine what the problem you are trying to solve here is - although I'm not familiar with wordpress. Can't you just call the function where the output is supposed to go?

You could use output buffering - use echo/print as usual but...

ob_start();
hello();
$output=ob_get_contents();
ob_end_clean();

But that doesn't solve the problem that you still need to send to the browser at the right place in the page - and if you can do:

print $output;

in the right place, then you can surely do:

hello();

in the same place.

share|improve this answer
there are shortcodes in Wordpress, when you write for example [hello] it will bring function hello(). The point is the shortcodes are processed before the whole page and everything in them that is not in "return" will be displayed at the top of the page. Always. So it's impossible to have any elements above or between them. I hope you get what I mean. I'm going to test the ob_start(); thing, will it work in MANY instances (of different and/or the same function?). – anonymous Mar 1 '11 at 14:16
2  
Hint: you can use $output = ob_get_clean();, which is a shorthand of $output = ob_get_contents(); ob_end_clean();. – binaryLV Mar 1 '11 at 14:18
feedback

PHP Heredoc syntax will keep things looking neat and tidy and you can return the output to a variable. As long as you don't require any constants it will work fine.

You use it in this fashion:

function bar() {
    $var = <<<EOV
    anything here
    anything there
EOV;

    return $var;
}
share|improve this answer
3  
There must be no whitespaces before EOV;, as "The closing identifier must begin in the first column of the line." (quote from manual) – binaryLV Mar 1 '11 at 14:20
ty, tidied up spacing. – Dunhamzzz Mar 1 '11 at 14:27
@Dunhamzzz, this gives me "Parse error: syntax error, unexpected T_SL", and the <<<EOV is red underlined in my editor. – anonymous Mar 1 '11 at 14:46
1  
@anonymous, check if there is any space or tab character after <<<EOV – binaryLV Mar 1 '11 at 14:52
@binaryLV right! Done. Now it shows 'Parse error: syntax error, unexpected ']', expecting T_STRING or T_VARIABLE or T_NUM_STRING'. Screenshot of the function - img5.imageshack.us/f/taxm.png (notice red underline and colors). When i change [] to [] with \ it says "unexpeceted $end" (in the last - echo get_taxonomy_list_html(our_porfolio_types); - line). – anonymous Mar 1 '11 at 15:10
show 1 more comment
feedback

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.