Zend Framework collection validation - php

I am using Zend Framework 3 and I'm trying to validate a form with a collection field.
My form has a field
$this->add([
'name' => 'domains',
'options' => [
'target_element' => [
'type' => Text::class
]
],
'type' => Collection::class
]);
When I submit the form I obtain something like this as POST data
[
'domains' => [
0 => 'first'
1 => 'second'
]
]
I am trying to validate this with a CollectionInputFilter like the following
$filter = new InputFilter();
$filter->add([
'type' => CollectionInputFilter::class,
'options' => [
'input_filter' => [
'validators' => [
[
'name' => Hostname::class
]
]
]
]
], 'domains');
$filter->setData($data);
but I obtain the exception Zend\InputFilter\CollectionInputFilter::setData expects each item in a collection to be an array or Traversable; invalid item in collection of type string detected.
What am I doing wrong?

I found out that the error was in using CollectionInputFilter. I should have been using ArrayInput instead.

Related

TYPO3 BE TCA type Preview Image

i search for a Solution:
How can i add a Preview Image for a TCA type?
Example: I have 3 different types and would like to display a preview image for them. The same as the t3 backend layouts.
Just like the Backend-Layout:
Maybe there is a solution to this?
The documentation is explaining it:
https://docs.typo3.org/m/typo3/reference-tca/main/en-us/Columns/Examples.html#select-drop-down-for-records-represented-by-images
This is the example code:
[
'columns' => [
'select_single_12' => [
'label' => 'select_single_12 foreign_table selicon_field',
'config' => [
'type' => 'select',
'renderType' => 'selectSingle',
'foreign_table' => 'tx_styleguide_elements_select_single_12_foreign',
'fieldWizard' => [
'selectIcons' => [
'disabled' => false,
],
],
],
],
],
]
And the code for the field of the connected table is this:
[
'ctrl' => [
'title' => 'Form engine elements - select foreign single_12',
'label' => 'fal_1',
'selicon_field' => 'fal_1',
// ...
],
'columns' => [
// ...
'fal_1' => [
'label' => 'fal_1 selicon_field',
'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
'fal_1',
[
'maxitems' => 1,
],
$GLOBALS['TYPO3_CONF_VARS']['SYS']['mediafile_ext']
),
],
],
// ...
];
As you have a strange label inside your field it's not clear if you want to link to an image, to a text or even to a field that offers a combination like it's done with relations to the table sys_file by the intermediate table sys_file_ref.
So defining more precise what you need exactly might help to give you a more detailed answer. You can edit your answer to add this description.

Livewire encountered corrupt data when trying to hydrate the [data-table] component, when trying to send closure to livewire component

I tried to send some closure to the livewire component inside a nested array but it produce this error:
Livewire encountered corrupt data when trying to hydrate the [data-table] component. Ensure that the [name, id, data] of the Livewire component wasn't tampered with between requests.**
What I sent to the component :
<livewire:data-table
:model="$modelClass"
:custom="[
[
'label' => 'E-Mail',
'column'=> 'email'
],
]"
:exclude="['password', 'email_verified_at', 'remember_token', 'updated_at']"
:include="[
[
'label' => 'Role',
'column'=> 'role.name',
'format'=> fn($value, $row) => '<strong>'.ucwords($value).'</strong>',
'formatType' => 'html'
],
[
'label' => 'Search Engine',
'links' => [
[
'title' => fn($row) => $row->name.' Google',
'link' => fn($row) => 'https://google.com/search?q='.$row->name,
'type' => 'button',
]
],
],
[
'label' => 'Social Media',
'links' => [
[
'title' => 'Facebook',
'link' => 'https://facebook.com',
'type' => 'link'
],
[
'title' => 'Instagram',
'link' => 'https://instagram.com',
'type' => 'link'
]
]
],
[
'label' => 'Email Provider',
'links' => [
[
'title' => function($row){
if(str_contains($row->email, 'gmail')){
return 'Google';
}elseif(str_contains($row->email, 'yahoo')){
return 'Yahoo';
}else{
return 'Unidentified';
}
},
'class' => 'cursor-pointer',
'onclick' => 'return false',
]
]
]
]"
/>
Then i check in ComponentCheckshumManager class, my array that contains the closure become empty when go through Hashing using json_encode.
Before Hashing :
Data before hashing
After Hashing :
Data after hashing
This error happens only when refreshing the component, is there any correct way to send closure to the livewire component? Please help.
Depends on name. If it's an attribute, then issue is somewhere else, if it's a magic function, then you have a problem. Each time a template modifies original data, you will get corrupt data. Even if it's $user->full_name magic function, it will corrupt original data.

Populate label or attribute of form element in Zend Framework 3

I'm still fairly new to ZF3 so forgive me if I'm asking an obvious question here, but after many searches, looks through the source and head scratching, I can't seem to find an obvious approach to populating label text with data from the entity.
Basically, I have a form collection containing form elements which are each stored with a type (ID), e.g. "Business phone", "Mobile phone", etc.
Is there a way to populate anything other than a value in a form element?
Edit (more info)
So, there is a PersonForm, with a Person Fieldset which contains a Phone Fieldset collection:
$phoneFieldset = new PhoneFieldset($objectManager);
$this->add([
"type" => Element\Collection::class,
"name" => "Phones",
"options" => [
"count" => 0,
"should_create_template" => true,
"allow_add" => true,
"allow_remove" => true,
"target_element" => $phoneFieldset
],
]);
This Phone fieldset contains the following elements:
$this->add([
"name" => "Type_ID",
"type" => "hidden",
]);
$this->add([
"name" => "Number",
"type" => "text",
"attributes" => [
"placeholder" => "Enter phone number",
],
"options" => [
"label" => "Email" // Ideally this would be $entity->getTypeName() for example, which would return the name based on the Type_ID mapped against a constant
]
]);
Sure, adding label information for a formCollection (Fieldset or Collection elements) is pretty much the same as for input elements (Element) (Element docs).
Some examples:
Add a Fieldset into a Form ($this->formCollection($form->get('address'))):
Docs: https://docs.zendframework.com/zend-form/element/collection/
$this->add(
[
'type' => AddressFieldset::class, // Note: FQCN -> provided by FormElementManager
'name' => 'address',
'required' => true,
'options' => [
'use_as_base_fieldset' => false,
'label' => _('Address'),
'label_options' => [
// .. add options for the label, see LabelInterface
],
'label_attributes' => [
// .. add attributes for the label, see LabelInterface
],
],
]
);
Renders as:
<fieldset>
<legend>Address</legend>
<!-- the inputs / labels of `Element` objects -->
</fieldset>
Add a Collection into a Form ($this->formCollection($form->get('cities'))):
Docs: https://docs.zendframework.com/zend-form/element/collection/
$this->add(
[
'name' => 'cities',
'type' => Collection::class,
'options' => [
'label' => _('Cities'),
'should_create_template' => true,
'allow_add' => true,
'allow_remove' => true,
'count' => 1,
'target_element' => $this->getCityFieldset(), // Must be an instantiated Fieldset (so provide via Factory)
'label_options' => [
// .. add options for the label, see LabelInterface
],
'label_attributes' => [
// .. add attributes for the label, see LabelInterface
],
],
'attributes' => [
'class' => 'fieldset-collection',
'data-fieldset-name' => _('City'),
],
]
);
Renders as:
<fieldset class="fieldset-collection" data-fieldset-name="City">
<legend>Cities</legend>
<fieldset><!-- add a <legend> using JS here, with the data-fieldset-name of the parent -->
<!-- the inputs / labels of `Element` objects -->
</fieldset>
<span data-template="<!-- contains entire template so you can use JS to create 'add' and 'remove' buttons for additional CityFieldset <fieldset> elements -->"></span>
</fieldset>
I added in the <!-- comments --> in the HTML output, you can figure those out ;-)
Additionally, if you're using an ORM, Doctrine in this example, then you could do it like this:
$this->add(
[
'name' => 'roles',
'required' => true,
'type' => ObjectMultiCheckbox::class,
'options' => [
'object_manager' => $this->getObjectManager(),
'target_class' => Role::class,
'property' => 'id',
'label' => _('Roles'),
'label_generator' => function ($targetEntity) {
/** #var Role $targetEntity */
return $targetEntity->getName();
},
'label_options' => [
'label_position' => FormRow::LABEL_APPEND,
],
'use_hidden_element' => true,
'checked_value' => 1,
'unchecked_value' => 0,
],
'attributes' => [
'class' => 'form-check-input',
],
]
);
Doctrine Form Elements docs

Create Associative Array with Foreach, Insert into existing Associative Array

Hello.
I currently have a problem with the AWS Route-53 API. To create a record you need to call a function, which itself needs an array of inputs.
I want to create a record set here and for that I have some POST values. One of them, $_POST['record_value'], is a textarea and has multiple lines. I loop through them. This is to enable multiple values for one record. The code is as follows when you hardcode it as one value in ResourceRecords;
$result = $this->route53->changeResourceRecordSets([
'ChangeBatch' => [
'Changes' => [
[
'Action' => 'CREATE',
'ResourceRecordSet' => [
'Name' => $recordName,
'ResourceRecords' => [
[
'Value' => $recordValue
],
],
'TTL' => $recordTtl,
'Type' => $recordType,
],
],
],
'Comment' => 'Routing Record Set',
],
'HostedZoneId' => $this->zone,
]);
Hower. I want to make ResourceRecords dynamically. For every line in the textarea I need a new set of the following part of the code;
[
'Value' => $recordValue
],
What I thought is the following;
$newData = [];
foreach(explode("\r\n", $recordValue) as $valLine) {
$newData[] = ["Value" => $valLine];
}
$result = $this->route53->changeResourceRecordSets([
'ChangeBatch' => [
'Changes' => [
[
'Action' => 'CREATE',
'ResourceRecordSet' => [
'Name' => $recordName,
'ResourceRecords' => [
$newData
],
'TTL' => $recordTtl,
'Type' => $recordType,
],
],
],
'Comment' => 'Routing Record Set',
],
'HostedZoneId' => $this->zone,
]);
However, this seems to return an exception: Found 1 error while validating the input provided for the ChangeResourceRecordSets operation:↵[ChangeBatch][Changes][0][ResourceRecordSet][ResourceRecords][0] must be an associative array. Found array(1).
Am I building the array wrong or am I doing this wrong alltogether?
$newData is already an array, you don't need to wrap it in another array.
'ResourceRecords' => $newData,

zend framework 3 Select tag validation

I am getting the error:
The input was not found in the haystack
After form post. Please see the selection tag code lines below:
// Add "roles" field
$this->add([
'type' => 'select',
'name' => 'roles',
'attributes' => [
'multiple' => 'multiple',
'options'=>$this->role_desc,
'inarrayvalidator' => false,
'class'=>'form-control'
],
'options' => [
'label' => 'Role(s)',
],
]);
// Add input for "roles" field
$inputFilter->add([
'class' => ArrayInput::class,
'name' => 'roles',
'required' => true,
'haystack'=>$this->role_ids,
'filters' => [
['name' => 'ToInt'],
],
'validators' => [
['name'=>'GreaterThan', 'options'=>['min'=>1]],
['name'=>'InArray', 'options'=>['haystack'=>$this-
>role_ids]]
],
]);
The InArray seems to be validating well, lm just no sure what is bringing up the exception. Thank you in advance.
Actually , your issue is similar to link
To solve this, change your validators definition to:
'validators' => [
['name'=>'GreaterThan', 'options'=>['min'=>1]],
[
'name' => 'Explode',
'options' => array(
'validator' => [
'name'=>'InArray',
'options'=> [
'haystack'=>$this->role_ids
]
]
)
]
],
Unfortunately, I do not think there is a "cleaner" way to do this.
Alternately, Maybe you could use the MultiCheckbox.

Categories