I have the following ZF form element.
$this->addElement('text', 'price', array(
'required' => true,
'label' => 'Price:',
'attribs' => array(
'title' => 'Please enter the value of your artwork'),
'filters' => array('Currency'),
'validators' => array(
array('NotEmpty', true, array(
'messages' => array(
Zend_Validate_NotEmpty::IS_EMPTY =>
"You must enter your artworks price"))),
array('Float', true, array(
'messages' => array(
Zend_Validate_Float::INVALID =>
"You must enter a valid price",
Zend_Validate_Float::NOT_FLOAT =>
"You must enter a valid price"))),
array('GreaterThan', true, array(
'min' => 0.99,
'messages' => array(
Zend_Validate_GreaterThan::NOT_GREATER =>
"You must enter a value of £1.00 or more"))))
));
The last validator is Zend_Validate_GreaterThan which has been set an error message, my problem is that the error message is not displayed on the form when this validator fails. All I get rendered is an empty unordered list!!
<ul>
<li></li>
</ul>
When I check the messages output by zend_form I get the error and the message.
array(1) {
["price"]=>
array(1) {
["notGreaterThan"]=>
string(39) "You must enter a value of £1.00 or more"
}
}
Does anyone know why the message is not being rendered on the form?
Many thanks in advance
Garry
EDIT
The only decorator I am using is a viewscript to render the form, on the form I have.
$this->setDecorators(array(
array('ViewScript', array('viewScript' => 'forms/add-item.phtml'))
));
and the viewscript itself.
$attribFilterObj = new Freedom_Zend_Filter_HtmlAttribs();
$attribs = $attribFilterObj->filter($this->element->getAttribs());
?>
<form <?php echo $attribs; ?>>
<dl>
<?php echo $this->element->ArtworkTitle->title->render(); ?>
<?php echo $this->element->ArtworkDescription->description->render(); ?>
<?php echo $this->element->price->render(); ?>
<?php echo $this->element->Genres->render(); ?>
<?php echo $this->element->image->render(); ?>
<?php echo $this->element->add->render(); ?>
</dl>
</form>
EDIT
The output of the var_dump is as follows
array(5) {
["Zend_Form_Decorator_ViewHelper"]=>
object(Zend_Form_Decorator_ViewHelper)#157 (6) {
["_buttonTypes":protected]=>
array(3) {
[0]=>
string(24) "Zend_Form_Element_Button"
[1]=>
string(23) "Zend_Form_Element_Reset"
[2]=>
string(24) "Zend_Form_Element_Submit"
}
["_helper":protected]=>
NULL
["_placement":protected]=>
string(6) "APPEND"
["_element":protected]=>
NULL
["_options":protected]=>
array(0) {
}
["_separator":protected]=>
string(2) "
"
}
["Zend_Form_Decorator_Errors"]=>
object(Zend_Form_Decorator_Errors)#158 (4) {
["_placement":protected]=>
string(6) "APPEND"
["_element":protected]=>
NULL
["_options":protected]=>
array(0) {
}
["_separator":protected]=>
string(2) "
"
}
["Zend_Form_Decorator_Description"]=>
object(Zend_Form_Decorator_Description)#159 (6) {
["_escape":protected]=>
NULL
["_placement":protected]=>
string(6) "APPEND"
["_tag":protected]=>
NULL
["_element":protected]=>
NULL
["_options":protected]=>
array(2) {
["tag"]=>
string(1) "p"
["class"]=>
string(11) "description"
}
["_separator":protected]=>
string(2) "
"
}
["Zend_Form_Decorator_HtmlTag"]=>
object(Zend_Form_Decorator_HtmlTag)#160 (7) {
["_encoding":protected]=>
NULL
["_placement":protected]=>
NULL
["_tag":protected]=>
NULL
["_tagFilter":protected]=>
NULL
["_element":protected]=>
NULL
["_options":protected]=>
array(2) {
["tag"]=>
string(2) "dd"
["id"]=>
array(1) {
["callback"]=>
array(2) {
[0]=>
string(22) "Zend_Form_Element_Text"
[1]=>
string(16) "resolveElementId"
}
}
}
["_separator":protected]=>
string(2) "
"
}
["Zend_Form_Decorator_Label"]=>
object(Zend_Form_Decorator_Label)#161 (6) {
["_placement":protected]=>
string(7) "PREPEND"
["_tag":protected]=>
NULL
["_tagClass":protected]=>
NULL
["_element":protected]=>
NULL
["_options":protected]=>
array(1) {
["tag"]=>
string(2) "dt"
}
["_separator":protected]=>
string(2) "
"
}
}
This is sometimes caused by forgetting to include 'Errors' in the form decorator for the element. If you're using a custom decorator, check that first.
a bit old but check this site http://zendguru.wordpress.com/2008/12/04/handling-zend-framework-form-error-messages/
i believe you have to get the error messages yourselve like and then print them
$errorsMessages = $this->form->getMessages();
I had the same problem, I was only using a ViewScript as you are. This solved it:
($this is in the form class I created)
$this->setDecorators(array(
array('ViewScript',
array('viewScript' => '/formElementViewscripts/editRoughDraft/_form.phtml')),
'Form'
));
You must also add the default 'Form' decorator to your form if you want to be able to receive those messages. I tried looking through the code but I couldn´t pinpoint exactly why.
Related
First issue is I have the following validators and public function in my table
UsersTable.php
$validator
->scalar('name')
->maxLength('name', 45)
->requirePresence('name', 'create')
->notEmptyString('name', 'You must enter a name for the user.');
$validator
->add('name', 'custom', array('rule' => 'checkExistingUser', 'message' => 'This user already appears to be in the system.', 'on' => 'create'));
public function checkExistingUser($value,$context)
{
return $this->find('all', ['conditions' => ['Users.name' => $context['data']['name'], 'Users.user_type_id' => $context['data']['user_type_id']]])->count() < 1 ;
}
When I save the form below I receive the message "Method checkExistingUser does not exist". Why doesn't it recognize the method when it's clearly defined in the table model? Am I missing something?
add.ctp
<?php echo $this->Form->create($user);?>
<fieldset>
<legend><?php echo __('Add User'); ?></legend>
<?php
echo $this->Form->control('name', ['type' => 'text']);
echo $this->Form->control('user_type_id');
echo $this->Form->control('owner', array('type' => 'text', 'label' => "Owner Name"));
echo $this->Form->control('owner_contact', array('type' => 'text', 'label' => "Owner Contact (phone, email etc)"));
echo $this->Form->control('description', ['type' => 'textarea']);
echo $this->Form->control('ia_exception', array('type' => 'text', 'label' => "IA Exception Number"));
echo $this->Form->control('is_manual', array('type' => 'checkbox', 'label' => "Password Updated Manually"));
echo $this->Form->control('Environment', ['type' => 'select', 'multiple' => 'true', 'label' => 'Environment(s)']);
?>
</fieldset>
<div class="buttons">
<?php
echo $this->Form->button('Save', ['type'=> 'submit', 'name' => 'submit']);
echo $this->Form->button('Cancel', ['type' => 'button', 'name'=>'cancel', 'onClick' => 'history.go(-1);return true;']);
echo $this->Form->end();
?>
</div>
UsersController.php
function add() {
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->set('The user has been saved');
return $this->redirect(array('action' => 'index'));
} else {
$this->Flash->set('The user could not be saved. Please, try again.');
}
}
$userTypes = $this->Users->UserTypes->find('list');
$changeSteps = $this->Users->ChangeSteps->find('list');
$environments = $this->Users->Environments->find('list');
$this->set(compact('user','userTypes', 'changeSteps', 'environments'));
}
Second issue is when I try to submit my form to check that the validator is working correctly for an empty name field I don't receive the message 'You must enter a name for the user'. Instead I receive a message stating 'This field is required'. Why is it not showing my message from notEmptyString? And where is 'This field is required' coming from?
For the first issue, I had to add a provider in my validator.
I changed
$validator
->add('name', 'custom', array('rule' => 'checkExistingUser', 'message' => 'This user already appears to be in the system.', 'on' => 'create'));
To this
$validator
->add('name', 'custom', ['rule' => 'checkExistingUser', 'provider' => 'table', 'message' => 'This user already appears to be in the system.', 'on' => 'create']);
Be careful with custom methods for validation during patching, because Cake expects string to be returned, otherwise it will rendere default meassage.
So for example, if we use a custom validation function during patching
// in a Controller
$this->Users->patchEntity($user, $data, ['validate' => 'custom');
Same applies for closures.
// in UserTable.php
public function validationCustom(Validator $validator) {
$validator = $this->validationDefault($validator);
$validator
->minLength('password',8,'At least 8 digits');
$validator->add('password',
'strength_light',[
'rule' => 'passwordCheck',
'provider' => 'table',
'message' => 'At least a number and a capital letter'
]
);
return $validator;
}
public function passwordCheck ($value = "") {
return preg_match("/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&*-]).{8,}/",$value);
}
This will return default message and not the custom one ("At least..") because we set a callable not-cakephp function as rule for custom validation, so the message should be returned by the called function:
public function passwordCheck ($value = "") {
if (!preg_match("/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&*-]).{8,}/",$value))
return "At least a number and a capital letter";
}
so I'm trying to set a selected option in my form but I can't seem to find out how to do this. I've Googled around and everything seems to be for Symfony2 where default was a thing, this seems to be no longer the case for Symfony4.
I've tried using data and empty_data but both don't select the correct value..
# weirdly, setting to ['guru'] gets undefined index error,
# setting to $options doesn't error
->add('guru', EntityType::class, array(
'class' => User::class,
'choice_label' => 'username',
'data' => $options['guru']
))
and how I pass $options:
$form = $this->createForm(EditCategoryType::class, array('guru' => $guruName));
So with the help of #Juan I. Morales Pestana I found an answer, the only reason I've added the below as an answer rather than marking his as correct was because there seems to be a slight difference in how it works now..:
Controller now reads (Thanks to #Juan):
$category = $this->getDoctrine()->getRepository(Category::class)->find($id);
$category->setGuru($category->getGuru());
$form = $this->createForm(EditCategoryType::class, $category);
My EditCategoryType class:
->add('guru', EntityType::class, array(
'class' => User::class,
'choice_label' => 'username',
'mapped' => false,
'data' => $options['data']->getGuru()
))
updated twig template:
{{ form_widget(form.guru, { 'attr': {'class': 'form-control'} }) }}
<a href="{{ path('register_new', { idpackage: p.id }) }}" class="btn_packages">
//sends to form type the package id
$fromPackage = '';
if($request->query->get('idpackage')) {
$fromPackage = $request->query->get('idpackage');
}
$form = $this->createForm(RegisterFormType::class, $register, ['fromPackage' => $fromPackage]);
in formType set the param in options:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Register::class,
'fromPackage' => null
]);
}
->add('package',EntityType::class, [
'label' => 'Select one item',
'class' => Package::class,
'choice_label' => function($package) {
return $package->getTitle() . ' | crédits : ' . $package->getAmount();
},
'attr' => ['class' => 'input-text', ],
'placeholder' => '...',
'required' => false,
'choice_attr' => function($package) use ($idFromPackage) {
$selected = false;
if($package->getId() == $idFromPackage) {
$selected = true;
}
return ['selected' => $selected];
},
])
$parentCategory = $categoryRepository->repository->find(2);
$category = new Category();
$category->setParentCategory(parentCategory);
$form = $this->createForm(CategoryType::class, $category);
we chose the predefined top category, it works if you use it this way.
try this :
empty_data documentation
As I said in my comments you are doing something wrong. I will explain all the process:
calling the form in the controller
$person = new Person();
$person->setName('My default name');
$form = $this->createForm('AppBundle\Form\PersonType', $person);
$form->handleRequest($request);
then the createForm function is executed here is the code
Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait
protected function createForm($type, $data = null, array $options = array())
{
return $this->container->get('form.factory')->create($type, $data, $options);
}
As you can see the data or options are nos setted directly in the form, another function is called and then the form is created
This is the result when I make a dump inside the PersonType
PersonType.php on line 20:
array:35 [▼
"block_name" => null
"disabled" => false
"label" => null
"label_format" => null
"translation_domain" => null
"auto_initialize" => true
"trim" => true
"required" => true
"property_path" => null
"mapped" => true
"by_reference" => true
"inherit_data" => false
"compound" => true
"method" => "POST"
"action" => ""
"post_max_size_message" => "The uploaded file was too large. Please try to upload a smaller file."
"error_mapping" => []
"invalid_message" => "This value is not valid."
"invalid_message_parameters" => []
"allow_extra_fields" => false
"extra_fields_message" => "This form should not contain extra fields."
"csrf_protection" => true
"csrf_field_name" => "_token"
"csrf_message" => "The CSRF token is invalid. Please try to resubmit the form."
"csrf_token_manager" => CsrfTokenManager {#457 ▶}
"csrf_token_id" => null
"attr" => []
"data_class" => "AppBundle\Entity\Person"
"empty_data" => Closure {#480 ▶}
"error_bubbling" => true
"label_attr" => []
"upload_max_size_message" => Closure {#478 ▶}
"validation_groups" => null
"constraints" => []
"data" => Person {#407 ▼ // Here is the data!!!
-id: null
-name: "My default name"
-salary: null
-country: null
}
]
As you can see the data is indexed at data so that is the reason why you get an undefined index error
So the proper way is to set the entity value from the controller or use your form as a service and call the repository and set the value using the data option which has not changed since version 2. My point is that you are using the form wrong.
Please change your code.
Hope it help
EDITED IN THE SYMFONY 4 WAY(with out namespaces bundles)
Let's see please, I have a Person Entity with a name just for this example
The controller
$person = new Person(); //or $personsRepository->find('id from request')
$person->setName('My default name');
$form = $this->createForm(PersonType::class, $person);
$form->handleRequest($request);
The form
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name',TextType::class,[
//'data' => 'aaaaa' // <= this works too
]);
}
The options array value which proves that you are accessing wrong
PersonType.php on line 20:
array:35 [▼
"block_name" => null
"disabled" => false
"label" => null
"label_format" => null
"translation_domain" => null
"auto_initialize" => true
"trim" => true
"required" => true
"property_path" => null
"mapped" => true
"by_reference" => true
"inherit_data" => false
"compound" => true
"method" => "POST"
"action" => ""
"post_max_size_message" => "The uploaded file was too large. Please try to upload a smaller file."
"error_mapping" => []
"invalid_message" => "This value is not valid."
"invalid_message_parameters" => []
"allow_extra_fields" => false
"extra_fields_message" => "This form should not contain extra fields."
"csrf_protection" => true
"csrf_field_name" => "_token"
"csrf_message" => "The CSRF token is invalid. Please try to resubmit the form."
"csrf_token_manager" => CsrfTokenManager {#457 ▶}
"csrf_token_id" => null
"attr" => []
"empty_data" => Closure {#480 ▶}
"error_bubbling" => true
"label_attr" => []
"upload_max_size_message" => Closure {#478 ▶}
"validation_groups" => null
"constraints" => []
"data" => Person {#407 ▼
-id: null
-name: "My default name" //Here is the data
-salary: null
-country: null
}
]
AppBundle is just another folder in my folder structure. Be pleased to test your self. The second parameter to the formCreate function is the entity or data not the options you are thinking that the options is the data.
I have TYPO3 7.6.18 and I am making ajaxDispatcher. I stay on final study. I trying to call $this->bootstrap->run( '', $this->configuration ); but it get an error. I can't know what this error is exactly. But I'm sure problem in this line.
My $this->configuration is:
array(8) {
["pluginName"] => string(7) "Piphoto"
["vendorName"] => string(5) "Istar"
["extensionName"] => string(7) "feFiles"
["controller"] => string(5) "Photo"
["action"] => string(4) "test"
["mvc"] => array(1) {
["requestHandlers"] => array(1) {
["TYPO3\CMS\Extbase\Mvc\Web\FrontendRequestHandler"] =>
string(48) "TYPO3\CMS\Extbase\Mvc\Web\FrontendRequestHandler"
}
}
["settings"] => array(2) {
["adminemail"] => string(15) "mvnaz#yandex.ru"
["pageShowPhotoId"] => string(2) "32"
}
["persistence"] => array(1) {
["storagePid"] => string(2) "31"
}
}
Action test is allowed in local_conf. The Vendor is set right, extension name, plugin and controller too.
Sorry)
["extensionName"]=>
string(7) "fefiles"
fefiles need Fefiles - uppercase!
Thank you all for help! )
I can't really find anything about this in the documentation.
I used Codeigniter a lot, and I used Ben Edmunds Ion auth mostly, and that was a bit easier for me, because there I was able to add a group insert function in the registration.
You can down vote this stupid question, but I can't find anything about this in the Sentry docs.
Here is my register code:
public function action_register()
{
$response = Response::forge();
// validation
$val = Validation::forge('registration');
$val->add_field('first_name', 'Username', 'required|trim|valid_string[alpha,spaces]');
//$val->add_field('first_name', 'Vezetéknév', 'required|');
$val->add_field('last_name', 'Keresztév', 'required');
$val->add_field('email', 'Email', 'required|valid_email');
$val->add_field('email_again', 'Email újra', 'required|valid_email|match_field[email]');
$val->add_field('password', 'Jelszó', 'required|min_length[5]');
$val->add_field('gender', 'Nemed', 'required');
$val->add_field('talent', 'Tehetséged', 'required');
$val->add_field('talent_level', 'Tehetségi szinted', 'required');
if($val->run()):
try
{
// register the user
$user = Sentry::user()->register(array(
'email' => Input::post('email'),
'password' => Input::post('password'),
'metadata' => array(
'first_name' => Input::post('first_name'),
'last_name' => Input::post('last_name'),
'gender' => Input::post('gender'),
'talent_level' => Input::post('talent_level'),
)
));
if($user):
//$email_data = array();
//echo Config::get('base_url'). "user/activate/". $user['hash'];
$email = Email::forge();
$email->from('my#email.me', Config::get('site_name'));
$email->to(Input::post('email'), Input::post('first_name'));
$email->subject('Regisztráció');
$email_data = array(
'name' => "Kedves " . Input::post('first_name'). "<br><br>",
'title' => "Üdvözöllek a ".Config::get('site_name')." oldalán" ."<br>",
'link' => 'Fiókod megerősítéséhez kérlek kattints ide'
);
$email->html_body(\View::forge('email/activation', array('email_data' => $email_data)));
$email->send();
$response->body(json_encode(array(
'status' => 'ok',
)));
else:
$data['errors'] = "error";
endif;
}
catch (SentryUserException $e)
{
$response->body(json_encode(array(
'status' => 'error',
'message' => array(
'email_taken' => $e->getMessage()
)
)));
}
else:
$response->body(json_encode(array(
'status' => 'error',
'message' => array(
'first_name' => $val->error('first_name') ? $val->error('first_name')->get_message() : null,
'last_name' => $val->error('last_name') ? $val->error('last_name')->get_message() : null,
'email' => $val->error('email') ? $val->error('email')->get_message() : null,
'email_again' => $val->error('email_again') ? $val->error('email_again')->get_message() : null,
'password' => $val->error('password') ? $val->error('password')->get_message() : null,
'gender' => $val->error('gender') ? $val->error('gender')->get_message() : null,
'talent' => $val->error('talent') ? $val->error('talent')->get_message() : null,
'talent_level' => $val->error('talent_level') ? $val->error('talent_level')->get_message() : null,
)
)));
endif;
return $response;
}
So my question is how can I make it save the user group selected?
Thank you.
This is taken from the Sentry Documentation; I think this is what you are after:
try
{
// option 1
$user->add_to_group(2);
// option 2
$user->add_to_group('editor');
}
catch (SentryUserException $e)
{
$errors = $e->getMessage(); // catch errors such as user already in group
}
Hey guys trying to declare a variable in CakePHP in the Fields Controller. This variable will display the template id from the template table, but the view is saying the variable is undefined even though we delared it in the controller. Temaplates has many fields and fields belongs to templates.
Here is the Fields Controller:
<?php
class FieldsController extends AppController{
public $uses = array('Template');
function add(){
$this->set('title_for_layout', 'Please Enter Your Invoice Headings');
$this->set('stylesheet_used', 'style');
$this->set('image_used', 'eBOXLogo.jpg');
$this->Session->setFlash("Please create your required fields.");
$templates = $this->Template->find('list');
//$current_template = $this->request->data['Field']['template_id'];
// right way to do it, but Template is undefined, and says undefined var
//$template = $this->request->data['Field']['template_id'];
// makes sense with the find, no errors, but still doesnt print in form, says undefined var
//$current_template = $this->request->data($template['Field']['template_id']);
if($this->request->is('post'))
{
$this->Field->create();
if ($this->Field->save($this->request->data))
{
if($this->request->data['submit'] == "type_1")
{
$this->Session->setFlash('The field has been saved');
$this->redirect( array('controller' => 'fields','action' => 'add'));
}
if($this->request->data['submit'] == "type_2")
{
$this->Session->setFlash('The template has been saved');
$this->redirect( array('controller' => 'templates','action' => 'index'));
}
}
else
{
$this->Session->setFlash('The field could not be saved. Please, try again.');
}
}
}
}
And here is our add view which adds fields:
<?php
echo $this->Form->create('Field', array('action'=>'add'));
echo $this->Form->create('Field', array('action'=>'add'));
echo $this->Form->input('name', array('label'=>'Name: '));
echo $this->Form->input('description', array('label'=>'Description: '));
//echo $this->Form->input('template_id',array('label'=>'Template ID: ', 'type' => 'select', 'options' => $templates));
echo $this->Form->input('template_id',array('label'=>'Template ID: ', 'type' => 'text', 'default'=> $templates));
//echo $this->Form->input('templates_id', array('label'=>'Template ID: ', 'type' => 'text', 'default' => $current_template['templates_id']));//this would be the conventional fk fieldname
echo $this->Form->button('Continue adding fields', array('name' => 'submit', 'value' => 'type_1'));
echo $this->Form->button('Finish adding fields', array('name' => 'submit', 'value' => 'type_2'));
echo $this->Form->end();
?>
You should try the following code:
<?php
class FieldsController extends AppController{
public $uses = array('Template', 'Field');
function add(){
$this->set('title_for_layout', 'Please Enter Your Invoice Headings');
$this->set('stylesheet_used', 'style');
$this->set('image_used', 'eBOXLogo.jpg');
$this->Session->setFlash("Please create your required fields.");
$templates = $this->Template->find('list', array('fields' => array('Template.id, Template.template_name' );
$this->set('templates', $templates);
//$current_template = $this->request->data['Field']['template_id'];
// right way to do it, but Template is undefined, and says undefined var
//comment: You should check the request data with in if condition
//$template = $this->request->data['Field']['template_id'];
// makes sense with the find, no errors, but still doesnt print in form, says undefined var
//$current_template = $this->request->data($template['Field']['template_id']);
if($this->request->is('post'))
{
$this->Field->create();
if ($this->Field->save($this->request->data))
{
if($this->request->data['submit'] == "type_1")
{
$this->Session->setFlash('The field has been saved');
$this->redirect( array('controller' => 'fields','action' => 'add'));
}
if($this->request->data['submit'] == "type_2")
{
$this->Session->setFlash('The template has been saved');
$this->redirect( array('controller' => 'templates','action' => 'index'));
}
}
else
{
$this->Session->setFlash('The field could not be saved. Please, try again.');
}
}
}
}
You view should looks like:
<?php
echo $this->Form->create('Field', array('action'=>'add'));
echo $this->Form->input('name', array('label'=>'Name: '));
echo $this->Form->input('description', array('label'=>'Description: '));
echo $this->Form->input('template_id',array('label'=>'Template ID: ', 'options' => $templates));
//echo $this->Form->input('template_id',array('label'=>'Template ID: ', 'type' => 'text', 'default'=> $templates));
//echo $this->Form->input('templates_id', array('label'=>'Template ID: ', 'type' => 'text', 'default' => $current_template['templates_id']));//this would be the conventional fk fieldname
echo $this->Form->button('Continue adding fields', array('name' => 'submit', 'value' => 'type_1'));
echo $this->Form->button('Finish adding fields', array('name' => 'submit', 'value' => 'type_2'));
echo $this->Form->end();
?>
Kindly check and verify if it is working for you or not.
You are missing $this->set('templates', $templates); after doing the find() for templates in your controller.