How to speed up a wordpress function with multiple loops?

Customizing a Wordpress function

  • Wordpress/PHP question. I'm working on a Wordpress theme and want to use an algorithm to alter some of the HTML it emits. I've got a general idea of how to do this, and could probably manage a brutish implementation on my own, but my PHP-fu is weak and there is probably a better way. Here's what's going on. I'm using the http://code.google.com/p/blueprintcss/ approach for a gridded layout. And I've got a "bottom-bar" of widgets, laid out in three columns. With blueprint css, the div for the third column needs class="last" added to it in (in addition to class declarations that apply to all divs) order for everything to line up right. What I want to do is get the count of widgets each time a widget is emitted, and if count mod 3 = 0, insert 'last' into the class. Barring that, if I could insert class="widget-N" (where N=count) in all divs, I could manage, although it would be less elegant. Ideally, all browsers would magically support CSS3 and obviate this problem, but I'm not holding my breath. Obviously I don't want to touch the core code. I don't mind inserting an altered version of whatever function is necessary into my functions.php file; but if there's a callback that lets me avoid doing that, so much the better.

  • Answer:

    blah, that last line should read$params[0]['before_widget'].=($count%3)?' last':'';

adamrice at Ask.Metafilter.Com Visit the source

Was this solution helpful to you?

Other answers

for ( $i = 0; $i { $last = ($i % 3) ? '' : 'last'; echo "class=\"widget $last\""; } Should do it. No idea where to stick it, though.>

Leon

Stupid brackets. Lets try this. The important linea are the one with the ? and the echo, anyway. for ( $i = 0; $i < sizeof( $widgets ); $i++ ) { $last = ($i % 3) ? '' : 'last'; echo "class=\"widget $last\""; } Should do it. No idea where to stick it, though.

Leon

Yeah, it's the "knowing where to stick it" part that gets me too. I could manage the function.

adamrice

I'm not sure what you're going for leon, your code would just print out: class="widget "class="widget "class="widget last"class="widget "class="widget "class="widget last"class="widget "class="widget "class="widget last"class="widget "class="widget "class="widget last" Which doesn't seem very helpful. PHP has a http://us3.php.net/dom you can use to manipulate HTML the same way you can in javascript, but unlike Javascript, you have to load the HTML and then manipulate it as a string, rather then modifying the DOM from 'inside' the page. But you could do something like creating a new PHP page that loads your wordpress blog in the background (using http://us3.php.net/fopen), modifies it using the DOM, and then sends the results to the browser. That has a bonus of not needing to modify any of the wordpress code.

delmoi

When you register your sidebars in the functions.php file of your theme, you can choose to create unique IDs for each widget (see here: http://automattic.com/code/widgets/api/) example code:'before_widget' => '<li id="%1$s" class="widget %2$s">','after_widget' => "</li>n",'before_title' => '<h2 class="widgettitle">','after_title' => "</h2>n"so if your layout only supports a maximum of 3 widgets to float in your bottom bar, you can write your function so that the third widget always is set to clear:both, and widgets 1 and 2 only do if there are not 3 widgets selected. This is, as you mention, less elegant, but keeps most of the functionality in the style sheet as opposed to mucking about with hooks (tho there may be a hook for the end of a sidebar, I'd look into that as well...)

annathea

Ok, this is majorly evil because it hacks wordpress core and isn't going to allow you to upgrade, but I don't have time to work up a hack using the before_widget callback ... My testing is limited, so this might not be 100%, but you should see how to get it to work. change line 223 in widgets.php from: foreach ( $sidebars_widgets[$index] as $id ) {to:foreach ( $sidebars_widgets[$index] as $count=>$id ) {Then, add on after line 237 (right after $classname_ = ltrim($classname_, '_');):$classname_.=$count%3?' last':''; //note space in front of ' last' That should do it. Can I say again this is TOTALLY evil and that you shouldn't use it because you're going to screw up your upgrade path? Additionally, it doesn't handle cases where you don't have a number of widgets exactly divisible by 3. I'm not sure what the correct solution is but there is probably a way for a widget to get its ordering from the hook system and thus add a plugin that handles the classname logic. In fact, even if it doesn't send a count, you could keep your own count in a separate plug (using a static var) and do it. So do that. oh psh, i just saw "Obviously I don't want to touch the core code.". Good choice. well, looks like you're using the 'dynamic_sidebar_params' filter callback to do something similar. Actually, if you're not writing a template for general consumption, I would probably prefer the annathea method, because your widget order is likely to be pretty static. Just give the 'last' behavior to the last element in each row. Lots faster than mucking about with plugins and a lot nicer than altering core.

fishfucker

fishfucker is going down the same path I've been going down. I've created a customized version of the dynamic_sidebar function, doing almost exactly what he describes, and stuck that in functions.php (I've also realized the situation could be further complicated by the fact that I'm using two sidebars, and only want to mung the widgets in one of them). Also, fwiw, the layout works fine even if the last widget is not exactly divisible by 3. What annathea describes happens by default. If this theme were only for my own consumption, I'd probably content myself with her method, but I'd like to make it publicly available. What delmoi describes sounds interesting, but I have no idea where to start with that. How would I intercept the PHP being emitted by WP? I also figured out a janky way of handling this problem in CSS with no PHP munging. I'm not thrilled with any of the options right now. It doesn't seem like there's an orthodox way to get the current widget count and to inject a value returned by an external function into the widget wrapper, which would be ideal. For the time being, I am going with the evil option.

adamrice

Seconding http://ask.metafilter.com/95376/Customizing-a-Wordpress-function#1392479. The Widgets API specifically includes register_sidebar() arguments for this purpose.

theiconoclast31

Messing with core code doesn't have to cut off your upgrade path if you use Subversion for your install. http://codex.wordpress.org/Installing/Updating_WordPress_with_Subversion. If you're not familiar with Subversion, it's a version control program that tracks changes to software source code. If you make changes in your installation, Subversion will allow you to merge your changes in with any changes made by WordPress. I use Subversion for my WordPress and MediaWiki installations, and it works great. Even if you don't have command-line access to your server, you can install a Subversion client on your local machine, manage your changes there, and then upload your finished files.

expialidocious

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.