Are injectable classes allowed to have constructor parameters in DI?

Given the following code:

class ClientClass{

    public function print(){
        //some code to calculate $inputString
        $parser= new Parser($inputString);
        $result= $parser->parse();
    }
}

class Parser{
    private $inputString;
    
    public __construct($inputString){
        $this->inputString=$inputString;
    }
    public function parse(){
        //some code
    }
}

Now the ClientClass has dependency on class Parser. However, if I wanted to use Dependency Injection for unit testing it would cause a problem because now I can’t send the input string to the parser constructor like before as its calculated inside ClientCalss itself:

class ClientClass{
        private $parser;
        public __construct(Parser $parser){
            $this->parser=$parser;
        }
        public function print(){
            //some code to calculate $inputString
            $result= $this->parser->parse(); //--> will throw an exception since no string was provided

        }
}

The only solution I found was to modify all my classes that took parameters in their constructors to utilize Setters instead (example: setInputString()).
However, I think there might be a better solution than this because sometimes modifying existing classes can cause much harm than benefit.

So,

  • Are injectable classes not allowed to have input parameters?
  • If a class must take input parameters in its constructor, what would be the way to inject it properly?

UPDATE
Just for clarification, the problem happens when in my production code I decide to do this:

$clientClass= new ClientClass(new Parser($inputString));//--->I have no way to predict $inputString as it is calculated inside `ClientClass` itself.

UPDATE 2
Again for clarification, I’m trying to find a general solution to the problem not for this example code only because some of my classes have 2, 3 or 4 parameters in their constructors not only one.

3

In the old code, the ClientClass constructs a Parser. So minimal change would be to inject a parser factory, not an instance. The factory can have any arguments you need and obviously can pass them to the constructor of created class.

To give an example, the code in question should be modified along the lines of:

class ClientClass{
    private $parserFactory;
    public __construct($parserFactory){
        $this->parserFactory=$parserFactory;
    }
    public function print(){
        $parser = $this->parserFactory($inputString)
        $result= $parser->parse();
    }
}

and called like:

new ClientClass(function($inputString) { return new Parser($inputString) });

(of course a named function may be used too). This is perfectly generic; you wrap the construction of the object you need in a function that will pass through any arguments you need, provide that to the dependent class and inside that class you’ll call the function instead of constructing the dependence directly. Of course the function you pass can create mock object instead or it can modify the arguments or hardcode some extra arguments or whatever you need.

If your language does not have function objects and lambda expressions, you can instead create a factory class. Where function objects are available, they are easier to write.

PS: I am not proficient in PHP, so I am not absolutely sure I don’t have syntax error in the example.

2

 > Are injectable classes allowed to have constructor parameters in DI?

In java/spring it is possible to have classes that require paramaters in the constructor as stated by @Jeff Vanzella.

However in you example it is more difficuilt to use di because the creation of the parser is not fixed- it depends on a non static context ($inputString).

One possible general soultion to this is: the parser class constructor gets a contextlocator parameter that knows how to get the context.

class Parser{
    private $contextLocator;

    public __construct($contextLocator){
        $this->contextLocator=$contextLocator;
    }
    public function parse(){
        $inputString = $contextLocator->getContext()
        //some code
    }
}   

But this aproach adds unneccessary complexity to your soulotion. The use of a init-method that defines the context (or functionlly equivalent the use of a property to set the context as you suggested) is much easier.

in you special example this is not necessary. Move the parameter from the constructor to the parse method.

class Parser{
    private $inputString;

    public __construct(){
    }
    public function parse($inputString){
        $this->inputString=$inputString;
        //some code
    }
}

3

Simple answer: Yes, they can have input parameters. That is how I usually use DI and IoC.

The injection is done as soon as you can in your program. As for testing, in your case, just inject a known string. For other classes, you would have to actually make the parameter an Interface and either inject a mock class that does something known, or a mock object created from a mocking framework, which there are numerous open source and paid frameworks.

There is a wealth of information here. Most of the code is in C#, but the ideas and theories behind it are well written

2

I realize this might be simplified example of what you deal with, but it seems that your print method (now assuming this is a code you work with and can change) does a little bit too much. To be precise, it calculates value it has to print. Moving that behaviour to separate construct (another dependency) will easily mitigate problem:

class ClientClass{
    private $parser;
    private $inputProvider;

    public __construct(InputProvider $inputProvider, Parser $parser){
        $this->inputProvider = $inputProvider;
        $this->parser = $parser;
    }

    public function print(){
        $input = $this->inputProvider->calculate();
        $result = $this->parser->parse($input);
    }
}

This way, not only you don’t have to change any existing code (Parser), but you gain little bit more in terms of lose coupling/separation of concerns. Printing does print, and input calculation logic (which can be unit tested separately, too) is delegated outside.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật