zend-frameworkzend-validatezend-filter

Zend Framework - Application Structure - Location of Custom Filters and Validators


I have already written several custom validators and filters. I put them in the library like this:

/library
    /My
        /Filter
            /FilterName.php
        /Validate
            /ValidateName.php
    /Zend
    /Zendx

I now am writing a validator that I want to be "application aware". It will use application-level configuration values. I see two possibilities for this, each with their own set of questions.

ONE: Place code in the /application directory. What directory structure is standard/recommended?

TWO: Place code in the /library directory structure. What is the preferred way to pass configuration options to the validator?


Solution

  • At the risk of not answering your question, I don't usually make my lower-level classes - like filters and validators, as in your question - application-aware in the sense that I make available to them the entire app-config.

    Rather, I try to identify precisely which parts of app-config they need and pass those pieces to the filter/validator as constructor arguments.

    This serves two benefits:

    1. It clearly identifies the dependencies
    2. I can then use the filter/validator on other projects which may have a wholly different app-config structure.

    As an example, suppose my custom validator needs to know some list of email addresses to whitelist when performing its validation; and that this whitelist is stored in application.ini config as:

    whitelist[] = "good1@example.com"
    whitelist[] = "good2@example.com"
    

    and that this app-config object is stored in the Zend_Registry under key 'config'.

    I could make my validator access that info by using:

    $config = Zend_Registry::get('config');
    $whitelist = $config['whitelist'];
    // use the whitelist
    

    But this is, IMO, terrible. I can't unit-test the validator since it pulls the config info out of the ether.

    Alternatively, I could pass the entire app config to the validator in its constructor:

    $validator = new My_Validate_ValidateName($config);
    

    At least now, when I want to test the validator, I can pass in different $config objects/arrays and it's clear that the validator depends upon something.

    But I think this is giving the validator more info than he needs. Further, he needs to know how to access the whitelist from the app-config. That info might vary from project to project. And, in any case, it's not easy to see directly that the validator needs only the whitelist of email addresses.

    In my view, the best thing is:

    $config = Zend_Registry::get('config');
    $whitelist = $config['whitelist'];
    $validator = new My_Validate_ValidateName($whitelist);
    

    Now, it's clear to me what the validator needs. It doesn't matter where he gets it - from app-config, from a remote service, from whatever. It is the consumer of the validator that has the responsibility to provide the validator with what he needs.

    If the consumer of that validator, for example, is a form, then the form needs to know how to get that whitelist somehow. The same principle applies: give him what he needs in his constructor. When I finally get up to the controller level, I consider myself at "app-level". At that point, I feel comfortable expecting the controller to know where he can find his app-config and how to access its internal data.

    Just my own take on it. YMMV. ;-)

    UPDATE

    As for location, I tend to place them based upon intended usage. That is, if I plan to use them cross-project, then I place them in library. If I plan to use them only in this application, then I place them in application.