Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8530005
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T09:09:29+00:00 2026-06-11T09:09:29+00:00

EDIT : My main question has now become ‘How do I get the ServiceManager

  • 0

EDIT : My main question has now become ‘How do I get the ServiceManager with the doctrine entity manager into the hands of my form, element, and input classes in some clean way?’ Read on to see the full post.

I’m going to try and ask by example here so bear with me. Let me know where I’m going wrong/right or where I could improve

I’m trying to create a registration form. I could use ZfcUser module but I want to do this on my own. I’m using ZF2 with Doctrine2 as well so that leads me away from that module a bit.

My strategy was this,

  1. Create a form class called registration form

  2. Create separate ‘element’ classes for each element where each element will have an input specification

  3. Since each element is a separate class from the form I can unit test each one separately.

All seemed fine until I wanted to add a validator to my username element that would check that the username is NOT is use yet.

Here is the code thus far

namepsace My\Form;

use Zend\Form\Form,
    Zend\Form\Element,
    Zend\InputFilter\Input,
    Zend\InputFilter\InputFilter,

/**
 * Class name : Registration
 */
class Registration
    extends Form
{

    const USERNAME     = 'username';
    const EMAIL        = 'email';
    const PASSWORD     = 'password';
    const PASS_CONFIRM = 'passwordConfirm';
    const GENDER       = 'gender';
    const CAPTCHA      = 'captcha';
    const CSRF         = 'csrf';
    const SUBMIT       = 'submit';

    private $captcha = 'dumb';

    public function prepareForm()
    {
        $this->setName( 'registration' );

        $this->setAttributes( array(
            'method' => 'post'
        ) );

        $this->add( array(
            'name'       => self::USERNAME,
            'type'       => '\My\Form\Element\UsernameElement',
            'attributes' => array(
                'label'     => 'Username',
                'autofocus' => 'autofocus'
            )
            )
        );

        $this->add( array(
            'name'       => self::SUBMIT,
            'type'       => '\Zend\Form\Element\Submit',
            'attributes' => array(
                'value' => 'Submit'
            )
        ) );

    }

}

I removed a lot that I think isn’t necessary. Here is my username element below.

namespace My\Form\Registration;

use My\Validator\UsernameNotInUse;
use Zend\Form\Element\Text,
    Zend\InputFilter\InputProviderInterface,
    Zend\Validator\StringLength,
    Zend\Validator\NotEmpty,
    Zend\I18n\Validator\Alnum;

/**
 *
 */
class UsernameElement
    extends Text
    implements InputProviderInterface
{

    private $minLength = 3;
    private $maxLength = 128;

    public function getInputSpecification()
    {
        return array(
            'name'     => $this->getName(),
            'required' => true,
            'filters'  => array(
                array( 'name'       => 'StringTrim' )
            ),
            'validators' =>
            array(
                new NotEmpty(
                    array( 'mesages' =>
                        array(
                            NotEmpty::IS_EMPTY => 'The username you provided is blank.'
                        )
                    )
                ),
                new AlNum( array(
                    'messages' => array( Alnum::STRING_EMPTY => 'The username can only contain letters and numbers.' )
                    )
                ),
                new StringLength(
                    array(
                        'min'      => $this->getMinLength(),
                        'max'      => $this->getMaxLength(),
                        'messages' =>
                        array(
                            StringLength::TOO_LONG  => 'The username is too long. It cannot be longer than ' . $this->getMaxLength() . ' characters.',
                            StringLength::TOO_SHORT => 'The username is too short. It cannot be shorter than ' . $this->getMinLength() . ' characters.',
                            StringLength::INVALID   => 'The username is not valid.. It has to be between ' . $this->getMinLength() . ' and ' . $this->getMaxLength() . ' characters long.',
                        )
                    )
                ),
                array(
                    'name'    => '\My\Validator\UsernameNotInUse',
                    'options' => array(
                        'messages' => array(
                            UsernameNotInUse::ERROR_USERNAME_IN_USE => 'The usarname %value% is already being used by another user.'
                        )
                    )
                )
            )
        );
    }    
}

Now here is my validator

namespace My\Validator;

use My\Entity\Helper\User as UserHelper,
    My\EntityRepository\User as UserRepository;
use Zend\Validator\AbstractValidator,
    Zend\ServiceManager\ServiceManagerAwareInterface,
    Zend\ServiceManager\ServiceLocatorAwareInterface,
    Zend\ServiceManager\ServiceManager;

/**
 *
 */
class UsernameNotInUse
    extends AbstractValidator
    implements ServiceManagerAwareInterface
{

    const ERROR_USERNAME_IN_USE = 'usernameUsed';

    private $serviceManager;

    /**
     *
     * @var UserHelper
     */
    private $userHelper;
    protected $messageTemplates = array(
        UsernameNotInUse::ERROR_USERNAME_IN_USE => 'The username you specified is being used already.'
    );

    public function isValid( $value )
    {
        $inUse = $this->getUserHelper()->isUsernameInUse( $value );
        if( $inUse )
        {
            $this->error( UsernameNotInUse::ERROR_USERNAME_IN_USE, $value );
        }

        return !$inUse;
    }

    public function setUserHelper( UserHelper $mapper )
    {
        $this->userHelper = $mapper;
        return $this;
    }

    /**
     * @return My\EntityRepository\User
     */
    public function getUserHelper()
    {
        if( $this->userHelper == null )
        {
            $this->setUserHelper( $this->getServiceManager()->get( 'doctrine.entitymanager.orm_default' )->getObjectRepository( 'My\Entity\User') );
        }
        return $this->userHelper;
    }

    public function setServiceManager( ServiceManager $serviceManager )
    {
        echo get_class( $serviceManager );
        echo var_dump( $serviceManager );
        $this->serviceManager = $serviceManager;
        return $this;
    }

    /**
     *
     * @return ServiceManager
     */
    public function getServiceManager( )
    {
        return $this->serviceManager;
    }

}

Why did this seem like a good idea to me?

  1. It seemed like a good testability/re-use choice to make since I could re-use the elements separately across my application if need be.

  2. I could unit test each Input generated by each element to make sure it correctly accepts/rejects input.

This is the example of my unit test for the element

public function testFactoryCreation()
{
    $fac = new Factory();

    $element = $fac->createElement( array(
        'type' => '\My\Form\Registration\UsernameElement'
        ) );
    /* @var $element \My\Form\Registration\UsernameElement  */

    $this->assertInstanceOf( '\My\Form\Registration\UsernameElement',
                             $element );

    $input      = $fac->getInputFilterFactory()->createInput( $element->getInputSpecification() );
    $validators = $input->getValidatorChain()->getValidators();
    /* @var $validators \Zend\Validator\ValidatorChain */

    $expectedValidators = array(
        'Zend\Validator\StringLength',
        'Zend\Validator\NotEmpty',
        'Zend\I18n\Validator\Alnum',
        'My\Validator\UsernameNotInUse'
    );

    foreach( $validators as $validator )
    {
        $actualClass = get_class( $validator['instance'] );
        $this->assertContains( $actualClass, $expectedValidators );

        switch( $actualClass )
        {
            case 'My\Validator\UsernameNotInUse':
                $helper = $validator['instance']->getUserHelper();
                //HAVING A PROBLEM HERE
                $this->assertNotNull( $helper );
                break;

            default:

                break;
        }
    }

}

The problem I’m having is that the validator can’t fetch the UserHelper properly, which is really a UserRepository from doctrine. The reason this is happening is because the validators only get access to the ValidatorPluginManager as a ServiceManager rather than having access to the application wide ServiceManager.

I get this error for the Validator portion, although if I call the same get method on the general service manager it works with no problems.

1) Test\My\Form\Registration\UsernameElementTest::testFactoryCreation
Zend\ServiceManager\Exception\ServiceNotFoundException: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for doctrine.entitymanager.orm_default

The var_dump( $serviceManager ) in validator shows me it is of the class ValidatorPluginManager.

I tried putting a factory in the service_manager entry like so

'service_manager' => array(
                'factories' => array(
                    'My\Validator\UsernameNotInUse' => function( $sm )
                    {
                        $validator = new \My\Validator\UsernameNotInUse();
                        $em        = $serviceManager->get( 'doctrine.entitymanager.orm_default' );
                        /* @var $em \Doctrine\ORM\EntityManager */
                        $validator->setUserHelper( $em->getRepository( '\My\Entity\User' ) );

                        return $validator;
                    }
                )

but that didn’t work because it’s not consulting the application level service manager.

So, overall, here are my questions :

  1. Is this strategy of separating the form and elements a good one? Should I keep going this way? What are alternatives? ( I’m for breaking stuff up for the sake of testability ) I was going to test ONLY the form itself originally with a combination of ALL the inputs but it seemed like I’d be trying to do too much.

  2. How do I resolve the issue I have above?

  3. Should I be using the Form/Element/Input parts of Zend in some other way that I’m not seeing?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T09:09:31+00:00Added an answer on June 11, 2026 at 9:09 am

    this is my validator, using a static method to inject the entityManager and working with any doctine entity.

    <?php
    
    namespace Base\Validator;
    
    use Traversable;
    use Zend\Stdlib\ArrayUtils;
    use Zend\Validator\AbstractValidator;
    use Doctrine\ORM\EntityManager;
    
    class EntityUnique extends AbstractValidator
    {
        const EXISTS = 'exists';
    
        protected $messageTemplates = array(
            self::EXISTS => "A %entity% record already exists with %attribute% %value%",
        );
    
        protected $messageVariables = array(
            'entity' => '_entity',
            'attribute' => '_attribute',
        );
    
    
        protected $_entity;
        protected $_attribute;
        protected $_exclude;
    
        protected static $_entityManager;
    
        public static function setEntityManager(EntityManager $em) {
    
            self::$_entityManager = $em;
        }
    
        public function getEntityManager() {
    
            if (!self::$_entityManager) {
    
                throw new \Exception('No entitymanager present');
            }
    
            return self::$_entityManager;
        }
    
        public function __construct($options = null)
        {
            if ($options instanceof Traversable) {
                $options = ArrayUtils::iteratorToArray($token);
            }
    
            if (is_array($options)) {
    
                if (array_key_exists('entity', $options)) {
    
                    $this->_entity = $options['entity'];
                }
    
                if (array_key_exists('attribute', $options)) {
    
                    $this->_attribute = $options['attribute'];
                }
    
                if (array_key_exists('exclude', $options)) {
    
                    if (!is_array($options['exclude']) ||
                        !array_key_exists('attribute', $options['exclude']) ||
                        !array_key_exists('value', $options['exclude'])) {
    
                        throw new \Exception('exclude option must contain attribute and value keys');
                    }
    
                    $this->_exclude = $options['exclude'];
                }
            }
    
            parent::__construct(is_array($options) ? $options : null);
        }
    
        public function isValid($value, $context = null)
        {
            $this->setValue($value);
    
            $queryBuilder = $this->getEntityManager()
                ->createQueryBuilder()
                ->from($this->_entity, 'e')
                ->select('COUNT(e)')
                ->where('e.'. $this->_attribute . ' = :value')
                ->setParameter('value', $this->getValue());
    
            if ($this->_exclude) {
    
                $queryBuilder = $queryBuilder->andWhere('e.'. $this->_exclude['attribute'] . ' != :exclude')
                    ->setParameter('exclude', $this->_exclude['value']);
            }
    
            $query = $queryBuilder->getQuery();        
            if ((integer)$query->getSingleScalarResult() !== 0) {
    
                $this->error(self::EXISTS);
                return false;
            }
    
            return true;
        }
    }
    

    ie. i’m using it for theese form elements which are also tested and working fine:

    <?php
    
    namespace User\Form\Element;
    
    use Zend\Form\Element\Text;
    use Zend\InputFilter\InputProviderInterface;
    
    class Username extends Text implements InputProviderInterface
    {
        public function __construct() {
    
            parent::__construct('username');
            $this->setLabel('Benutzername');
            $this->setAttribute('id', 'username');
        }
    
        public function getInputSpecification() {
    
            return array(
                'name' => $this->getName(),
                'required' => true,
                'filters'  => array(
                    array(
                        'name' => 'StringTrim'
                    ),
                ),
                'validators' => array(
                    array(
                        'name' => 'NotEmpty',
                        'break_chain_on_failure' => true,
                        'options' => array(
                            'messages' => array(
                                'isEmpty' => 'Bitte geben Sie einen Benutzernamen ein.',
                            ),
                        ),
                    ),
                ),
            );
        }
    }
    

    When creating a new user

    <?php
    
    namespace User\Form\Element;
    
    use Zend\InputFilter\InputProviderInterface;
    use User\Form\Element\Username;
    
    class CreateUsername extends Username implements InputProviderInterface
    {
        public function getInputSpecification() {
    
            $spec = parent::getInputSpecification();
            $spec['validators'][] = array(
                'name' => 'Base\Validator\EntityUnique',
                'options' => array(
                    'message' => 'Der name %value% ist bereits vergeben.',
                    'entity' => 'User\Entity\User',
                    'attribute' => 'username',  
                ),    
            );
    
            return $spec;
        }
    }
    

    when editin an existing user

    <?php
    
    namespace User\Form\Element;
    
    use Zend\InputFilter\InputProviderInterface;
    use User\Form\Element\Username;
    
    class EditUsername extends Username implements InputProviderInterface
    {
        protected $_userId;
    
        public function __construct($userId) {
    
            parent::__construct();
            $this->_userId = (integer)$userId;
        }
    
        public function getInputSpecification() {
    
            $spec = parent::getInputSpecification();
            $spec['validators'][] = array(
                'name' => 'Base\Validator\EntityUnique',
                'options' => array(
                    'message' => 'Der name %value% ist bereits vergeben.',
                    'entity' => 'User\Entity\User',
                    'attribute' => 'username',
                    'exclude' => array(
                        'attribute' => 'id',
                        'value' => $this->_userId,  
                    ),
                ),    
            );
    
            return $spec;
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

My main.xml has 2 edit text for the user to insert values. And my
Edit: While this question has been asked and answered before ( 1 ), (
Edit 4: The main issue has been resolved - turned out the problem was
EDIT: My main code no longer works, should this function work? <script type=text/javascript src=jquery-1.7.2.js></script>
I want to create simple app able to edit images. Main view of app
Ok, i have 2 edit controls and a button in my main window; in
EDIT 07/14 As Bill Burgess mentionned in a comment of his answer, this question
Edit (updated question) I have a simple C program: // it is not important
quick question. I am trying to get C++ nailed down, and today I spent
This question is related to my other one and I hope to get some

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.