Say you wrote some code below for projectA.

function do_task(){
  // init
  my_init();
  // calling a class function
  $v = class_A::some_method($p1, $p2, $p3, $p4, $p5, $p6, $p7);
  // return
  return $v;
}

Now, your boss loves it. Then he asks you to do a very similar thing for projectB. Naively, you may do:

function do_task($project_type){
  // init
  my_init();
  // calling a class function
  if ($project_type == "projectA"){
    $v = class_A::some_method($p1, $p2, $p3, $p4, $p5, $p6, $p7);
  }elseif ($project_type == "projectB"){
    $v = class_B::some_method($p1, $p2, $p3, $p4, $p5, $p6, $p7);
  }
  // return
  return $v;
}

Um… it would work, but imagine if you will soon have projectC, and D, and on… and what if you need to add one more parameter to the some_method function?

In my opinion, the do_task function needs to be generalized, by taking in the class name as a parameter. Then add a lookup function to translate project names to class names. See below:

function do_task($class_name){
  // init
  my_init();
  // calling a class function
  $my_class = new $class_name();
  $v = $my_class::some_method($p1, $p2, $p3, $p4, $p5, $p6, $p7);
  // return
  return $v;
}

function lookup_class_name($project_name){
  switch ($project_name){
    case "projectA": return "class_A";
    case "projectB": return "class_B";
    // ...
  }
}

// main
$class_name = lookup_class_name("projectB");
$v = do_task($class_name);

The code looks a lot more manageable now. ;)