Where can I plug in OOP?

Several people have told me learning OOP would improve my websites, so I read a couple beginner’s tutorials. It wasn’t as theoretically complex as I expected, but it’s still a little over my head. It would help if I could understand how it relates to my code. One author stressed that OOP and procedural PHP both have their place, and OOP should come into play only if your procedural code becomes too complex or confusing.

I have a CMS - not a brand name but one that I created myself. It’s a actually a collection of websites rolled into one. That is every site is built on PHP includes stores in the home website. Every website has multiple sections, some shared with other websites. For example, most have World and Reference sections - MySite/World, MySite2/World, etc.

So I have variables that display the names of nations ($MyCountry = United States), their parents ($MyParent = North America) and abbreviations ($MyID = U.S., $IDParent = NA). I also have variables that describe types of pages (e.g. $MyKind = Home, World Home or Child, $MyKind2 further subdivides it into children of child pages).

It gets a little confusing, but I can’t understand how a more complex code (OOP) would make it any simpler.

The code for my reference pages can get really complex, with lots of variables for details. But, again, I don’t see how OOP would be an improvement.

One thing that would help, though, is if I could somehow condense some of my longer, more complex PHP switches. For example, the code I posted below is a series of switches designed to classify living things into various categories - animals vs plants, vertebrates vs invertebrates; vertebrates into mammals, birds, etc.; warm-blooded vs cold-blooded vertebrates, etc.

Is that something that could be improved with OOP? If so, how would I start? Would I designate each major group a class? For example, this is from the tutorial:


class MyClass
{
    public $prop1 = "I'm a class property!";
}

$obj = new MyClass;

var_dump($obj);

echo $obj->prop1;

Would I change that to something like this?


class Mammals
{
    public $prop1 = "I'm a mammal!";
}

$obj = new Mammals;

var_dump($obj);

echo $obj->prop1;

…and then I’d somehow append smaller groups of mammals (e.g. primates, whales) to that? It looks to me like OOP would actually make my switches more complicated, but I’m probably missing something. Thanks.

Note: Don’t bother analyzing the code I posted below; I just wanted to illustrated how long and complex it is. The starting values (e.g. $Kingdom) derive from a database query that defines parents, grandparents, great-grandparents, etc. :wink:


