How to translate data models by the means of Symfony? - forms

I would like to present another description for a general use case.
Form fields (or form types) can be generated like the following.
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class registration_form extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('address_street');
}
}
?>
The label “Address street” is accordingly displayed then on a test web page so far.
I would like to achieve that translated information will be shown on demand.
Thus I imagine that I need to pass dedicated parameters for the execution environment so that translated data will be retrieved from selected information sources and applied instead of the specified input field name.
Would you like to add any further ideas for such an application according to known key words?
national language support
internationalisation
localisation
translation
See also:
Symfony forms for Translatable Doctrine entities
How will the chances evolve to improve the software documentation for the involved function arguments so that data models (and corresponding form fields) can be translated in easier and safer ways?

I don't know if you took a look into FormType Field Reference.
You can use that configuration:
// instead of 'label' you can use 'label_format'
$builder->add('address_street', null, [
'label_format' => 'form.%name%',
]);
And Then, add the following code to your translations file:
form:
address_street: Your Translated Label # 'address_street' key replaced %name%

Related

How to share functionality between controllers in Symfony when dealing with forms?

Let's imagine that we want to build a simple cms application in Symfony, we are going to code the functionality to "crud" the posts and then we are going to display that data in a custom format using twig and css so it looks appealing to our users, obviously we have to make it easy to look for a specific post by adding search functionality.
So we create the search form by using a form class so we can reuse the form later:
<?php
namespace App\Form;
use App\Entity\Post;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\Type;
use Symfony\Component\Form\Extension\Core\Type\SearchType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class SearchForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('search_texfield', SearchType::class, array(
'attr' => array(
'placeholder' => 'Search ...',
),
'label' => false,
))
->add('search_button', SubmitType::class, array(
'label' => 'Search',
));
}
}
?>
The problem that i am facing is that i have to create the same form per controller, [home controller, results controller, some controller...], basically every view to which the user has access must have the search functionality or Symfony will launch $search_form is not defined basically because the header which contain the search form is shared to all the views as all of them extends base.layout.twig so the next block of code is repeated per view.
$search_form = $this->createForm(SearchForm::class);
return $this->render('some.view.twig', [
'search_form' => $search_form->createView(),
...
]);
What could be an approach to share this form without having to define it per controller?
As mentioned before - Embedded controllers are one way to go. Just be careful to not use too many of them as they can be expensive.
Second option is defining service and including it as global to your templates (you stated you need it everywhere). How to do it is described
https://symfony.com/doc/current/templating/global_variables.htm. This service then can create this form and provide it to template. With this approach you can have one service, which will provide form and second service which will provide setting filtering criteria (for example on Doctrine ORM).

Symfony disable form fields depending on user rol

I'm developing an app in symfony for follow the workflow of a document. In the lifecycle of the document, take part various departments, I mean, people of each department with his own role inside de app (ROLE_USER, ROLE_SYSTEMS...). I have the same form for all of them but in the different states of the lifecycle of the document one of them has to complete specific fields and the rest will be disable or readonly.
I want to know how is the best way to do this in Symfony, check the role and disable the fileds the user can't edit in every moment of the lifecycle.
I have investigated and find something like this for my twig templates, but I will have to do this for each field and each role and I don't know if I can apply this to field attributes like disabled or readonly, is it?.
{{% if is_granted('ROLE_ADMIN') %}
Delete
{% endif %}
I also heard about voters but I don't have very clear how it works and if it is appropriate for my situation.
What do you think?
Easy but ugly way would be different form type classes (just to play around to find out which fields are necessary and which aren't, but it's optional).
The better way would be FormEvents like PRE_SET_DATA where you could add/remove (not sure if modifien also available).
Look here to find out more -> How to Dynamically Modify Forms Using Form Events
Basically you should try following:
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Add your general fields which are available for all
//$builder->add(...)
// at the end add an EventListener
$builder->addEventListener(FormEvents::PRE_SET_DATA, [$this, 'onPreSetData']);
}
and in the same form-class create the onPreSetData method:
public function onPreSetData(FormEvent $formEvent)
{
$form = $formEvent->getForm();
$entity = $formEvent->getData();
//if user is admin then $form->add(...) like above in with $buildForm->add(...)
}

What alternatives are there to Yii active form?

I wish to build a form that does not create/update any active records. An example of such a form would be a search filter using check boxes for the user to select which categories to apply to the search.
Everything I read about forms in Yii is centred around the CActiveForm class. What is the Yii way to build forms that don't use active records?
If you want to embrace Yii's convenient form handling, you should use CActiveForm. It does not require CActiveRecord. But it always requires a model for your form data - which is a good thing, because this will keep the validation rules out of your view files. Instead of a CActiveRecord you could also build a simple model class from CFormModel.
class SomeForm extends CFormModel
{
public $name;
public $email;
public function rules()
{
return array(
array('name,email','required'),
array('email','email'),
);
}
}
Check the docs of the CHtml class. While it contains all the active* method, there are plain form methods in there as well, such as checkBox() or checkBoxList() that sound like what you're looking for.

Symfony 2.x Form Field Name

When I render a form, form Filed Name is given as an array. For example: search[item], search[keyword] etc. where search is name of the form.
I'm not great on working with forms but I think, the name should be rendered as simply, name="item" or name="keyword".
I've looked at all the documentation, customizing form rendering topic etc. but I can't find any way to change the default behaviour of Symfony form to render form filed name from 'search[item]' to 'item'.
This way, when I ask for the POST data, I can ask simply $this->getRequest()->request->get('item'), as I have to deal with lots of individual parameters.
Help would be great i) To figure out how to achieve what I want. ii) to let me know, why the name is rendered this way. is this the good practice?
Rather than accessing parameters from the Request object, you can bind the Request object to the form.
For example, in your controller method that you post your form to:
namespace Acme\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Acme\Form\MyFormClass;
class MyFormController extends Controller
{
receiveFormAction(Request $request)
{
$form = new MyFormClass();
// you can specify that a route only accepts a post
// request in the routing definition
if ($request->isMethod('POST')) {
// this populates the form object with the data
// from the form submission
$form->bind($request);
if ( ! $form->isValid()) {
throw new \Exception('Invalid form');
}
// an array of the data the format you require
$data = $form->getData();
$data['item'];
$data['keyword'];
// etc.
}
}
}
The above is the way you should be handling forms in Symfony 2, and is how you can leverage the power that the forms component gives you, with validation etc.
Symfony supports multiple forms on a page. They might be instances of the same form or have similar field names. Having the fields for each form all together in an array makes this easy to do.

symfony2 forms custom fields

So, I have a form for editing blog articles.
Among other things I need to be able to edit article tags. They are stored as ArrayCollection inside my Blog entity. (ManyToMany cascade: persist,remove)
Now, Simfony handles this type of data with <select> tag and it works just fine for selecting, but I want to be able to remove and add tags too.
This is also possible and is very well explained in this Cookbook article: How to Embed a Collection of Forms
However, result of this tutorial is still not very elegant and I would love to have input box similar to StackOverflow tag box.
Since there are many already done solutions under free licences I decided to just use one of them, for example jQuery Tags Input.
Basically, all I need to do is run $('#tags_input_box').tagsInput() and it transforms it into SO-like tag box.
Now, I'm searching for the easiest way to bind some custom made input to my form and submit it back together with the rest of 'genuine' fields in a shape that will be understood by Symfony2.
Could anyone refer me to some document or give me some starting info where I should begin my research on this matter ?
It appears that plugin sends it in as a comma-separated string value.
Probably the easiest way would be to simply treat it as a single input in your form, and then split it up when you process the form.
// Entity to hold it in string form.
namespace Some\Entity;
class TagStringEntity {
protected $tagString;
// getTagString and setTagString
}
// Custom form type.
// Use this AbstractType in your form.
namespace Some\Form;
Symfony\Component\Form\AbstractType;
class TagType extends AbstractType {
public buildForm(FormBuilder $builder, array $options) {
$builder->add('tagString'); // will default to text field.
}
}
// In Controller
public function displayFormAction() {
// Join the tags into a single string.
$tagString = implode(',', $article->getTags()); // assuming it returns an array of strings.
$tagStringType = new TagStringType();
$tagStringType->setTagString($tagString);
// build form, etc...
}
public function checkFormAction() {
// ...
if ($form->isValid()) {
// Get the tag string, split it, and manually create your separated tag objects to store.
}
}
That's probably the cleanest and simplest way to do it using that jQuery plugin. Takes a bit of working around since you are turning multiple items into many and vice versa, but not too bad.