Inserting PHP code in a database display

Let’s start with an article on a static page (Animals.php) that includes another file (Test.php)…

require_once($BaseINC."/inc/Test.php");

Test.php includes some PHP code that relies on values defined in a third file, Values.php.

Everything works fine until I take the article out of Test.php and put it in a database, displaying it by echoing $Content. The PHP include no longer works.

I’ve learned that you can’t insert includes in databases, so now I’m trying to insert the include in the display.

This doesn’t work…

$BaseINC = '../../MySite';
$Content = str_replace('<p id="">', ''.require_once($BaseINC."/$MyPHP/inc/A/Test.php").'<p id="1">',     $Content);

There were several bugs, but I finally got it to replace the static contents (“Test”) of Test.php. However, it displayed “Test” at the top of the page, not in the article retrieved from my database. Strangely, it inserted a numeral one where “Test” is supposed to display.

I then learned how to use file_get_contents…’

file_get_contents($BaseINC."/inc/Test.php")

However, that only displays static content. Next, I learned how to parse the included file, like this:

file_get_contents("http://MySite/inc/Test.php")

It will now display echo values - but only if they’re defined on Test.php. Everything defined on Values.php has apparently been removed from the flow.

So what’s the trick? Is there a way to use str_replace to insert an include in database-derived content? If not, is there some other way of pulling dynamic code from other files into my display, with the echo values intact?

I should mention that Test.php is physically located on one website (MySite1), while the article I’m previewing is on another site. In fact, all my websites include files stored on MySite1. I’ve included thousands of files; I just haven’t figured out how to do it with a str_replace operation. Thanks.

One problem is that when I try to insert an include via str_replace, I get an error message that interprets the path as Test.php <div>, or something like that. In other words, it apparently doesn’t know where the include request ends. No problem - I just inserted a semi-colon after Test.php). But that throws a syntax error. So maybe all I need is to figure out how to indicate where my include request ends.

I am not sure I totally understand what you are trying to do. So this may or may not help.

The way I have this designed is when a page is called say the url is

I route section to a controller called section.con.php which would look like this


<?php
    /*
   *Code needed to get everything needed to build the actual view
  */
    $content = '/path/to/some/content.inc.php';
    require('/template.tpl.php');

then in template it would look like this


   <html>
   <body>
        <h1>heading</h1>
        <div><?php include($content);?></div>
   </body>
  </html>

By separating the pieces like this you can build the $content variable however you need to in the controller then pass just the path to the view.

Let me know if this helps or if I am headed in the wrong direction.

I think the string result from the two PHP files can be stored safely in your database by using the following function:



//===========================
function loadIntoMemory($fInclude)
{
  $result = NULL;
  
  ob_start();
    require $fInclude;
    $result = ob_get_contents();
  ob_end_clean();


  return $result;
}



Please supply typical Test.php and Values.php files for a more accurate and detailed solution.

Thanks for the tips. It will take me a while to try those out.

@ John_Bettong - One project I’m working on is a series of articles about various biology topics. Each page features a series index that features links to every article in that series (e.g. Mammal Series), along with links to other series (e.g. Plants, Reptiles). To make it work, I first derive some values from my database, particularly $PopTax (e.g. Life, Animal, Mammal, Plant) and $MyTopic (e.g. Homes, Morphology, Ecology).

Then I include a file that puts together a fairly elaborate project index based on these values. So if I visit MySite/topics/animal-behavior, it would display links to every articles (about a dozen) in the Animals series, links to the home pages of other series, and a list of all behavior articles (animals, mammals, fish, etc.).

It’s a big pile of code, but I pasted the whole thing below, just to give you an idea of what I’m working with. Hopefully, I can condense the code some day after I learn a few more PHP tricks. :wink:

Thanks.


switch($PopTax)
{
// PLANTS
 case 'Plant':
  // INNER SWITCH
  switch($MyTopic)
  {
   case 'Introduction':
   case 'Homes':
   case 'People':
   $Title2 = $Title;
   break;
   default:
   $Title2 = str_replace(''.$PopTax.' ', '', $Title);
   break;
  }
  // END INNER SWITCH
 break;
 
 case 'Flowering Plant':
 case 'Conifer':
  // INNER SWITCH
  switch($MyTopic)
  {
   case 'Introduction':
   case 'Homes':
   case 'People':
   $Title2 = $Title;
   break;
   default:
   $Title2 = str_replace(''.$PopTax.' ', '', $Title);
   break;
  }
  // END INNER SWITCH
 break;

// ANIMALS
 case 'Animal':
 case 'Vertebrate':
 case 'Human':
  // INNER SWITCH
  switch($MyTopic)
  {
   case 'Introduction':
   case 'Homes':
   case 'People':
   $Title2 = $Title;
   break;
   default:
   $Title2 = str_replace(''.$PopTax.' ', '', $Title);
   break;
  }
  // END INNER SWITCH
 break;

 case 'Mammal':
 case 'Bird':
 case 'Reptile':
 case 'Amphibian':
 case 'fish':
 case 'Arthropod':
 case 'Insect':
 case 'Mollusk':
  // INNER SWITCH
  switch($MyTopic)
  {
   case 'Introduction':
   case 'Homes':
   case 'People':
   $Title2 = $Title;
   break;
   default:
   $Title2 = str_replace(''.$PopTax.' ', '', $Title);
   break;
  }
  // END INNER SWITCH
 break;

 default:
 break;
}

