Container Setter Side Effect

Hi… Try saying the subject 5 times fast :wink:

Having a container to reflect upon and wire up the class is really nice; however I question one problem that it seems to create: No parameters can be set when instantiated by the container, so it leads to two issues:

  1. Have to write a setter in place of the parameters passed at instantiation. This also mean the usage of the object becomes less clear (example of this in the second code block).
  2. Have public methods that need to run after certain passed dependencies are set.

Take the following code. BTW the use of the interface is questionable here as it is not really useful, but that is not the purpose of this post. The login() method needs the salt set before it runs. If the $salt was passed during instantiation then it would remove the need for the public function go($secret).

<?php
interface Auth
{
    function logout ();
}

class PDOAuth implements Auth
{
    protected $pdo;
    protected $session;
    protected $hashObj;
    protected $hash;
    protected $salt;
    protected $user;
    protected $username;
    protected $password;
    protected $redirect;
    protected $track;


    function __construct(DbFactory $pdo, SaltHash $hash, Session $session, TrackLogins $track, Redirect $redirect) {
        $this->pdo = $pdo;
        $this->hashObj = $hash;
        $this->session = $session;
        $this->track = $track;
        $this->track->getSession($session);
        $this->redirect = $redirect;
        $this->redirect->setRedirect('http://www.abc.com/login', FALSE);
    }
    
    public function go($secret ='2246521bcfa564587cc4daa138823878') {
        $this->setSalt($secret);
        $this->login();
    }

...

This is illustrated when the contain is used:

<?php
require_once("bucket.inc.php");

    function __autoload($class_name) {
        require_once $class_name . '.php';
    }
   $container = new bucket_Container(new DbFactory);
   $container->registerImplementation('Auth', 'PDOAuth');

   $auth = $container->get('Auth');  
   $auth->go('2246521bcfa564587cc4daa138823878');

Have I missed a different (better way) to handle this, or is this just the way it is?

Regards,
Steve

I haven’t looked into what bucket supports itself, but with the container I use you can do something like this:

$args = array('secret'=>'dsfsdf');
$auth = $container->get('Auth',$args);

The code is already reflecting on PDOAuth, so the names of the constructor variables are available. The container simply matches the keys in the passed 2nd argument to get() to any variable names and then populates any unknown variables from typehints. It means that variable constructor names are coupled with other areas of your code, but that was a sacrifice I was willing to make…

Hi robt,

Well it looks like bucket does not allow for this i.e.

[B]Fatal error[/B]:  Uncaught exception 'bucket_CreationException' with message 'Can't auto-assign parameter 'salt' for 'PDOAuth'' in ...

I guess I either have to switch containers, or rewrite my code a different way, or live with it.

Thanks,
Steve

DI forces you to make a strict distinction between creation time dependencies and run time dependencies. This is where your conflict lies. You need to either degrade your object (PDOAuth) to a transient object or you need to separate the variant and make it global to the scope of the container.

Where does $secret come from?

This is where closures come in handy, imo.

Instead of just registering an implementation with the container, you register a closure which returns an instance.

See a previous post of mine for an example.

Hi [COLOR=#FF6600][B]kyberfabrikken[/B][/COLOR],

Yes you reminded me of a post/article/blog that you wrote talking about this, but I failed to see it!

The secret comes in this way currently, which will be changed now because I am trying to force the contained object to handle run time and time dependencies.

I understand what you are saying, yet I don’t know yet how to do what you are saying

…or you need to separate the variant and make it global to the scope of the container.

The $secret currently comes just shortly after instantiating the PDOAuth class. ie.

 $auth = $container->get('Auth'); 
//$auth->go($secret)
   $auth->go('2246521aece564587cc4daa138823878');

Thank you for you help!

Steve

Hi Ren,

Yes your example of closures works really nicely for this; however, unfortunately I am not able to use PHP 5.3 for this project. I will however stash your approach and dust it off the first chance I can use PHP 5.3.

Thank you!

Regards,
Steve

Sorry I forgot to mention that I will try to work this out myself :slight_smile:

I understand what you are saying, yet I don’t know yet how to do what you are saying

Steve

this is the simplest and most straight forward solution.
all other approaches i can think of will put more complexity
in your or the container code.

it’s fine.

@ren
your example would be much more powerful if you’d pass
the container by default to the closure. :slight_smile:

If the closure requires the container, define it in the arguments


function(DependencyInjector $di)
{
.... ;
}

and the container will pass itself in.

Have made a few more variations of it too, lessening the reliance on Reflection.

Yes, I meant - is it a constant or is it only known after some time (For example, do you need a http request to know it)?

Hi,

It is a constant.

Rather than embed it in the object. I wanted to provide a more public way (without using a config file) to update the salt secret - for example when the owners of the application want everyone to log-in again without checking the hash stored in the session, and creating a new hash that is stored in the session.

Regards
Steve

In that case, I would suggest that you make it a class constant. You could use inheritance, if you want to separate the actual hash value from the code. If you want to to be able to regenerate the hash like that, you could put the hash in a database. I mean - You have to store it somewhere.

Yes the database is a good option duh duh duh :blush::slight_smile:

Thank you.
Steve