switch($Kingdom)
{
 case 'Animalia':

  // Endo/Ectotherms...
  // INNER SWITCH
  switch($MyCla)
  {
   case 'Mam':
   case 'Ave':
   $Therm = 'endotherms';
   break;
   default:
   $Therm = 'ectotherms';
   break;
  }
  // END INNER SWITCH

  // Define $MyCla2...
  // INNER SWITCH
  switch($Tetrafish)
  {
   case 'Fish':
    // INNER SWITCH 2
    switch($MyCla)
    {
     case 'Act':
     $MyCla2 = 'Act';
     break;
     default:
     $MyCla2 = 'Fishetc';
     break;
    }
    // END INNER SWITCH 2
   break;
   default:
    // INNER SWITCH 2
    switch($MyCla)
    {
     case 'Rep':
     case 'Amp':
     $MyCla2 = 'Herps';
     break;
     default:
     $MyCla2 = $MyCla;
     break;
    }
    // END INNER SWITCH 2
 break;
}

  // VERTEBRATE vs INVERTEBRATE...
  // INNER SWITCH
  switch($Vert)
  {
   case 'Vert':
    // INNER SWITCH 2
    switch($Tetrafish)
    {
     case 'Tetrapod':

      // Define $Herptile...
      // INNER SWITCH 3
      switch($MyCla)
      {
       // Herptiles...
       case 'Rep':
       case 'Amp':
       $Herptile = 'herptiles';
       break;
       default:
       $Herptile = '';
       break;
      }
      // END INNER SWITCH 3

    // INNER SWITCH 2
    // SUBORDERS
    switch($MyCla)
    {
     case 'Mam':
      // INNER SWITCH 3
      switch($MyOrd)
      {
       case 'Carnivora':
        // INNER SWITCH 4
        switch($MyFam)
        {
         case 'Odobenidae':
         case 'Otariidae':
         case 'Phocidae':
         $Suborder = 'Pinnipedia';
         break;
         default:
         $Suborder = '';
         break;
        }
        // END INNER SWITCH 4
       break;
       case 'Artiodactyla':
        // INNER SWITCH 4
        switch($MyFam)
        {
         case 'Camelidae':
         $Suborder = 'Tylopoda';
         break;
         case 'Hippopotamidae':
         case 'Suidae':
         case 'Tayassuidae':
         $Suborder = 'Suina';
         break;
         default:
         $Suborder = 'Ruminantia';
         break;
        }
        // END INNER SWITCH 4
       break;

       case 'Cetacea':
        // INNER SWITCH 4
        switch($MyFam)
        {
         case 'Balaenidae':
         case 'Balaenopteridae':
         case 'Neobalaenidae':
         $Suborder = 'Mysticetes';
         break;
         default:
         $Suborder = 'Odontocetes';
         break;
        }
        // END INNER SWITCH 4
       break;
       default:
	   break;
      }
      // END INNER SWITCH 3

     break;
     case 'Rep':
      // INNER SWITCH 3
      switch($MyOrd)
      {
       case 'Squamata':
        // INNER SWITCH 4
        switch($MyFam)
        {
         case 'Acrochordidae':
         case 'Aniliidae':
         case 'Anomalepidae':
         case 'Anomochilidae':
         case 'Atractaspididae':
         case 'Boidae':
         case 'Bolyeridae':
         case 'Colubridae':
         case 'Cylindrophiidae':
         case 'Elapidae':
         case 'Hydrophiidae':
         case 'Leptotyphlopidae':
         case 'Loxocemidae':
         case 'Tropidophiidae':
         case 'Typhlopidae':
         case 'Uropeltidae':
         case 'Viperidae':
         case 'Xenopeltidae':
         // Snakes
         $Suborder = 'Serpentes';
         break;
         case 'Amphisbaenia':
         case 'Amphisbaenidae':
         case 'Rhineuridae':
         // Worm lizards
         $Suborder = 'Amphisbaenia';
         break;
         default:
         // Legless lizards: Anniellidae
         // Lizard families: Amphisbaenia, Anguidae, Agamidae, Anniellidae, Chamaeleonidae, Cordylidae, Corytophanidae, Crotaphytidae, Dibamidae, Gekkonidae, Gerrhosauridae, Gymnophthalmidae, Helodermatidae, Hoplocercidae, Iguanidae, Lacertidae, Lanthanotidae, Opluridae, Phrynosomatidae, Polychrotidae, Pygopodidae, Scincidae, Teiidae, Tropiduridae, Varanidae, Xantusiidae and Xenosaurida
         $Suborder = 'Lacertilia';
         break;
        }
        // END INNER SWITCH 4
       break;
       default:
       break;
    }
      // END INNER SWITCH 3
     break;
     default:
     break;
    }
    // END INNER SWITCH 2
    // End Tetrapod Suborders...
     break;
     case 'Fish':
      // Define $Fish2...
      // INNER SWITCH 3
      switch($MyCla)
      {
       case 'Act':
       case 'Sar':
       $Fish2 = 'Bony';
       break;
       case 'Ela':
       case 'Hol':
       $Fish2 = 'Cartilage';
       break;
       default:
       $Fish2 = 'Jawless';
       break;
      }
      // END INNER SWITCH 3

      // SUPERORDERS
      // Sharks & Rays
      // INNER SWITCH 3
      switch($MyCla)
      {
       case 'Ela':
        // INNER SWITCH 4
        switch($MyOrd)
        {
         case 'Pristiformes':
         case 'Rajiformes':
         case 'Torpediniformes':
         $Superorder = 'Batoidea';
         $Superorder2 = 'rays';
         break;
         default:
         $Superorder = 'Selachimorpha';
         $Superorder2 = 'sharks';
         break;
        }
        // END INNER SWITCH 4
   break;
   default:
   break;
  }
  // END INNER SWITCH
     break;
     default:
     break;
    }
    // END INNER SWITCH 2
   break;
   case 'Invert':
   break;
   default:
   break;
  }
  // END INNER SWITCH
 break;
 case 'Plantae':
 break;
 default:
 break;
}

// FISH
switch($Tetrafish)
{
 case 'Fish':
 break;
 default:
 break;
}

// FISH iFamilies
switch($MyCla)
{
 case 'Act':
  // INNER SWITCH
  switch($MyOrd)
  {
   case 'Scorpaeniformes':
   $iFam = 'Scorp';
   break;
   case 'Siluriformes':
   $iFam = 'Silur';
   break;
   case 'Perciformes':
    // INNER SWITCH 2
    $iPerci = substr($MyFam,0,1);
    switch($iPerci)
    {
     case 'A':
     case 'B':
     case 'C':
     $iFam = 'Perci1';
     break;
     case 'D':
     case 'E':
     case 'G':
     case 'H':
     case 'I':
     case 'K':
     case 'L':
     $iFam = 'Perci2';
     break;
     case 'M':
     case 'N':
     case 'O':
     case 'P':
     case 'R':
     $iFam = 'Perci3';
     break;
     case 'S':
     case 'T':
     case 'U':
     case 'X':
     case 'Z':
     $iFam = 'Perci4';
     break;
     default:
     break;
    }
    // END INNER SWITCH
   break;
   case '':
   $iFam = 'ActMisc';
   break;
   break;
   default:
   break;
  }
  // END INNER SWITCH
 break;
 default:
 break;
}

// Divide mammals into nine groups...
switch($MyCla)
{
 case 'Mam':
  // INNER SWITCH
  switch($MyOrd)
  {
   // Marine Mammals
   case 'Cetacea':
   case 'Sirenia':
   $Duende = 'Marine_Mammals';
   break;
   // Bats
   case 'Chiroptera':
   $Duende = 'Bats';
   break;
   // Ungulates
   case 'Proboscidea':
   case 'Perissodactyla':
   case 'Artiodactyla':
   $Duende = 'Ungulates';
   break;
   // Carnivorans
   case 'Carnivora':
   $Duende = 'Carnivorans';
   break;
   // Primates
   case 'Primates':
   $Duende = 'Primates';
   break;
   // Rodents
   case 'Rodentia':
   $Duende = 'Rodents';
   break;
   // Marsupials
   case 'MARSUPIALS':
   $Duende = 'Marsupials';
   break;
   // Tropical Oddballs
   case '':
   $Duende = 'Oddballs';
   break;
   // Misc.
   default:
   break;
  }
  // END INNER SWITCH
 break;
 default:
 break;
}

switch($MyURL)
{
 case 'Mammals':
 case 'Marine_Mammals':
 case 'Bats':
 case 'Ungulates':
 case 'Carnivorans':
 case 'Primates2':
 case 'Marsupials':
 case 'Tropical_Oddballs':
 case 'Other_Mammals':
 $MyCla = 'Mam';
 break;
 default:
 break;
}

The place to start with OOP is to rethik the way you design the program from the start.

The first step is to work out what types of “things” the program needs to have in order to do whatever it is supposed to do. That gives you your classes.

You then work out what actions each of those things needs to be able to perform - those become the methods on the class.

If you are going to convert gradually then start out by defining one class and then rewrite your existing code to use objects based on that class where ever the code needs to interact with whatever “thing” you decided to make into a class.

Let’s start by packing all those switch statements into a class:


$lifeRepo = new LifeRepository();

echo sprintf("Cla For Bats: %s\
",$lifeRepo->findCla('Bats'));

echo sprintf("Duende For Perissodactyla: %s\
",$lifeRepo->findDuende('Mam','Perissodactyla'));

echo sprintf("Duende For Perciformes,K2: %s\
",$lifeRepo->findDuende('Act','Perciformes','K2'));

=== Console ===
Cla For Bats: Mam
Duende For Perissodactyla: Ungulates
Duende For Perciformes,K2: Perci2

The idea is that with a LifeRespository we can hide all those switch statements inside of an object.
Much of what you did with switch statements could be implemented with arrays or a database or even a YAML file.
But your application would not care if the implementation changes. All it needs to know about is the LifeRepository.

Here is one possible implementation. I’ll let you decide if it is any cleaner than your nested switches.


class LifeRepository
{
    public function findDuende($cla,$ord,$fam = null)
    {
        switch($cla)
        {
            case 'Mam': return $this->findDuendeMam($ord);
            case 'Act': return $this->findDuendeAct($ord,$fam);
        }
    }
    public function findDuendeAct($ord,$fam)
    {
        switch($ord)
        {
            case 'Scorpaeniformes': return 'Scorp';
            case 'Siluriformes':    return 'Silur';
                
            case 'Perciformes': return $this->findDuendeActPerci($fam);  
                
            case '': return 'ActMisc';
        }
    }
    public function findDuendeActPerci($fam)
    {
        $iPerci = substr($fam,0,1);
        switch($iPerci)
        {
            case 'A': case 'B': case 'C':
                return 'Perci1';
                    
            case 'D': case 'E': case 'G': case 'H':
            case 'I': case 'K': case 'L':
                return 'Perci2';
                    
            case 'M': case 'N': case 'O': case 'P': case 'R':
                return 'Perci3';
                    
            case 'S': case 'T': case 'U': case 'X': case 'Z':
                return 'Perci4';
        }
    }
    public function findDuendeMam($ord)
    {
        switch($ord)
        {
            // Marine Mammals
            case 'Cetacea':
            case 'Sirenia':
                return 'Marine_Mammals';
                        
            // Ungulates
            case 'Proboscidea':
            case 'Perissodactyla':
            case 'Artiodactyla':
                return 'Ungulates';
                        
            case 'Chiroptera': return 'Bats';
            case 'Carnivora':  return 'Carnivorans';
            case 'Primates':   return 'Primates';
            case 'Rodentia':   return 'Rodents';
            case 'MARSUPIALS': return 'Marsupials';
            case '':           return 'Oddballs';
        } 
    }
    public function findCla($url)
    {
        switch($url)
        {
            case 'Mammals':
            case 'Marine_Mammals':
            case 'Bats':
            case 'Ungulates':
            case 'Carnivorans':
            case 'Primates2':
            case 'Marsupials':
            case 'Tropical_Oddballs':
            case 'Other_Mammals':
                return 'Mam';
        }
    }
}

Wow! Thanks for taking the time to write that code. It will take me a little time to get the hang of it, but I can see now that OOP might be worth pursuing. :wink: