5

I have a basic understanding of PHP, but I feel like what I am trying to do could by done in a much simpler way. I am using PHP to display HTML content for a Wordpress theme. I want users to be able to determine the order in which HTML "blocks" are displayed. Currently I am using an if/elseif setup. Here is an overly simplified example:

if ( $layout == 'layout_one' ) {
   echo '<div class="header">Header</div>';
   echo '<div class="content">Content</div>';
   echo '<div class="footer">Footer</div>';
} elseif ( $layout == 'layout_two' ) {
   echo '<div class="content">Content</div>';
   echo '<div class="header">Header</div>';
   echo '<div class="footer">Footer</div>';
} elseif ( $layout == 'layout_three' ) {
   echo '<div class="footer">footer</div>';
   echo '<div class="header">Header</div>';
   echo '<div class="content">Content</div>';
}

Now, this technique becomes an absolute bear due to the shear number of layout options (permutations). So in my mind you would write a separate function for each HTML content block, and then in some way have another function that presents them in the order specified by the user. Or maybe putting all the blocks into an array and then reordering the array based on the layout selection...

Anyway, I have hit a wall on how to actually do this. Any guidance would be greatly appreciated. Thanks

2
  • The general approach (prepare the block content, then order the blocks) seems reasonable. What is the problem--you don't know how to write the functions to prepare the block contents? Or you're not sure whether it would be better to use an if/else loop or something else? Commented Aug 23, 2014 at 15:01
  • Another quick comment -- if you have a bewildering selection of different layouts to deal with in your code, the users may also find the number of different layout choices bewildering too. Commented Aug 23, 2014 at 15:02

4 Answers 4

6

This is not a trivial question; as the number of layout parts grows, it becomes more and more difficult to maintain. However I'm going to try to provide a "simple" solution for this.

Let's assume you have 3 parts, as in your example. However this should work for N parts. You set them in an array:

$parts = [
  0 => '<div class="header">Header</div>',
  1 => '<div class="content">Content</div>',
  2 => '<div class="footer">Footer</div>'
  ]

Then you want the combinations in a deterministic way. This is what I came up with, although I'm sure there's some algorithm to do all possible combinations (one example of an algorithm) so this step is automatic:

$layout_combinations = [
  0 => [0, 1, 2],
  1 => [0, 2, 1],
  2 => [1, 0, 2],
  3 => [1, 2, 0],
  4 => [2, 0, 1],
  5 => [2, 1, 0]
  ];

Do you really have $layout == 'layout_one'? We'll have to convert it:

$layout_number = [
  'layout_one'   => 0,
  'layout_two'   => 1,
  'layout_three' => 2,
  'layout_four'  => 3,
  'layout_five'  => 4,
  'layout_six'   => 5
  ];

To use it, after defining the parts above, simply do:

$layout = 'layout_four';

if (!array_key($layout, $layout_number))
  throw new Exception('Invalid layout');

$layout_number = $layout_number[$layout];

$layout_structure = $layout_combinations[$layout_number];

foreach ($layout_structure as $part_number) {
  echo $parts[$part_number];
  }

The main advantage is that it's very easily extensible. If you want to put another part, simply add it to the $parts array, add the corresponding new $layout_combinations and to the "english => number" conversion.

Note: a step could be prevented if $layout = 4 instead of $layout = 'layout_four'. This is highly preferable since it allow you to make it automatic, simply adding an element at the end of your $parts array.

Sign up to request clarification or add additional context in comments.

6 Comments

This is really nice! Maybe ndiego should think about making it even simpler: No need for the $layout_number array, he should use integers as layout_numbers. For example: $layout = 1 instead of $layout = 'layout_one'. Then he does not need the array layout_number anymore. What do you think about that?
I completely agree, I just added a note. It makes the process of adding a new part to the layout as simple as adding a new element in $parts (:
This is exactly what I was thinking! Thank you so much. I was just having trouble putting it all together. And yea, I like your ideas for simplifying the process. Thanks again!
This is probably overcomplicating things -- you could generate the different combinations and layout numbers programmatically.
Thanks @girlwithglasses, I noted it in I'm sure there's some algorithm to do the same so it doesn't become difficult to maintain for N > 3 and I was hoping for the $layout to be able to be a number from the beginning by changing some previous code from the OP, so no need for that step also.
|
2

What about this:

<?php
$h = '<div class="header">Header</div>';
$c = '<div class="content">Content</div>';
$f = '<div class="footer">Footer</div>';

if ($layout == 'layout_one') {
    echo $h.$c.$f;
} elseif($layout == 'layout_two') {
    echo $c.$h.$f;
} elseif($layout == 'layout_three') {
    echo $f.$h.$c;
}

Comments

2

Create an identifier for each layout that dictates the order of the components, e.g. h_c_f means header, content, footer, and c_f_h is content, footer, header.

Store the contents of your sections in an array indexed by the appropriate letter:

$section_stuff = array(
   'h' => '<div>Header</div>',
   'c' => '<div>Contents</div>',
   'f' => '<div>Footer</div>',
);

Assemble your output using the layout identifier to work out the order:

// $order is the layout name, e.g. c_f_h, f_c_h, etc.
// split $order by "_" to get the appropriate order

$ordered = explode( '_', $order );
foreach ($ordered as $section) {
    echo $section_stuff[$section];
}

Obviously you'd need to add in error checking, etc.

The advantage with this method is that you could use something like a drag-and-drop interface to set up the order of the sections; the identifier name dictates the layout, rather than being an arbitrary value.

If you want to generate all the possible layouts in advance, the PHP cookbook has some suitable suggestions.

Comments

1

Switch case can be used to instead of long elseif conditions. Because switch is efficient than elseif and will support large amount of condition. The exact replacement of your code will be like follows for switch.

switch ($layout) {
    case 'layout_one':

        echo '<div class="header">Header</div>';
        echo '<div class="content">Content</div>';
        echo '<div class="footer">Footer</div>';

        break;
    case 'layout_two':

        echo '<div class="content">Content</div>';
        echo '<div class="header">Header</div>';
        echo '<div class="footer">Footer</div>';

        break;
    case 'layout_three':

        echo '<div class="footer">footer</div>';
        echo '<div class="header">Header</div>';
        echo '<div class="content">Content</div>';

        break;
}

additionally a tricky work cane done by php include function. You can create template as php file with the same name used on the if statement and use the variable in include statement. Sample code would be like follows.

include("/path_to/layout/".$layout.".php");

Sample HTML layout will be like follows with related names.

layout_one.php

<div class="header">Header</div>
<div class="content">Content</div>
<div class="footer">Footer</div>

1 Comment

Yeah, but I will still have to replicate the order manually for each case. Maybe there is no way around the replication...hmmmm

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.