switch($PopTax)
{
 case 'Life':
 $SeriesIndex = '1. <a href="/introduction" title="Life 101">Life 101</a><br>
 2. <a href="/topics/classification" title="Classification">Classification</a><br>
 3. <a href="/topics/homes" title="Homes">Homes</a><br>
 4. <a href="/topics/morphology" title="Morphology">Morphology</a><br>
 5. <a href="/topics/physiology" title="Physiology">Physiology</a><br>
 6. <a href="/topics/movement" title="Movement">Movement</a><br>
 7. <a href="/topics/nutrition" title="Nutrition">Nutrition</a><br>
 8. <a href="/topics/behavior" title="Behavior">Behavior</a><br>
 9. <a href="/topics/reproduction" title="Reproduction">Reproduction</a><br>
 10. <a href="/topics/ecology" title="Ecology">Ecology</a><br>
 11. <a href="/topics/evolution" title="Evolution">Evolution</a><br>
 12. <a href="/topics/people" title="People">People</a>';
 $SeriesIndex = str_replace('<a href="/'.$Title.'" title="Life 101">Life 101</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>Life 101</b></span>', $SeriesIndex);
 $SeriesIndex = str_replace('<a href="/topics/'.$MyURL.'" title="'.$Title.'">'.$Title.'</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$Title.'</b></span>', $SeriesIndex);
 break;

// PLANTS
 case 'Plant':
 $SeriesIndex = '1. <a href="/topics/'.$PopTaxL.'" title="'.$PopTaxa.' 101">'.$PopTaxa.' 101</a><br>
 2. <a href="/topics/'.$PopTaxL.'-classification" title="'.$PopTax.' Classification">Classification</a><br>
 3. <a href="/topics/'.$PopTaxL.'-homes" title="'.$PopTax.' Homes">'.$PopTax.' Homes</a><br>
 4. <a href="/topics/'.$PopTaxL.'-morphology" title="'.$PopTax.' Morphology">Morphology</a><br>
 5. <a href="/topics/'.$PopTaxL.'-physiology" title="'.$PopTax.' Physiology">Physiology</a><br>
 6. <a href="/topics/'.$PopTaxL.'-movement" title="'.$PopTax.' Movement">Movement</a><br>
 7. <a href="/topics/'.$PopTaxL.'-nutrition" title="'.$PopTax.' Nutrition">Nutrition</a><br>
 8. <a href="/topics/'.$PopTaxL.'-behavior" title="'.$PopTax.' Behavior">Behavior</a><br>
 9. <a href="/topics/'.$PopTaxL.'-reproduction" title="'.$PopTax.' Reproduction">Reproduction</a><br>
 10. <a href="/topics/'.$PopTaxL.'-ecology" title="'.$PopTax.' Ecology">Ecology</a><br>
 11. <a href="/topics/'.$PopTaxL.'-evolution" title="'.$PopTax.' Evolution">Evolution</a><br>
 12. <a href="/topics/'.$PopTaxaL.'-and-people" title="'.$PopTaxa.' and People">'.$PopTaxa.' &amp; People</a>';
 $SeriesIndex = str_replace('<a href="/topics/'.$MyURL.'" title="'.$Title.'">'.$Title2.'</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$Title2.'</b></span>', $SeriesIndex);
 $SeriesIndex = str_replace('<a href="/topics/'.$MyURL.'" title="'.$Title.'">'.$PopTaxa.' &amp; People</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$PopTaxa.' &amp; People</b></span>', $SeriesIndex);
 break;
 
 case 'Flowering Plant':
 case 'Conifer':
 $PopTaxL = str_replace(' ', '-', $PopTax);
 $PopTaxaL = str_replace(' ', '-', $PopTaxa);
 $SeriesIndex = '1. <a href="/topics/'.$PopTaxL.'" title="'.$PopTaxa.' 101">'.$PopTaxa.' 101</a><br>
 2. <a href="/topics/'.$PopTaxL.'-classification" title="'.$PopTax.' Classification">Classification</a><br>
 3. <a href="/topics/'.$PopTaxL.'-homes" title="'.$PopTax.' Homes">'.$PopTax.' Homes</a><br>
 4. <a href="/topics/'.$PopTaxL.'-morphology" title="'.$PopTax.' Morphology">Morphology</a><br>
 5. <a href="/topics/'.$PopTaxL.'-physiology" title="'.$PopTax.' Physiology">Physiology</a><br>
 6. <a href="/topics/'.$PopTaxL.'-nutrition" title="'.$PopTax.' Nutrition">Nutrition</a><br>
 7. <a href="/topics/'.$PopTaxL.'-reproduction" title="'.$PopTax.' Reproduction">Reproduction</a><br>
 8. <a href="/topics/'.$PopTaxL.'-ecology" title="'.$PopTax.' Ecology">Ecology</a><br>
 9. <a href="/topics/'.$PopTaxL.'-evolution" title="'.$PopTax.' Evolution">Evolution</a><br>
 10. <a href="/topics/'.$PopTaxL.'-and-people" title="'.$PopTaxa.' and People">'.$PopTaxa.' &amp; People</a>';
 $SeriesIndex = str_replace('<a href="/topics/'.$MyURL.'" title="'.$Title.'">'.$Title2.'</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$Title2.'</b></span>', $SeriesIndex);
 $SeriesIndex = str_replace('<a href="/topics/'.$MyURL.'" title="'.$Title.'">'.$PopTaxa.' &amp; People</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$PopTaxa.' &amp; People</b></span>', $SeriesIndex);
 break;

// ANIMALS
 case 'Animal':
 case 'Vertebrate':
 case 'Human':
 $SeriesIndex = '1. <a href="/topics/'.$PopTaxL.'" title="'.$PopTaxa.' 101">'.$PopTaxa.' 101</a><br>
 2. <a href="/topics/'.$PopTaxL.'-classification" title="'.$PopTax.' Classification">Classification</a><br>
 3. <a href="/topics/'.$PopTaxL.'-homes" title="'.$PopTax.' Homes">'.$PopTax.' Homes</a><br>
 4. <a href="/topics/'.$PopTaxL.'-morphology" title="'.$PopTax.' Morphology">Morphology</a><br>
 5. <a href="/topics/'.$PopTaxL.'-physiology" title="'.$PopTax.' Physiology">Physiology</a><br>
 6. <a href="/topics/'.$PopTaxL.'-movement" title="'.$PopTax.' Movement">Movement</a><br>
 7. <a href="/topics/'.$PopTaxL.'-nutrition" title="'.$PopTax.' Nutrition">Nutrition</a><br>
 8. <a href="/topics/'.$PopTaxL.'-behavior" title="'.$PopTax.' Behavior">Behavior</a><br>
 9. <a href="/topics/'.$PopTaxL.'-reproduction" title="'.$PopTax.' Reproduction">Reproduction</a><br>
 10. <a href="/topics/'.$PopTaxL.'-ecology" title="'.$PopTax.' Ecology">Ecology</a><br>
 11. <a href="/topics/'.$PopTaxL.'-evolution" title="'.$PopTax.' Evolution">Evolution</a><br>
 12. <a href="/topics/'.$PopTaxaL.'-and-people" title="'.$PopTaxa.' and People">'.$PopTaxa.' &amp; People</a>';
 $SeriesIndex = str_replace('<a href="/topics/'.$MyURL.'" title="'.$Title.'">'.$Title2.'</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$Title2.'</b></span>', $SeriesIndex);
 $SeriesIndex = str_replace('<a href="/topics/'.$MyURL.'" title="'.$Title.'">'.$PopTaxa.' &amp; People</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$PopTaxa.' &amp; People</b></span>', $SeriesIndex);
 break;

 case 'Mammal':
 case 'Bird':
 case 'Reptile':
 case 'Amphibian':
 case 'fish':
 case 'Arthropod':
 case 'Insect':
 case 'Mollusk':
 $SeriesIndex = '1. <a href="/topics/'.$PopTaxL.'" title="'.$PopTaxa.' 101">'.$PopTaxa.' 101</a><br>
 2. <a href="/topics/'.$PopTaxL.'-classification" title="'.$PopTax.' Classification">Classification</a><br>
 3. <a href="/topics/'.$PopTaxL.'-homes" title="'.$PopTax.' Homes">'.$PopTax.' Homes</a><br>
 4. <a href="/topics/'.$PopTaxL.'-morphology" title="'.$PopTax.' Morphology">Morphology</a><br>
 5. <a href="/topics/'.$PopTaxL.'-physiology" title="'.$PopTax.' Physiology">Physiology</a><br>
 6. <a href="/topics/'.$PopTaxL.'-movement" title="'.$PopTax.' Locomotion">Locomotion</a><br>
 7. <a href="/topics/'.$PopTaxL.'-nutrition" title="'.$PopTax.' Diets">Diets</a><br>
 8. <a href="/topics/'.$PopTaxL.'-behavior" title="'.$PopTax.' Behavior">Behavior</a><br>
 9. <a href="/topics/'.$PopTaxL.'-reproduction" title="'.$PopTax.' Reproduction">Reproduction</a><br>
 10. <a href="/topics/'.$PopTaxL.'-ecology" title="'.$PopTax.' Ecology">Ecology</a><br>
 11. <a href="/topics/'.$PopTaxL.'-evolution" title="'.$PopTax.' Evolution">Evolution</a><br>
 12. <a href="/topics/'.$PopTaxaL.'-and-people" title="'.$PopTaxa.' and People">'.$PopTaxa.' &amp; People</a>';
 $SeriesIndex = str_replace('<a href="/topics/'.$MyURL.'" title="'.$Title.'">'.$Title2.'</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$Title2.'</b></span>', $SeriesIndex);
 $SeriesIndex = str_replace('<a href="/topics/'.$MyURL.'" title="'.$Title.'">'.$PopTaxa.' &amp; People</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$PopTaxa.' &amp; People</b></span>', $SeriesIndex);
 break;

 case 'Invertebrate':
 $SeriesIndex = '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>Invertebrates</b></span>';
 break;
 default:
 break;
}
?>

<?php
switch(PHP_OS)
{
 case 'Linux':
 break;
 default:
  // INNER SWITCH
  switch ($ShadowPage)
  {
   case 'ShadowPage':
   echo '<div style="background: #90c; color: #fff;; font-size: 75%; text-align: center;">inc/D/Shared/Body/Content/Series/GZ.php</div>';
   break;
   default:
   break;
  }
  // END INNER SWITCH
 break;
}
?>
<div style="padding: 5px; background: #fff; border: 1px dashed #000;">
  <div id="IntroSeries" style="margin-bottom: 5px; background: #000; color: #fff; font-weight: 800; text-align: center;">Introductory Series</div>
<?php
echo $SeriesIndex;

switch($PopTax)
{
 case 'Human':
 $HumanCode = '';
 break;
 default:
 $HumanCode = ' background: #ff0; border: 1px solid #f00;';
 break;
}
$Switch = '<div style="margin: 5px auto; padding: 2px 5px; background: #cff; border-top: 1px dotted #000;">
  <em>Switch to...</em>
  <a href="/introduction" title="Life">LIFE</a><br>
  <div style="padding: 5px; background: #fcc;">
    <a href="/topics/animal" title="Animals">Animals</a> >
    I. <a href="/topics/vertebrate" title="Vertebrates">Vertebrates</a> >
    <a href="/topics/mammal" title="Mammals">Mammals</a> >
    <a href="/topics/human" title="Humans">Humans</a> |
    <a href="/topics/bird" title="Birds">Birds</a> |
    <a href="/topics/reptile" title="Reptiles">Reptiles</a> |
    <a href="/topics/amphibian" title="Amphibians">Amphibians</a> |
    <a href="/topics/fish" title="Fish">Fish</a>
    II. <a href="/topics/invertebrate" title="Invertebrates">Invertebrates</a> >
    <a href="/topics/arthropod" title="Arthropods">Arthropods</a> |
    <a href="/topics/insect" title="Insects">Insects</a> |
    <a href="/topics/mollusk" title="Mollusks">Mollusks</a>
  </div>
  <div style="padding: 5px; background: #cfc;">
    <a href="/topics/plant" title="Plants">Plants</a> >
    <a href="/topics/flowering-plant" title="Flowering Plants">Flowering Plants</a> |
    <a href="/topics/conifer" title="Conifers">Conifers</a>
  </div>
  <div style="padding: 5px; background: #fff;">
    <a href="/topics/fungus" title="Fungi">Fungi</a>
  </div>
</div>';

switch($PopTax)
{
 case 'Life':
 $Switch = str_replace('<a href="/introduction" title="Life">LIFE</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>Life</b></span>', $Switch);
 break;
 case 'Flowering Plant':
 $Switch = str_replace('<a href="/topics/flowering-plant" title="Flowering Plants">Flowering Plants</a>', '<span style="padding: 0 5px; background: #f00; color: #ff0;"><b>Flowering Plants</b></span>', $Switch);
 break;
 default:
 $Switch = str_replace('<a href="/topics/'.$PopTaxL.'" title="'.$PopTaxa.'">'.$PopTaxa.'</a>', '<span  style="padding: 0 5px; background: #f00; color: #ff0;"><b>'.$PopTaxa.'</b></span>', $Switch);
 break;
}

echo $Switch;
?>
</div>

<?php
$MyTopicL = strtolower($MyTopic);
switch($MyTopic)
{
 case 'People':
echo '<div style="margin-top: 5px; padding: 5px; background: #fff; border: 1px dashed #000;">
 <div id="IntroSeries" style="margin-bottom: 5px; background: #009; color: #fff; font-weight: 800; text-align: center;">'.$MyTopic.' Channel</div>
   &#8226; <a href="/topics/plants-and-people" title="Plants and People">Plants</a><br>
   > <a href="/topics/flowering-plants-and-people" title="Flowering Plants and People">Flowering Plants</a><br>
   > <a href="/topics/conifers-and-people" title="Conifers and People">Conifers</a><br>
   &#8226; <a href="/topics/animals-and-people" title="Animals and People">Animals</a><br>
   > <a href="/topics/mammals-and-people" title="Mammals and People">Mammals</a><br>
   >> <a href="/topics/humans-and-people" title="Humans and People">Humans</a><br>
   > <a href="/topics/birds-and-people" title="Birds and People">Birds</a><br>
   > <a href="/topics/reptiles-and-people" title="Reptiles and People">Reptiles</a><br>
   > <a href="/topics/amphibians-and-people" title="Amphibians and People">Amphibians</a><br>
   > <a href="/topics/fish-and-people" title="Fish and People">Fish</a><br>
   > <a href="
/topics/invertebrate#'.$MyTopic.'" title="Invertebrates and People">Invertebrates</a><br>
   > <a href="/topics/arthropods-and-people" title="Arthropod and People">Arthropods</a><br>
   > <a href="/topics/insects-and-people" title="Insect and People">Insects</a>
 </div>';
 break;
 default:
  // INNER SWITCH
  switch($MyTopic)
  {
   case 'Movement':
    // INNER SWITCH 2
    switch($MyTopic)
    {
     case 'Flowering Plant':
	 $FloweringPlants = '';
     break;
     case 'Conifer':
	 $Conifers = '';
     break;
	 case 'Fungi':
	 $Fungi = '';
	 break;
     default:
     break;
    }
    // END INNER SWITCH 2
   break;
   case 'Behavior':
    // INNER SWITCH 2
    switch($MyTopic)
    {
     case 'Flowering Plant':
	 $FloweringPlants = '';
     break;
     case 'Conifer':
	 $Conifers = '';
     break;
	 case 'Fungi':
	 $Fungi = '';
	 break;
     default:
     break;
    }
    // END INNER SWITCH 2
   break;
   default:
   $FloweringPlants = '> <a href="/topics/flowering-plant-'.$MyTopicL.'" title="Flowering Plant '.$MyTopic.'">Flowering Plants</a><br>';
   $Conifers = '> <a href="/topics/conifer-'.$MyTopicL.'" title="Conifer '.$MyTopic.'">Conifers</a><br>';
   $Fungi = '&#8226; <a href="/topics/fungi-'.$MyTopicL.'" title="Fungis '.$MyTopic.'">Fungi</a><br>';
   break;
  }
  // END INNER SWITCH
echo '<div style="margin-top: 5px; padding: 5px; background: #fff; border: 1px dashed #000;">
 <div id="IntroSeries" style="margin-bottom: 5px; background: #009; color: #fff; font-weight: 800; text-align: center;">'.$MyTopic.' Channel</div>
   &#8226; <a href="/topics/plant-'.$MyTopicL.'" title="Plant '.$MyTopic.'">Plants</a><br>
   '.$FloweringPlants.'
   '.$Conifers.'
   '.$Fungi.'
   &#8226; <a href="/topics/animal-'.$MyTopicL.'" title="Animal '.$MyTopic.'">Animals</a><br>
   > <a href="/topics/mammal-'.$MyTopicL.'" title="Mammal '.$MyTopic.'">Mammals</a><br>
   >> <a href="/topics/human-'.$MyTopicL.'" title="Human '.$MyTopic.'">Humans</a><br>
   > <a href="/topics/bird-'.$MyTopicL.'" title="Bird '.$MyTopic.'">Birds</a><br>
   > <a href="/topics/reptile-'.$MyTopicL.'" title="Reptile '.$MyTopic.'">Reptiles</a><br>
   > <a href="/topics/amphibian-'.$MyTopicL.'" title="Amphibian '.$MyTopic.'">Amphibians</a><br>
   > <a href="/topics/fish-'.$MyTopicL.'" title="Fish '.$MyTopic.'">Fish</a><br>
   > <a href="
/topics/invertebrate#'.$MyTopic.'" title="Invertebrate '.$MyTopic.'">Invertebrates</a><br>
   > <a href="/topics/arthropod-'.$MyTopicL.'" title="Arthropod '.$MyTopic.'">Arthropods</a><br>
   > <a href="/topics/insect-'.$MyTopicL.'" title="Insect '.$MyTopic.'">Insects</a>
 </div>';
 break;
}

@Chavista - There seems to be an awful lot of duplicate code in those switch statements. What are the essential differences between the indexes you’re generating for different sections of your site?

I’ve developed a series of series that are almost identical for every taxon (mammals, mammals, etc.). For example, each series includes an introduction, followed by articles about classification, morphology, etc.

One of the big differences is the links - animal-ecology vs plant-ecology. There are also tiny differences here and there. For example, there are no articles about behavior in the plant and fungi series. (Actually, I guess there is a single article about plant behavior.)

Then there are tiny differences in plurals - add an s to mammal, bird, reptile - just about everything except fish.

So I just wound up putting together an elaborate code that covers all the bases. I also designed it so that, if the URL is animal-evolution, that particular link is highlighted, rather than linked.

Are these articles stored in a DB? If so, rather than hard-coding all these different menus you could generate them automatically, which would save a lot of code and be easier to maintain than all those switch statements.

Yes, I have two database tables. One stores the URL’s, page titles, page topics, etc. The other stores the articles.

I couldn’t figure out how to generate the kind of menu I had in mind, though. But I’ll take another look at it. Thanks.

If you want, you could post the structure of the two tables and a sample entry for each and I can try to help you with that?

I agree with fretburner that this should be handles in the database. If you have the database set up correctly you can use it to make the menus and sub menus.

On second thought, I don’t think the database table with the articles has anything to do with this. Instead, it’s based on the table gz_topics, particularly on the fields URL, Title, Parent, PopTax and MyTopic. The field Rank would probably help in finding a database solution, too.

URL | Title | Parent | PopTax | MyTopic | Rank
classification | Classification | life | Life | Classification | 2
behavior | Behavior | life | Life | Behavior | 2
animal-behavior | Animal Behavior | behavior | Animal | Behavior | 3
vertebrate-behavior | Vertebrate Behavior | animal-behavior | Vertebrate | Behavior | 4
mammal-behavior | Mammal Behavior | vertebrate-behavior | Mammal | Behavior | 5
human-behavior | Human Behavior | mammal-behavior | Human | Behavior | 6

There are a total of twelve topics…

Introduction
Classification
Homes
Morphology
Physiology
Movement
Nutrition
Behavior
Reproduction
Ecology
Evolution
People

And I think I currently have 17 taxons in the series…

Life
Plant
> Flowering Plant
> Conifer
Fungi
Animal
> Vertebrate
>> Mammal
>>> Human
>> Bird
>> Reptile
>> Amphibian
>> Fish
> Invertebrate
>> Arthropod
>>> Insect
>> Mollusk

But there are a variety of exceptions. For example, there are no articles about behavior for flowering plants, conifers or fungi. Ditto for movement. In addition, the top articles about movement are titled Movement, Plant Movement, Animal Movement, etc., but the titles for all the animals taxons are Mammal Locomotion, Bird Locomotion…except Human Movement.

The topic category People is unique, too. URL’s include animals-and-people, mammals-and-people, with matching titles - Animals and People, Mammals and People.

There’s just one article in the Invertebrate series, though there are a dozen articles for various groups of invertebrates (insects, mollusks, etc.).

As you can see, my database table is pretty redundant, too. I could probably delete two or three fields and use str_replace to manipulate the remaining columns. Part of the problem is I’m in the process of changing all my URL’s from upper case to lower case, at the same time replacing underscores with dashes. Thus, Topics/Animal_Behavior will become topics/animal-behavior.

Anyway, I just threw together something that works until I get a chance to refine it.

You could actually build the lists with relatively little data.

Imagining that you have your taxons and topics stored tables with structures like this:


taxon
-------
ID
name
parent_id (refers back to ID of parent entry)

topic
------
ID
name

all you would need then is a link table:


taxon_topics
------------------
taxon_id
topic_id

and then querying for a list of the correct topics for a taxon is then just a matter of using a JOIN query:

SELECT * FROM topics 
JOIN taxon_topics ON taxon_topics.topic_id = topics.id
WHERE taxon_topics.taxon_id = :taxon_id

and looping over the topics to generate the menu html:


function generate_menu_items($taxon, $topics, $current_topic)
{
	$menu_items = array();

	foreach ($topic as $topics)
	{
		$url   = "/topics/$taxon-$topic[name]";
		$title = "$taxon $topic[name]";
		$text  = $topic['name'];

		if ($topic === 'People') {
			$url   = "$taxon[name]-and-$topic";
			$title = "$taxon[name] and $topic";
			$text  = "$taxon[name] &amp; $topic";
		}

		if ($topic === 'Movement' && $taxon['parent'] == 8 && $taxon['name'] != 'Human') {
			$url   = "$taxon[name]-locomotion";
			$title = "$taxon[name] Locomotion";
			$text  = "Locomotion";
		}

		$menu_items[] = array(
			'url' 	 => strtolower($url),
			'title'  => ucwords($title),
			'text' 	 => ucfirst($text),
			'active' => ($topic['name'] === $current_topic)
		);
	}

	return $menu_items;
}


function render_menu($menu_items)
{
	$list_items = array();

	foreach ($menu_items as $item)
	{
		if ($item['active']) {
			$list_items[] = "<li><span class=\\"active\\">$item[text]</b></span></li>";
		} else {
			$list_items[] = "<li><a href=\\"$item\\" title=\\"$item[title]\\">$item[text]</a></li>";
		}
		
	}

	return '<ol>' . implode("\
", $list_items) . '</ol>';
}

Wow, thanks! That’s an elegant improvement over my sloppy code.

@ fretburner - I understand your script in general, but I’m hung up on a couple things. First, am I supposed to paste your script inside a while loop or outside it? It sounds like it should go INSIDE a while loop, but when I put it inside the loop, I get this error message:

Cannot redeclare generate_menu_items() (previously declared in…

So I’ve been working with it outside the while loop, like this:


while ($row = $stm->fetch())
{
 $MyTitle = $row['Title'];
 $PopTax = $row['PopTax'];
 $Topic = $row['MyTopic'];
 $Topics[] = $row['MyTopic'];
}

function generate_menu_items($PopTax, $Topics, $Current_Topic)
{

Second, I don’t understand where you got the second menu item - $Topics - from. Did you mean to write $Topic? If not then I assume $Topics is supposed to capture a list of ALL topics, which is why I changed $Topics = $row[‘MyTopic’] in the while loop to an array - $Topics = $row[‘MyTopic’].

Third, I don’t understand what [‘name’] refers to, as in $Topic[‘name’] or $Taxon[‘name’]. Am I supposed to replace ‘name’ with the name of a database field that holds the values for topic names or taxon names?

I gave that a try, but the script isn’t displaying anything. Thanks.

The two functions only need to be declared once, so you don’t want to put them within a loop. Usually, with procedural programs, it’s common to put related functions into a separate file which you can include in any of your scripts that need them:

include_once('menu-functions.php');

$topics is supposed to be a list of all topics for the selected taxon, retrieved with a JOIN query like the one in my last post.

The function generate_menu_items() expects the following arguments:


// $taxon - an associative array representing a single row from the imaginary [B]taxon[/B] table, representing a single taxon. 
// Example:
array(
    'id' => 9,
    'parent_id' => 8,
    'name' => 'Human'
);

// $topics - a multidimensional array (i.e using fetchAll with the JOIN query) of topics related to the current taxon.
// Example:
array(
    array(
        'id' => 1,
        'name' => 'Introduction'
    ),
    array(
        'id' => 2,
        'name' => 'Classification'
    ),
    // etc.
);

// $current_topic - a string representing the currently viewed topic
// Example:
"Classification";

I actually made a couple of mistakes in the function, by missing out the [name] part in some places. The correct function should be like this:


function generate_menu_items($taxon, $topics, $current_topic)
{
    $menu_items = array();

    foreach ($topic as $topics)
    {
        $url   = "/topics/$taxon[name]-$topic[name]";
        $title = "$taxon[name] $topic[name]";
        $text  = $topic['name'];

        if ($topic === 'People') {
            $url   = "$taxon[name]-and-$topic[name]";
            $title = "$taxon[name] and $topic[name]";
            $text  = "$taxon[name] &amp; $topic[name]";
        }

        if ($topic === 'Movement' && $taxon['parent'] == 8 && $taxon['name'] != 'Human') {
            $url   = "$taxon[name]-locomotion";
            $title = "$taxon[name] Locomotion";
            $text  = "Locomotion";
        }

        $menu_items[] = array(
            'url'    => strtolower($url),
            'title'  => ucwords($title),
            'text'   => ucfirst($text),
            'active' => ($topic['name'] === $current_topic)
        );
    }

    return $menu_items;
}

All of the above though is based around the imaginary table structures I described in my previous post, so it’s not going to work with your existing code right away (you’ll at least need a topics table and a link table).

You actually need to call the functions and pass in the required data, something like:


// DB code not shown
// ...

$menu_items = generate_menu_items($PopTax, $Topics, $Current_Topic);
$menu_html = render_menu($menu_items);

// Now you can echo $menu_html in your template wherever you want your menu to appear

OK, getting closer. :wink:

I already created the tables you specified. When I paste my query into phpMyAdmin > SQL, replacing the variable with ‘mam,’ it displays a row of info for every mammal topic, which coincides with every mammal URL - MySite/topics/mammal, MySite/topics/mammal-homes, etc.

I should note that I renamed $Taxon to $PopTax (= “popular taxon name”) and $Topic to $MyTopic to avoid confusion with the values $Taxon and $Topics, which are already declared in an earlier query. My ID’s consist of the first three letters of a taxon or topic. Thus, the id for mammals is Mam, while a topic ($MyTopic) ID could be Hom for Homes or Cla for Classification.

I’m not sure why it still isn’t displaying anything, but the problem is probably $menu_html = render_menu($menu_items). I’ve pasted it in several locations, but nothing works.

I added some notes in my code below. Thanks!


// I can later create these two values with the preceding database query, but I just inserted them manually for now. They tell us that this page represents Mam = mammals, so the taxon-topic is Mam-Hom, which corresponds to the URL mammal-homes.
$Tax_ID = 'Mam';
$Current_Topic = 'Homes';

// I had to modify the query to make it work. I had to join the third table. Also, when I pasted the query into phpMyAdmin  > SQL, it displayed the entire table, so I added a few qualifiers until it only displayed the topics for a single taxon (mammals, in this case).

$stm = $pdo->prepare("SELECT T.Title, T.MyTopic, T.Topic_ID, TP.Topic_ID, TP.Tax_ID, Tax.ID, Tax.PopTax, Tax.Parent
 FROM gz_topics T
 JOIN gz_topics_poptax TP ON TP.Topic_ID = T.Topic_ID
 JOIN gz_poptax Tax ON Tax.ID = TP.Tax_ID
 WHERE Tax.ID = :Tax_ID AND Tax.PopTax = T.PopTax");
 $stm->execute(array(
  'Tax_ID'=>$Tax_ID
 ));

while ($row = $stm->fetch())
{
 $MyTitle = $row['Title'];
 $PopTax = $row['PopTax'];
 $Topics = $row['MyTopic'];
}

function generate_menu_items($PopTax, $Topics, $Current_Topic)
{ 
    $menu_items = array(); 

    foreach ($Topic as $Topics) 
    { 
        $url   = "/topics/$PopTax[PopTax]-$Topic[MyTopic]"; 
        $title = "$PopTax[PopTax] $Topic[MyTopic]"; 
        $text  = $Topic['MyTopic']; 

        if ($Topic === 'People') { 
            $url   = "$PopTax[PopTax]-and-$Topic[MyTopic]"; 
            $title = "$PopTax[PopTax] and $Topic[MyTopic]"; 
            $text  = "$PopTax[PopTax] &amp; $Topic[MyTopic]"; 
        } 

        if ($Topic === 'Movement' && $PopTax['Parent'] == 8 && $PopTax['PopTax'] != 'Human') { 
            $url   = "$PopTax[PopTax]-locomotion"; 
            $title = "$PopTax[PopTax] Locomotion"; 
            $text  = "Locomotion"; 
        } 

        $menu_items[] = array( 
            'url'    => strtolower($url), 
            'title'  => ucwords($title), 
            'text'   => ucfirst($text), 
            'active' => ($Topic['MyTopic'] === $Current_Topic) 
        ); 
    } 

    // Where does this line go?
    $menu_html = render_menu($menu_items); 

    return $menu_items; 
}

It’s important to note that the function code only defines a couple of functions that we’ll use later, they don’t actually do anything until we call them. Also, the arguments and variables within functions are separate from other variables outside of the function, so you don’t have to worry about naming clashes.

As I said before, I’d recommend putting the function declarations into their own file:

menu-functions.php


<?php

function generate_menu_items($PopTax, $Topics, $Current_Topic)
{ 
    $menu_items = array(); 

    foreach ($Topic as $Topics) 
    { 
        $url   = "/topics/$PopTax[PopTax]-$Topic[MyTopic]"; 
        $title = "$PopTax[PopTax] $Topic[MyTopic]"; 
        $text  = $Topic['MyTopic']; 

        if ($Topic === 'People') { 
            $url   = "$PopTax[PopTax]-and-$Topic[MyTopic]"; 
            $title = "$PopTax[PopTax] and $Topic[MyTopic]"; 
            $text  = "$PopTax[PopTax] &amp; $Topic[MyTopic]"; 
        } 

        if ($Topic === 'Movement' && $PopTax['Parent'] == 8 && $PopTax['PopTax'] != 'Human') { 
            $url   = "$PopTax[PopTax]-locomotion"; 
            $title = "$PopTax[PopTax] Locomotion"; 
            $text  = "Locomotion"; 
        } 

        $menu_items[] = array( 
            'url'    => strtolower($url), 
            'title'  => ucwords($title), 
            'text'   => ucfirst($text), 
            'active' => ($Topic['MyTopic'] === $Current_Topic) 
        ); 
    } 

    return $menu_items; 
}

function generate_menu_html($menu_items)
{
	$list_items = array();

	foreach ($menu_items as $item)
	{
		if ($item['active']) {
			$list_items[] = "<li><span class=\\"active\\">$item[text]</b></span></li>";
		} else {
			$list_items[] = "<li><a href=\\"$item\\" title=\\"$item[title]\\">$item[text]</a></li>";
		}
		
	}

	return '<ol>' . implode("\
", $list_items) . '</ol>';
}

(Note: I think you might have to change this part that reads $PopTax['Parent'] == 8, as I’m not sure how to identify taxons that are sub-taxons of mammal… would it be ‘Mammal’ or ‘Mam’?)

This means we can keep the main script shorter and easier to read:


<?php
// Include the file so we have access to our two functions
include_once('menu-functions.php');

$Tax_ID = 'Mam';
$Current_Topic = 'Homes';

// Do first query to retrieve topic list
$stm = $pdo->prepare("SELECT T.Topic_ID, T.MyTopic
FROM gz_topics T
JOIN gz_topics_poptax TP ON TP.Topic_ID = T.Topic_ID
WHERE TP.Tax_ID = :Tax_ID");

$stm->execute(array('Tax_ID' => $Tax_ID));
// Fetch all rows (topics) as an associative array
$Topics = $stm->fetchAll(PDO::FETCH_ASSOC);

// Get the DB row for the taxon we're dealing with
$stm = $pdo->prepare("SELECT Tax.ID, Tax.PopTax, Tax.Parent
FROM gz_poptax Tax
WHERE Tax.ID = :Tax_ID");

$stm->execute(array('Tax_ID' => $Tax_ID));
// Fetch a single row, as the query should only return one row anyway
$PopTax = $stm->fetch(PDO::FETCH_ASSOC);

// Call our custom functions to generate the menu items, and render them as a HTML list
$menu_items = generate_menu_items($PopTax, $Topics, $Current_Topic);
$menu_html = render_menu($menu_items);

// Output the list to screen
echo $menu_html;

Note that I’ve made some changes to your DB query, based upon what I can understand about the table structures from your code. I’ve actually split it into two separate queries, and removed some of the unused fields, so we’re transferring less data from the DB.

Awesome! I just made a couple more changes, and it’s working beautifully now. Thanks for such a cool script. :wink: