EDIT: Câu hỏi chính của tôi giờ đây đã trở thành 'Làm cách nào để có được ServiceManager với trình quản lý thực thể học thuyết vào bàn tay của biểu mẫu, phần tử và lớp đầu vào của tôi một cách rõ ràng?' Đọc để xem toàn bộ bài đăng.Cách tạo các đầu vào/phần tử biểu mẫu trong ZF2
Tôi sẽ cố gắng và yêu cầu bằng ví dụ ở đây để chịu đựng với tôi. Hãy cho tôi biết nơi tôi đang đi sai/phải hoặc nơi tôi có thể cải thiện
Tôi đang cố gắng tạo biểu mẫu đăng ký. Tôi có thể sử dụng mô-đun ZfcUser nhưng tôi muốn làm điều này một mình. Tôi đang sử dụng ZF2 với Doctrine2 cũng để dẫn tôi đi từ mô-đun đó một chút.
Chiến lược của tôi là điều này,
Tạo một lớp mẫu gọi là hình thức đăng ký
Tạo 'tố' các lớp riêng biệt cho mỗi phần tử trong đó mỗi phần tử sẽ có một đặc điểm kỹ thuật đầu vào
Vì mỗi phần tử là một lớp riêng biệt từ biểu mẫu, tôi có thể kiểm tra từng phần tử một cách riêng biệt.
Tất cả có vẻ tốt cho đến khi tôi muốn thêm trình xác thực vào phần tử tên người dùng sẽ kiểm tra xem tên người dùng đó chưa được sử dụng hay chưa.
Đây là mã vậy, đến nay
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'
)
));
}
}
tôi loại bỏ rất nhiều điều mà tôi nghĩ là không cần thiết. Đây là phần tử tên người dùng của tôi bên dưới.
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.'
)
)
)
)
);
}
}
Bây giờ đây là validator của tôi
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;
}
}
Tại sao điều này có vẻ như là một ý tưởng tốt với tôi?
Nó có vẻ như một lựa chọn tốt/tái sử dụng để làm vì tôi có thể tái sử dụng các yếu tố riêng biệt trên ứng dụng của tôi nếu cần thiết.
Tôi có thể kiểm tra từng đầu vào được tạo bởi từng yếu tố để đảm bảo đầu vào chấp nhận/từ chối đầu vào chính xác.
Đây là ví dụ về kiểm tra đơn vị của tôi cho các phần tử
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;
}
}
}
Vấn đề tôi đang gặp là validator không thể tìm nạp UserHelper đúng cách, mà thực sự là một UserRepository từ học thuyết . Lý do điều này xảy ra là do các trình xác nhận hợp lệ chỉ truy cập vào ValidatorPluginManager như một ServiceManager thay vì có quyền truy cập vào ServiceManager ứng dụng rộng.
Tôi gặp lỗi này cho phần Trình xác thực, mặc dù nếu tôi gọi cùng một phương thức nhận trên trình quản lý dịch vụ chung, nó hoạt động mà không có vấn đề gì.
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
var_dump ($ serviceManager) trong trình xác nhận cho tôi biết đây là lớp ValidatorPluginManager.
Tôi đã thử đặt một nhà máy ở mục service_manager như vậy
'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;
}
)
nhưng điều đó không làm việc vì nó không có ý kiến của quản lý dịch vụ mức ứng dụng.
Vì vậy, tổng thể, đây là những câu hỏi của tôi:
là chiến lược này tách các hình thức và các yếu tố một tốt nhất? Tôi có nên tiếp tục theo cách này không? Lựa chọn thay thế là gì? (Tôi cho phá vỡ công cụ lên vì lợi ích của testability) Tôi sẽ thử nghiệm ONLY hình thức bản thân ban đầu với một sự kết hợp của tất cả các yếu tố đầu vào nhưng nó có vẻ như tôi muốn được cố gắng để làm quá nhiều.
Làm cách nào để giải quyết vấn đề tôi có ở trên?
Tôi có nên sử dụng các phần Form/Element/Input của Zend theo một cách khác mà tôi không thấy không?
Bạn đã đã kiểm tra [docs] (http://zf2.readthedocs.org/en/latest/modules/zend.form.quick-start.html) về biểu mẫu? Tôi đặc biệt khuyên bạn nên sử dụng Chú thích vì đây là cách nhanh nhất để tạo biểu mẫu. –
@DanielM Tôi đã xem các tài liệu bạn đã đề cập nhưng câu hỏi 'làm cách nào để tôi kiểm tra từng đầu vào một cách riêng biệt?' vẫn còn. Với phương pháp chú thích tôi sẽ nhận được một hình thức hoàn toàn nhận ra đúng không? Vì vậy, tôi sẽ không bị buộc phải kiểm tra bằng cách sử dụng kết hợp đầu vào EVERY? –
Vâng, tôi không kiểm tra chúng. Tôi không nghĩ rằng thử nghiệm được yêu cầu ở đây bởi vì các lớp phần tử chính nó được kiểm tra, các trình duyệt tính hợp lệ được kiểm tra và các bộ lọc đầu vào cũng vậy. Tất nhiên, nếu bạn tạo một lớp Element mới cho một mục đích đặc biệt không phù hợp với các phần tử hiện có, bạn nên tạo các trường hợp thử nghiệm mới. Nếu không, tiền phạt của nó. Và có, các biểu mẫu được tạo bằng cách sử dụng chú thích có thể được hiển thị hoàn toàn mà không cần phải làm gì ngoại trừ 'echo $ this-> formCollection ($ myForm);' bên trong khung nhìn nếu bạn không cần bất kỳ hiển thị tùy chỉnh nào. –