Get the message from assert in symfony template - symfony

I have a question related to Assert form validation in symfony. So I have :
/**
* #ORM\Column(type="string")
* #Assert\NotBlank(message="client.firstName.notBlank")
* #Assert\Length(
* min = 2,
* max = 50,
* minMessage = "client.firstName.invalid",
* maxMessage = "client.firstName.invalid"
* )
* #Assert\Regex(
* pattern = "/^[0-9]+$/i",
* htmlPattern = "^[0-9]+$",
* message="client.firstName.regex"
* )
*/
protected $firstName;
And in validators.yml :
client:
firstName:
notBlank: 'Not Blank'
invalid: 'Invalid'
regex: 'Regex'
In form I have :
<div class="form-group">
{{ form_label(form.firstName) }}
{{ form_widget(form.firstName) }}
<div class="invalid-feedback">
{{ 'client.firstName'|trans({}, 'validators') }}
</div>
</div>
When I try to submit the form I get the message : client.firstName. I need a way to get message from assert. Can you help me please ? Thx in advance.

You need add one other file for each your assert messages:
# app/Resources/translations/validators.en.yml
client.firstName.notBlank: Please enter your firt name.
......
I think this is not necessary:
<div class="invalid-feedback">
{{ 'client.firstName'|trans({}, 'validators') }}
</div>

Related

Did we migrate incorrectly? Validation not happening in forms migrated from Symfony 2.7 to 4.0

In code migrated from Symfony 2.7 to 4.0, validation no longer happens on my form, allowing bad data to pass through and cause a Doctrine constraint violation
I'm new to Symfony and was asked to migrate a 2.7 application to 4.0. I did this in steps (2.7->2.8->3.x->4.0) and addressed issues as they came up, but one thing that broke along the way is automatic form validation. In the original version, if I attempted to create a new user and left the fields blank, it would correctly flag those and pop up " must not be empty" messages in the UI. Now, it lets those past until it attempts to write to the database, at which point Doctrine barfs because the database not null constraints are violated.
I've tried to figure out what I'm doing wrong, but I don't have a firm grasp on how the form creation process and syntax has changed. All of the example documentation on validation in forms assumes the createFormBuilder() approach, and all my existing code uses createForm(). What am I missing?
Here's part of the user object associated with the form showing the #Assert statements that I expect to trigger validation warnings:
/**
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Domain\CoreBundle\Repository\UserRepository")
* #ORM\HasLifecycleCallbacks()
* #UniqueEntity(fields="email", message="This email address is already in usage")
* #UniqueEntity(fields="username", message="This username is already in usage")
*/
class User extends BaseUser implements JsonSerializable
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Assert\NotBlank(message="Email should not be empty")
* #Assert\Email(strict=true)
* #Assert\Length(max=150, maxMessage="Email should be less than {{ limit }} characters")
*/
protected $email;
/**
* #Assert\NotBlank(message="Username should not be empty")
* #Assert\Regex(
* pattern = "/^\d*[a-zA-Z][ a-zA-Z0-9\!\#\#\$\%\^\&\-\_\=\+\~\?\.]*$/i",
* message = "Username should include at least one letter"
* )
*/
protected $username;
/**
* #var string
*
* #Assert\NotBlank(message="First name should not be empty")
* #ORM\Column(name="first_name", type="string", length=255)
*/
protected $firstName;
/**
* #var string
*
* #Assert\NotBlank(message="Last name should not be empty")
* #ORM\Column(name="last_name", type="string", length=255)
*/
protected $lastName;
(rest of code omitted for conciseness)
And here's the addNew action from the controller (AdministratorController extends UserController):
/**
* Add new administrator
*
* #param Request $request
*
* #return Response
*/
public function addNewAction(Request $request)
{
$company = $this->getCurrentCompany();
$form = $this->createForm(AddAdministratorType::class, null,
array('current_user'=> $this->user, 'restricted_admin'=>$this->getRestrictedAdmin(), 'company'=>$company));
if ($request->getMethod() == Request::METHOD_POST) {
$form->handleRequest($request);
// check if the user already exists
$userManager = $this->get('fos_user.user_manager');
$user = $form->getData();
$oldUser = $userManager->findUserByUsername($user['email']);
if ($oldUser)
{
$alreadyExists = false;
if ($user["isSuperAdmin"] &&$oldUser->isGrantedSuperAdmin())
$alreadyExists = true;
if ($user["isCompanyAdmin"] && $oldUser->isGranted(UserRepository::ROLE_COMPANY_ADMIN, $company))
$alreadyExists = true;
if (!$user["isCompanyAdmin"] && !$user["isSuperAdmin"] && $oldUser->isGranted(UserRepository::ROLE_ADMIN,$company))
$alreadyExists = true;
if ($alreadyExists)
$form->get('email')->addError(new FormError('This email address is already in use'));
}
if ($form->isValid()) {
$user = $form->getData();
if ($oldUser) // if the user already exists, we just need to add the role
{
if (!$this->getUser()->isGrantedSuperAdmin() &&
!in_array($company->getId(), array_map(function($x){return $x->getId();}, $oldUser->getCompaniesWithRole())))
{
// the user isn't currently in this company and the user adding the role
// isn't a super admin, so we have to create a shadow user entry to hide
// the real user info from other in the company until the user logs into
// the company
$oldShadow=$this->em->getRepository(ShadowUser::class)->findOneBy(array("user" => $oldUser, "company"=>$company));
if (!$oldShadow)
{
$shadow = new ShadowUser();
$shadow->setUser($oldUser);
$shadow->setFirstName($user["firstName"]);
$shadow->setLastName($user["lastName"]);
$shadow->setCompany($company);
$shadow->setIsVydioUsed($user["isVydioUsed"]);
$shadow->setVydioRoomLink($user["vydioRoomLink"]);
$shadow->setCreatedDate(new \DateTime());
$this->em->persist($shadow);
}
}
if ($user["isSuperAdmin"])
{
$oldUser->addMyRole(UserRepository::ROLE_SUPER_ADMIN, $company);
$this->get('pp_mailer')->onAddNewRole($oldUser,UserRepository::ROLE_SUPER_ADMIN, $company );
}
if ($user["isCompanyAdmin"])
{
$oldUser->addMyRole(UserRepository::ROLE_COMPANY_ADMIN, $company);
$this->get('pp_mailer')->onAddNewRole($oldUser,UserRepository::ROLE_COMPANY_ADMIN, $company );
}
if (!$user["isSuperAdmin"] && !$user["isCompanyAdmin"])
{
$oldUser->addMyRole(UserRepository::ROLE_ADMIN, $company);
$this->get('pp_mailer')->onAddNewRole($oldUser,UserRepository::ROLE_ADMIN, $company );
}
$programRepo = $this->em->getRepository(ProgramUser::class);
foreach($user["programs"] as $program)
{
$oldRelation = $programRepo->findOneBy(array("user"=> $oldUser, "program"=>$program));
if (!$oldRelation)
{
$relation = new ProgramUser();
$relation->setUser($oldUser);
$relation->setProgram($program);
$relation->setCompany($company);
$this->em->merge($relation);
}
}
$this->em->persist($oldUser);
$this->em->flush();
}
else
{
$newUser = new User();
$newUser->setPassword($this->get('domain_core_service')->generatePassword());
$newUser->setDefaultCompany($company);
$newUser->setFirstName($user["firstName"]);
$newUser->setLastName($user["lastName"]);
$newUser->setEmail($user["email"]);
$newUser->setUsername($user["email"]);
$newUser->setEnabled($user["enabled"]);
$newUser = $this->em->getRepository('DomainCoreBundle:User')->addUserInSystem($userManager, $newUser);
$token = $this->get('domain_core_service')->generateToken();
$newUser->setConfirmationToken($token);
if ($user["isSuperAdmin"])
{
$newUser->addMyRole(UserRepository::ROLE_SUPER_ADMIN, $company);
$this->get('pp_mailer')->onAddNewUser($newUser,UserRepository::ROLE_SUPER_ADMIN, $company );
}
if ($user["isCompanyAdmin"])
{
$newUser->addMyRole(UserRepository::ROLE_COMPANY_ADMIN, $company);
$this->get('pp_mailer')->onAddNewUser($newUser,UserRepository::ROLE_COMPANY_ADMIN, $company );
}
if (!$user["isSuperAdmin"] && !$user["isCompanyAdmin"])
{
$newUser->addMyRole(UserRepository::ROLE_ADMIN, $company);
$this->get('pp_mailer')->onAddNewUser($newUser,UserRepository::ROLE_ADMIN, $company );
}
foreach($user["programs"] as $program)
{
$relation = new ProgramUser();
$relation->setUser($newUser);
$relation->setProgram($program);
$relation->setCompany($company);
$this->em->merge($relation);
}
$this->em->persist($newUser);
$this->em->flush();
}
return $this->redirect($this->generateUrl('domain_admin_show_all_administrators_page'));
}
}
return $this->render(
'DomainAdminBundle:Administrators:add-new.html.twig',
array(
'form' => $form->createView(),
'page_title' => 'Add New Administrator',
'currentSidebar' => $this->currentSideBar,
'currentSidebarItem' => $this->currentSidebarItem,
)
);
}
And the twig file for the form:
{% extends 'DomainAdminBundle::base-admin-layout.html.twig' %}
{% import '::widgets/form_errors.html.twig' as form_custom_errors %}
{% import '::widgets/label.html.twig' as form_custom_labels %}
{% block title %} My Application| {{ page_title }} {% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript" src="{{ asset('assets/scripts/admin-add-new.js') }}"></script>
{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" type="text/css" href="{{ asset('assets/styles/admin-add-new.css') }}">
{% endblock %}
{% block admin_main_content %}
<div class="content-block administrator-controller" ng-controller="AdministratorController">
<div class="content-title-bar">
<div class="pull-left">
<h2>{{ page_title }}</h2>
</div>
</div>
<div class="content-block" ng-controller="AdminController">
{{ form_start(form, {"attr": { "action":"{{ path('domain_admin_add_new_administrator_page') }}", 'enctype': 'multipart/form-data', "method":"POST", "novalidate":"novalidate", "autocomplete":"off", "class":"form-horizontal add-user", "ng-submit":"disableAddButton()" }}) }}
<div class="base-box info-block">
<div class="control-group">
<div class="controls">
{{ form_widget(form.enabled) }}
{{ form_label(form.enabled, 'Active') }}
</div>
</div>
{% if app.user.isGrantedSuperAdmin() %}
<div class="control-group">
<div class="controls">
{% set companyAdminValue = form.isCompanyAdmin.vars.checked ? 'true' : 'false' %}
{{ form_widget(form.isCompanyAdmin, { 'attr':{ 'ng-model':'adminForm.isCompanyAdmin', 'ng-init': 'adminForm.isCompanyAdmin=' ~ companyAdminValue } }) }}
{{ form_label(form.isCompanyAdmin, 'Company Admin') }}
{% set superAdminValue = form.isSuperAdmin.vars.checked ? 'true' : 'false' %}
{{ form_widget(form.isSuperAdmin, { 'attr':{ 'ng-model':'adminForm.isSuperAdmin', 'ng-init': 'adminForm.isSuperAdmin=' ~ superAdminValue } }) }}
{{ form_label(form.isSuperAdmin, 'Super Admin') }}
</div>
</div>
{% endif %}
<div class="control-group" ng-init="initMultiSelect(true)">
{{ form_custom_labels.widget(form.programs) }}
<div class="controls">
{{ form_widget(form.programs) }}
{{ form_custom_errors.widget(form.programs) }}
</div>
</div>
<div class="control-group">
{{ form_custom_labels.widget(form.firstName) }}
<div class="controls">
{{ form_widget(form.firstName) }}
{{ form_custom_errors.widget(form.firstName) }}
</div>
</div>
<div class="control-group">
{{ form_custom_labels.widget(form.lastName) }}
<div class="controls">
{{ form_widget(form.lastName) }}
{{ form_custom_errors.widget(form.lastName) }}
</div>
</div>
<div class="control-group">
{{ form_custom_labels.widget(form.email) }}
<div class="controls">
{{ form_widget(form.email) }}
{{ form_custom_errors.widget(form.email) }}
</div>
</div>
<div class="control-group">
{{ form_custom_labels.widget(form.timezone) }}
<div class="controls">
{{ form_widget(form.timezone) }}
{{ form_custom_errors.widget(form.timezone) }}
</div>
</div>
</div>
<div class="text-right">
<button id="add-admin-submit" type="submit" class="btn btn-do" ng-disabled="isDisabled">Add new administrator</button>
Cancel
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
</div>
{% endblock %}
If I leave all fields blank and click "Add New Administrator" it doesn't flag them as blank, instead passing them onto Doctrine. The expected behavior is that it flags them at the UI and doesn't attempt to write them to the database.
I'm sure I've created multiple crimes against Symfony as I've ramped up the learning curve, so go easy. Right now I'm just trying to address this narrow issue; refactoring to more elegantly fit Symfony 4 will have to wait for another day.
Thanks!
Looks like you want to validate the User class against the data from your request.
Have you set data_class option in your form type class?
It's required if you want to use validation rules from another class (as you marked your properties with some #Assert* annotations).
https://symfony.com/doc/current/forms.html#creating-form-classes
Another way to do validation is to choose validation rules right in your FormType.

best way customize field_error in symfony 3

i have a entity with path field
/**
* #var string
* #Assert\NotBlank(message="Please, upload scontrino/fattura della stufa acquistata.")
* #Assert\File(mimeTypes={ "application/pdf","image/png" ,"image/jpg","image/jpeg" })
* #ORM\Column(name="path_file", type="string", length=255)
*/
private $path;
i have this field in a form
->add('path', FileType::class, array('data_class' => null))
;
and in the twig file
<div class="row">
<div class="input-field col s12 ">
{{ form_errors(form.path) }}
{{ form_widget(form.path) }}
</div>
</div>
when i press submit button and i put i not allowed file now my message is
Il mime type del file non รจ valido ("application/zip"). I tipi permessi sono "application/pdf", "image/png", "image/jpg", "image/jpeg".
I want to change that message but i don't understand the best way to do that.
If i must do it in entity file or in form file or in twig file
You have to add:
mimeTypesMessage = "with the text you want", in the #Assert\File
in your #Assert\File of your entity
/**
* #var string
* #Assert\NotBlank(message="Please, upload scontrino/fattura della stufa acquistata.")
* #Assert\File(mimeTypes={ "application/pdf","image/png" ,"image/jpg","image/jpeg" }, mimeTypesMessage = "with the text you want")
* #ORM\Column(name="path_file", type="string", length=255)
*/
The symfony Reference

Details list in symfony2, from two bundles

I have little in the development of Symfony and I have a question: To show a list with details of two Bundles.
My project have a Owner, but can have 1 o more consultants. The Entity has been related but when the results are listed only can view the user id. How can see the user name?
I will attach a image with my entities.
Thanks,
View
Entities
I need show the name of the differents consultants in a project. These are users too. I have already related the owner of the project, but this consultant is a field in my entity.
Attachment images to reference, and the php and twig files content. See the image: Database relation, and view.
UserProjectController
public function showAction(UserProject $userProject, User $user) {
$id = $userProject->getId();
$em = $this->getDoctrine()->getManager();
$project = $em->getRepository('ProjectBundle:Project')->find($id);
$userProjects = $em->getRepository('ProjectBundle:UserProject')->findby(array('idproject' => $id, 'status' => '1'));
if (empty($userProjects)) {
return $this->redirectToRoute('userproject_new');
}
$users = $em->getRepository('UserBundle:User')->findby(array('id' => 1));
return $this->render('ProjectBundle:Userproject:show.html.twig', array(
'userProjects' => $userProjects, 'project' => $project, 'User' => $user,
));
}
Entity User
/**
* #ORM\OneToMany(targetEntity="ProjectBundle\Entity\UserProject", mappedBy="user")
*/
protected $uproject;
Entity UserProject
/**
* #ORM\ManyToOne(targetEntity="ProjectBundle\Entity\Project", inversedBy="userproject")
* #ORM\JoinColumn(name="project_id", referencedColumnName="id")
* #Assert\NotBlank()
*/
protected $idproject;
/**
* #ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="uproject")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* #Assert\NotBlank()
*/
protected $user;
Entity Project
/**
* #ORM\OneToMany(targetEntity="ProjectBundle\Entity\UserProject", mappedBy="idproject")
*/
protected $userproject;
View show.html.twig
{% for userProject in userProjects %}
<br>
<dl>
<dt><span class="text-primary">{{'User_id'|trans}}</span></dt>
<dd>
{{ userProject.user }}
</dd>
<br>
<dt><span class="text-primary">{{'Consultor_id'|trans}}</span></dt>
<dd>
{{ userProject.consultorId }}
</dd>
<br>
<dt><span class="text-primary">{{'Status'|trans}}</span></dt>
<dd>
{% if userProject.status == 1 %}
<span class="text-success">{% trans %}Enabled{% endtrans %}</span>
{% elseif userProject.status == 0 %}
<span class="text-danger">{% trans %}Disabled{% endtrans %}</span>
{% endif %}
</dd>
<br>
</dl>
{% endfor %}

Can't access every object property in Twig

I have a News entity with the next properties:
text
start_date
expire_date
Here's part of the class:
//News.php
/**
* #ORM\Column(type="string", length=200)
*/
private $text;
/**
* #ORM\Column(type="datetime")
*/
private $start_date;
/**
* #ORM\Column(type="datetime")
*/
private $expire_date;
I want to show all the news in a list in a twig template, this is how I'm doing that:
<div class="list-group">
{%for news in news%}
<div class="panel panel-default">
<div class="panel-heading">{{ news.start_date|date('Y-m-d') }}</div>
<div class="panel-body">
{{ news.text }}
</div>
</div>
{%endfor%}
</div>
The fact is that I get the following error:
Neither the property "start_date" nor one of the methods "start_date()", "getstart_date()"/"isstart_date()" or "__call()" exist and have public access in class "AppBundle\Entity\News".
But If I try to render only the text property, I am able to access it.
Why is that?
Your attribute is private. you can add a getter
public fucntion getStartDate() {
return $this->start_date;
}
and in twig
{{ news.startDate|date('Y-m-d') }}

Add action in Symfony2

In the show page i whant add order quantity in my session.
This is my action
/**
* #Route("/add/{id}", name="add_action")
* #param Request $request
* #param $id
* #return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function addAction(Request $request, $id)
{
$session = $request->getSession();
$basket = $session->get('basket');
$key = array_search($id, $basket);
if(!$key)
{
$basket[$key] = $request->query->get('item');
$session->set('basket', $basket[$key]);
}
return $this->redirectToRoute('basket_action');
}
In this action i have error Warning: array_search() expects parameter 2 to be array, null given. What can be done to make it work?
P.S.
part of my template
<form method="get" action="{{ path('add_action', {'id' : product.id}) }}">
<select class="form-control" name="item">
{% for i in 1..10 %}
<option value="{{ i }}">{{ i }}</option>
{% endfor %}
</select>
<button class="btn btn-success" >Add to basket</button>
</form>
change
$basket = $session->get('basket');
to
$basket = $session->get('basket', array());
Looks like you are not storing basket as an array on session correctly, I would need to see your code where stores it. You can add a check if is an array before using array_search to prevent this error

Resources