I want to know how can I validate array of arrays in symfony.
My validation rules are:
User - NotBlank
Date - Date and NotBlank
Present - NotBlank
So far I have done this:
$validator = Validation::createValidator();
$constraint = new Assert\Collection(array(
'user' => new Assert\NotBlank(),
'date' => new Assert\Date(),
'present' => new Assert\NotBlank()
));
$violations = $validator->validate($request->request->get('absences')[0], $constraint);
But the problem is that it only allows to validate single array eg.
$request->request->get('absences')[0].
Here is how the array looks like:
You have to put the Collection constraint inside All constraint:
When applied to an array (or Traversable object), this constraint allows you to apply a collection of constraints to each element of the array.
So, your code will probably look like this:
$constraint = new Assert\All(['constraints' => [
new Assert\Collection([
'user' => new Assert\NotBlank(),
'date' => new Assert\Date(),
'present' => new Assert\NotBlank()
])
]]);
Update: if you want to use annotations for this, it'll look something like this:
#Assert\All(
constraints={
#Assert\Collection(
fields={
"user"=#Assert\NotBlank(),
"date"=#Assert\Date(),
"present"=#Assert\NotBlank()
}
)
}
)
Related
While I was trying to show pictures I made this pleasant discovery in backpack:
$this->crud->addFields([
[ // Upload
'name' => 'pictures', //<-- this is an Entity
'label' => 'Photos',
'type' => 'upload_multiple',
'upload' => true,
'disk' => 'uploads'
]
]);
This fragment of code gives me this:
My questions is:
What am I doing wrong?
How can get the value 'file' of this two vectors? I need this for display the images.
You probably forgot to add 'photos' to the cast array.
Based on the documentation:
Step 3. Since the filenames are stored in the database as a JSON array, we're going to use attribute casting on your model, so every time we get the filenames array from the database it's converted from a JSON array to a PHP array:
protected $casts = [
'photos' => 'array'
];
https://laravel-backpack.readme.io/docs/crud-fields#upload_multiple
I want to use how to access the username and password fields from the below code.
AppBundle\Entity\MasterUserAccount Object
(
[id:AppBundle\Entity\MasterUserAccount:private] =>
[firstName:AppBundle\Entity\MasterUserAccount:private] =>
[lastName:AppBundle\Entity\MasterUserAccount:private] =>
[username:AppBundle\Entity\MasterUserAccount:private] => test
[password:AppBundle\Entity\MasterUserAccount:private] => 123456
[createdBy:AppBundle\Entity\MasterUserAccount:private] =>
[updatedBy:AppBundle\Entity\MasterUserAccount:private] =>
[createdAt:AppBundle\Entity\MasterUserAccount:private] =>
[updatedAt:AppBundle\Entity\MasterUserAccount:private] =>
[status:AppBundle\Entity\MasterUserAccount:private] =>
)
$data = $form->getData();
$username = $data['username'];
I'm getting the below error the following error
Cannot use object of type AppBundle\Entity\classname as array
The data that you get out of a symfony form is an Entity. You can't access an attribute of this entity, as you do for arrays.
Instead you should be using getter method defined inside class MasterUserAccount.
So. It should be:
$username = $data -> getUserName();
This is assuming that getter method is already defined inside MasterUserAccount class. If not, create a getter method first.
Here's what I have:
In my route I create a default entity. "startdate" and "enddate", both date objects.
/**
* #Route("/vacature/nieuw", name="create_vacancy")
*/
public function createVacancyAction(Request $request)
{
$vacancy = new Vacancy();
$vacancy->setStartdate(new \DateTime())
->setEnddate(new \DateTime());
$form = $this->createForm(VacancyType::class, $vacancy);
// check if valid and persist or whatever
}
In my VacancyType I set the date constraint for both my date fields like so:
->add("startdate", DateType::class, array(
"widget" => "single_text",
"constraints" => array(
new Date(array(
"message" => "vacancy.date.message"
)),
new GreaterThanOrEqual("today")
)
))
The dates are pre-filled in html in a yyyy-mm-dd format which is how I want them to.
Then, without editing the html field I receive this error upon submitting the form:
found it! seemed I tried the constraint new GreaterThanOrEqual("startdate"). Thinking it would refer to my startdate....sadly it doesn not :(
In a Symfony 2.4+ project, what is the best way to register an array of values for a field that saves as an integer but needs to display human readable values in a template?
I have an entity with a property that is populated with integer values that represent different constant values:
/**
* The repetition frequency for billing cycle:
* #ORM\Column(type="smallint")
*/
protected $repetition = 0;
I would like to store the names of these values somewhere, so initially I put them in my entity with a getter:
protected $repetitionName = array(
0 => 'Setup',
1 => 'Second',
2 => 'Minute',
3 => 'Hour',
4 => 'Day',
5 => 'Week',
6 => 'Month',
7 => 'Year'
);
public function getRepetitionName() {
return $this->repetitionName;
}
This seems like a great central repository for the values.
Then in my twig template I don't want to display the integer, I want the corresponding name value. So I translate them like this:
<div class="billingCycle">{{ entity.repetitionName[entity.repetition] }}</div>
And in my form builder I make a field that references that array like this:
$builder->add('repetition', 'choice', array(
'label' => 'Billing Cycle',
'help' => 'The repetition frequency when this service is billed.',
'choices' => $builder->getData()->getRepetitionNamePer(),
// default to monthly (the most common)
'empty_data' => 6,
'required' => TRUE
));
The Problems With This Approach
1. Translation: If I want to translate this at any point, it's hard coded in one place.
2. Reusability: If I have other entities that have repetition (e.g. event calendar) it would be nice to reuse this.
3. Configurability: Ideally these would be editable in a config file instead of the entity code.
Alternative Solution: Custom Form Type as Global Service with Config Parameters
The better option seems to set some default parameters in the config file:
parameters:
gutensite_component.options.status:
0: Inactive
1: Active
gutensite_component.options.repetition:
0: Setup
1: Second
2: Minute
3: Hour
4: Day
5: Week
6: Month
7: Year
Then create a custom form type Gutensite\ComponentBundle\FormType\RepetitionType that loads the options from the config parameters. See the Documentation for a great example of this. Then just refer to that field type like this:
$builder->add('repetition', 'repetition', array(
'label' => 'Billing Cycle',
'help' => 'The repetition frequency when this service is billed.',
// default to monthly (the most common)
'empty_data' => 6,
'required' => TRUE
));
The inconvenient part of this solution, is that you have to either parameter to twig in your config (which is bloat for every template even if you don't need it), or always remember to manually pass the parameters to twig from your controller.
// I add to the standard object `$controller->view` which gets passed to Twig
$controller->view->options['repetition'] = $this->container->getParameter('gutensite_component.options.repetition');
To be accessed like:
<div class="priceValue label label-primary">${{ entity.price }}/<span class="billingCycle">{{ view.options.repetition[entity.repetition] }}</span></div>
This is more clunky than I would like but it is reusable. Maybe others have better solutions to pass the configuration to twig than what is represented here.
Other Suggestions?
Do you have any other suggestions, best practices or lessons learned? Please share.
What I would do is to save those values as objects of a new entity and set a manyToOne relation from your main entity (or any other entity as your calendar event entity) to the repetition entity
If so, you can easily add new repetitions every time you want or get all objects of the main entity using any specific repetition.
Also you can build a nice form for a new object of the main entity with an input (human readable) of repetition values:
$builder->add('repetition', 'entity', array(
'class' => 'AcmeDefaultBundle:Repetition', // This is your new 'repetition entity'
'property' => 'repetitionName', // The field of your 'repetition entity' that stores the name (the one that will show a human readable value instead of the id)
'expanded' => true, // True if you prefer checkbox instead of a dropdown list
'label' => 'Billing Cycle',
'help' => 'The repetition frequency when this service is billed.',
'required' => true,
));
Now when you want to show the name of the repetition in twig you will use:
<div class="billingCycle">{{ entity.Repetition.repetitionName }}</div> (you can also translate that value later)
A cleaner way (if you use it only for this entity) is to define a public method in your entity that returns you that array:
public function getRepetitionNames() {
return array(
0 => 'Setup',
1 => 'Second',
2 => 'Minute',
3 => 'Hour',
4 => 'Day',
5 => 'Week',
6 => 'Month',
7 => 'Year'
);
}
Another method to retrieve the label based by your "repetition" field value:
/**
* #param $key
* #return null
*/
function getRepetitionLabel(){
$repetitions = $this->getRepetitionNames();
return isset($repetitions[$this->repetition]) ? $repetitions[$this->repetition] : 0;
}
Will be much easier to access it in twig now:
<div class="billingCycle">{{ entity.repetitionLabel }}</div>
Last, in your form use your entity to retrieve the values:
$object = $builder->getData();
$repetitionChoices = $object->getRepetitionNames();
$builder->add('repetition', 'choice', array(
'label' => 'Billing Cycle',
'help' => 'The repetition frequency when this service is billed.',
'choices' => $repetitionChoices
'empty_data' => 6,
'required' => TRUE
));
If you plan to use it in more entities, you could use a interface.
How do I access the fields in a node in Drupal 7.
I have tried this but that do not work.
$node=node_load($nid);
$node->field_num[LANGUAGE_NONE][0]['value']=$num;
I think I have to be more specific:
I first create a node and set values on some fields like this:
$values = array(
'type' => 'scorings',
'uid' => $user->uid,
'status' => 1,
'comment' => 0,
'promote' => 0,
);
$entity = entity_create('node', $values);
$ewrapper = entity_metadata_wrapper('node', $entity);
$entity->field_rond_nid[LANGUAGE_NONE][0]['value']=$nid_scorekort;
$entity->field_golfid[LANGUAGE_NONE][0]['value']=$form_state['values']['golfid_1'];
$ewrapper->save(true);
entity_save('node', $entity);
$nid=$entity->nid;
This works fine. Then I want to access this node from another function (passing the nid to it) end set value to another field (field_score_1). I have tried this:
$node=node_load($nid, 'my_content type');
$node->field_score_1[LANGUAGE_NONE][]['value'] = $my_value;
But this do not work. Seams that node_load do not give me access to the fields.
Your node_load() call is incorrect.
From the Drupal API documentation for node_load() the function declaration is:
node.module node_load($nid = NULL, $vid = NULL, $reset = FALSE)
Your second parameter is a string, not a number, as $vid would be.
If node_load() returns a FALSE then it failed.
Perhaps you were wanting to use EntityFieldQuery() instead?