Software Design Question regarding DI Container

Hello everybody :smile:

TLDR: How to use the DI Container to inject services depending on values which are only known in runtime.

First of all let me swiftly explain what my service does:

I have a service called AlfredFTP which basically lets me check given (S)FTP Login data if they are correct or not.

I separated each check logic into their own connection variants which are

  • Plain FTP
  • FTP with implicit SSL/TLS
  • FTP with explicit SSL/TLS
  • SFTP

So in my AlfredFTP base class I basically do

      switch( $this->login_data->connection_type_id ) {
        case static::CONN_ID_FTP:
          $this->check_ftp_data();
          break;

        case static::CONN_ID_FTP_IMPLICIT:
          $this->check_implicit_ftp_data();
          break;

        case static::CONN_ID_FTP_EXPLICIT:
          $this->check_explicit_ftp_data();
          break;

        case static::CONN_ID_SFTP:
          $this->check_sftp_data();
          break;

Now in each of those functions I do some think like

    $ftp = new FTP( $this->categoryHelper );
    $is_valid = $ftp->is_valid( $this->login_data );

    if( $is_valid ):
        // more logic
    endif;

but as you see I “hardcoded” the new FTP( $this->categoryHelper ); part in there.

This is what I want to change to more easily make my service class testable via mocked services in phpunit.

But I just can’t get my head around how I should do that or how I should refactor my service class to make that possible because depending on the value present in $this->login_data->connection_type_id I want to have a object from a different class.

I am sure this is somehow possible so I really would appreciate if someone could enlighten me :smile:

1 Like

Thanks to the help of @ADmad in Slack/Discord I now found my solution in the registry pattern :smile:
http://rizqi.id/laravel-registry-pattern

2 Likes

Hi Kevin,
Thanks for posting this. I posted a Youtube video of converting the blog post code into a working CakePHP 5 DI setup here https://youtu.be/9B2dGXA5Krk

I think I’ve probably committed some coding faux pas by passing the controller back to the Stripe|Square|PaypalGateway classes but it shows the general idea.

LOL, I only just noticed your post was 3 years old. All the same thanks. I have been struggling to under stand DI and this helps.