Jump to content

Injecting arguments in constructors


NotionCommotion

Recommended Posts

Doing the following is concise and allows a common constructor to be inherited, but I think I am doing it too much. 

  • Should it ever be done?
  • Should an object never be included in the associated array data?  Obviously, this isn't applicable for form data, but I've used this same approach where one class creates some objects and injects them in another class.
  • How does one get around constructors needing different signatures?
    public function __construct(array $formData, \PDO $pdo)
    {
        $this->validate($properties);
        foreach($formData as $key=>$value) {
            $this->$key=$value;
        }
        $this->pdo=$pdo;
    }

 

Link to comment
Share on other sites

Ever? Sure.

Include an object? I don't see a reason why one should "never" do that. It's not about the type of value but about what it represents (and passing a database thing is very normal).

Constructor signatures? You override them in child classes with whatever signature you want. Constructors aren't like normal methods.

Link to comment
Share on other sites

I think you have to be careful with the terminology you are employing.  An argument is by definition "injecting" variables into a function or method.   

In general the important distinction is how an argument is passed.  

  1. Passed by Value:  Changes to the argument don't change the original variable
  2. Passed by Reference:  Changes to the argument change the original variable

A fundamental change in PHP from version 4 to 5 was that all objects get passed by reference.   In PHP 4 you frequently had to employ the 'reference' operator.

 

So when the word "injection" gets used, it's in reference to "Dependency Injection".  Obviously that is large topic, but it's predicated on the idea that you will inject objects that a class might depend on via the constructor.  Since code in the class will reference this dependency, it should be a parameter and not passed in via an array.

Now in terms of your specific example having to do with form data, it is hard for me to see the value of what you are doing when form data exists within PHP in a super global ($_POST).  If you look at most of the frameworks, all of which have some support or solution for form building, validation and error handling, doing what you are doing is an anti-pattern.  What you see more of is the use of a Request object that gets the raw form data from the request, then applies validations and updating of model objects as required.  

Just mapping an array of variables into an object seems of limited value.

 

Link to comment
Share on other sites

Thanks guys,  I either never knew or knew once and forgot that constructors do not need the same signature.  The implications are huge, and passing objects in an array just to get around PHP complaining was difficult to read and troubleshoot.

@gizmola regarding request objects and anti-patterns, showing the $_POST super global was just an example, and I actually do something like the following.  I do feel passing data in an array to the constructor is okay as one might be creating an entity from form data or from values obtained from the database.  The part I didn't like was sneaking a couple of objects in the array who's purpose was DI, and now know that I don't need to do so.  Does it still look like I am doing an anti-pattern?

My old way of doing this is as follows:

$app->get('/sources', function (Request $request, Response $response) {
    $rs=$this->get('SourcesIndex')->read($request->getQueryParams());    //returns [data, status code]
    return $response->withJson($rs[0],$rs[1]);
});

$app->post('/charts/{chartId:[0-9]+}', function (Request $request, Response $response, $args) {
    $rs=$this->get('ChartFactory')->getByID($args['chartId'])->addPoint($request->getParsedBody()); //returns [data, status code]
    return $response->withJson($rs[0],$rs[1]);
});

My new way of doing this is as follows:

$app->get('/sources', function (Request $request, Response $response) {
    return $this->sourceResponder->detail($response, $this->sourceService->read($request->getQueryParams()));
});

$app->post('/charts/{chartId:[0-9]+}', function (Request $request, Response $response, $args) {
    $factory=$this->chartFactory->init($args['chartId']);
    $rs=$factory->getService()->addPoint($request->getParsedBody()); //returns an object
    return $factory->getResponder()->update($response, $rs);
});

 

Link to comment
Share on other sites

I'm glad you got the main point of my comments, being, don't try and hide dependencies inside an array you pass to the constructor.

Your examples look similar to the type of code often associate with micro frameworks like Lumen, slim or silex.  Looks fairly kosher to me given the limited context.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.