strategy pattern, good practices on how to switch between classes i'm using an external API that posts products and orders into a marketplace, and it provides a class that in each request i have to specify an endpoint, user and password (token), it's something like this:

if($env == 'testing') {
    $endpoint = 'testing';
    $user = 'testing';
    $pass = 'testing';
} else {
    $endpoint = 'production';
    $user = 'production';
    $pass = 'production';
}


$itemSender = new ItemSender($endpoint, $user, $pass);
$orderSender = new OrderSender($endpoint, $user, $pass);


my first thought was to use the strategy pattern so i can have both testing and production environment, or even others environments, implementing an interface, i built something lie this:

interface EnviromentInterface () {

    function getEndpoint();
    function getUser();
    function getPassword();
}

class TestingEnvironment implements EnviromentInterface {

    private $endpoint;
    private $user;
    private $password;

    function getEndpoint() {
        return $this-&gt;endpoint;
        // return getFromConfigFile('API_ENDPOINT_TESTING');
    }

    function getUser() {
        return $this-&gt;user;
    }

    function getPassword() {
        return $this-&gt;password;
    }

}

class ProductionEnviroment implements EnviromentInterface {

    private $endpoint;
    private $user;
    private $password;

    function getEndpoint() {
        return $this-&gt;endpoint;
        // return getFromConfigFile('API_ENDPOINT_PRODUCTION');
    }

    function getUser() {
        return $this-&gt;user;
    }

    function getPassword() {
        return $this-&gt;password;
    }

}


and i would overwrite the parent's class construct to use the environment object, something like this:

class CustomItemSender extends ItemSender
{

    function __construct(EnviromentInterface $env)
    {
        parent::__construct($env-&gt;getEndpoint(), $env-&gt;getUser(), $env-&gt;getPassword());
    }
}


the problem is: how can i switch between these environment objects? i thought about using a switch/case, but if i need to implement more environments i have to add another if to the switch/case statment.

what would be a good aproach in this case? 

important: all info/credentials about the testing and production environments are inside a config file, that in this case is an .env file
You are probably looking for factory method pattern, instead of strategy pattern.

The CustomItemSender class is a good indicator of this.
Whenever you extend a class to only override the constructor, you probably need a factory instead. It means you need somewhat more complex way of constructing the object and that implies creational pattern. Strategy is a behavioral pattern (and in fact, your code does not implement this pattern).

The EnvironmentInterface is basicaly a data structure, it is immutable which is good, but it has no behaviour, which is not so good. It is just a tuple. Maybe you don't really need this structure and stay with tripplet of arguments.

Polymorphism only makes sense to abstract varying behaviour, not data. Anyway polymorphism won't help you avoid ifs/switches entirely. It will help you reduce the amount of them to minimum. You might still need some ifs in the creational part, but once a polymorhic object is created, it no longer repeats those ifs because it encapsulates the beforehand chosen branch.

Sometimes ifs/switches can be replaced by key-value maps though (such a map could be owned by a factory...).

Getting config values from a file using global function like yours getFromConfigFile(string $key) is not very wise btw. Because it either loads the file again on every request for a key. Or it loads it only once but stores the loaded data to a global variable thus having side effects on globle state which is a bad practice. You might want to load all config from the file to lets say array (possibly encapsulated in an objet) and serve the individual config values from it. And btw the function knows the location of the config file globally/magically and that is also not very good. You might need a factory for the config object, which will load the config from a given a file.

function loadConfigFromJsonFile(string $filename): array
{
  // add error handling
  return json_decode(file_get_contents($filename), true);
}

class SenderFactory
{

  private string $endpoint;
  private string $user;
  private string $password;

  public function __construct(string $endpoint, string $user, string $password)
  {
    $this-&gt;endpoint = $endpoint;
    $this-&gt;user = $user;
    $this-&gt;password = $password;
  }

  public function createOrderSender(): OrderSender
  {
     return new OrderSender($this-&gt;endpoint, $this-&gt;user, $this-&gt;password);
  }

  public function createItemSender(): ItemSender
  {
     return new ItemSender($this-&gt;endpoint, $this-&gt;user, $this-&gt;password);
  }
}

function createSenderFactory(string $env, array $config): SenderFactory
{
  // the if has to go somewhere anyway
  // add some error handling too (missing config keys, unknown $env, etc.)
  if ($env === 'testing') {
    return new SenderFactory($config['API_ENDPOINT_TESTING'], 'testing', 'testing');
  } else {
    return new SenderFactory($config['API_ENDPOINT_PRODUCTION'], 'production', 'production');  
  }
}


// ...


$config = loadConfigFromJsonFile($configPath);
$factory = createSenderFactory($env, $config);
$orderSender = $factory-&gt;createOrderSender();
$itemSender = $factory-&gt;createItemSender();
```