Recover data session with relationship in Symfony with twig - php

I have a manyToOne relation of my entity ticket to my entity command. I store my tickets and my order in session. I can retrieve the command information by doing for example: {{app.request.session.get("command").Nom}}
But I can not view the ticket information. For example, if I want to get the ticket price 107 with twig?
session
Function of my service :
public function startCommande(Request $request)
{
$commande = new Commande();
$form = $this->form->create(CommandeBilletType::class, $commande);
if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()){
$data = $form->getData();
$this->session->set('commande', $data);
}
return $form;
}
public function coordonneesCommande(Request $request)
{
$commande= $this->session->get('commande');
$form = $this->form->create(CommandeType::class, $commande);
if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) {
$this->price->tarifBillet($commande);
$response = new RedirectResponse('paiement');
$response->send();
}
return $form;
}
I tried {{app.request.session.get ("commande").Billet().Nom}}
{{app.request.session.get('Billet.nom')}}
...

You're trying to access a collection, you should iterate over it.
First set your "commande".
{% set commande = app.session.get('commande') %}
Now, you should be able to access the entity information and get your "billets" like this, (if i understand well you have a collection of billet):
{% for billet in commande.getBillet() %}
{{ billet.prix }}
{% endfor %}

Related

How may I put a $_POST data into a database table?

It's been 3 weeks since I've started to learn symfony 4. I am trying to put the chosen data from the dropdown list into a database but I am not using a Form builder - the data is entered in html/twig and then stored into a variable $value.
I am wondering, though, how can I put this data from the variable $value into a database of choice (table User)? I mean, (if understood it right) when I use the form builder I am supposed to use ObjectManager $manager as following:
$manager->persist($value);
$manager->flush();
In this case I, honestly, have no idea of how I can put my data into a database.
Can anyone give me a clue?
twig
<select name="user">
{% for user in users %}
<option value="{{ user.idUser }},{{ user.name }}" label="{{ user.name }} {{ user.surname }}">{{ user.name }} {{ user.surname }}</option>
{% endfor %}
</select>
<button type="submit" id="article_form_save" name="article_form[save]">ADD</button>
controller
/**
* #Route("/attribution", name="attribution")
*/
public function create (Request $request) {
$users = $this
->getDoctrine()
->getRepository(User::class)
->findAll();
$value = $_POST;
dump($value);
return $this->render('database/Roles/attrib.html.twig', [
'users' => $users
]);
You can access your dropdown data from $_POST['user'] or you can use $request->request->get('user')
In order to save data into the database, you can create an object (Post for example) where you set the values you are retrieving from the request and then saving them.
You can do something like this:
<?php
/**
* #Route("/attribution", name="attribution")
*/
public function create (Request $request) {
$users = $this
->getDoctrine()
->getRepository(User::class)
->findAll();
$user = $request->request->get('user');
$manager = $this->getDoctrine()->getManager();
$post = new Post();
$post->setUser($user); // I suppose the user property in your post is just an integer not an object
$manager->persist($post);
$manager->flush();
dump($user);
return $this->render('database/Roles/attrib.html.twig', [
'users' => $users
]);
?>
This is just an example, which you can adapt it to your needs.
Your value should have only the user id. Change
<option value="{{ user.idUser }},{{ user.name }}"
to
<option value="{{ user.idUser }}"
Then, you can get the user like this:
$userId = $request->request->get('user'); //this will not be a user entity, but only an id
Which will return the user id.
Then you need to retrieve the user via your repository and save it.
Inject your user repository and entity manager by type-hinting them in your function arguments:
public function create (Request $request, UserRepository $repository, EntityManagerInterface $entityManager) {
do a findOneBy:
$user = $repository->findOneBy(['id' => $userId]);
Set the user to the article and save it
$article.setUser($user);
$entityManager->persist($article);
$entityManager->flush();
PS: using Symfony forms would make it waaay simpler.

How to restrict modification to selected properties of an entity while persisting?

Let's suppose I have an entity class and a generic FormType corresponding to the entity
class Entry {
protected $start_time;
protected $end_time;
protected $confirmed; // Boolean
// ... Other fields and getters and setters
}
On the CRUD of this entity, I don't want to allow any modification on start_time or end_time if the entity has been confirmed or in the above case when $confirmed === true
On the twig file, I disable the fields I want to restrict, like the following:
{% if entity.approved == true %}
{{ form_row(entity.start_time), { 'attr' : { 'disabled' : 'disabled' } }) }}
{% endif %}
{# Sameway for another field #}
Now the problem is that this is a front end resolution which can be tampered very easily using web developer tools in web browsers now. But regardless what I am trying to achieve is not have those two fields changed once the entity in confirmed.
So, one way I tried was after the form was submitted, I check if the entity was confirmed and if it was was, I fetch the earlier state of the entity and set the value of the new one (which is about to be persisted) with the values from old one.
On Controller:
$confirmed = $entity->getConfirmed();
$form->handleRequest($request);
if($form->isSubmitted() && $editForm->isValid()) {
// The form was submitted
if($confirmed === true) { // if the entity was confirmed previously
$oldEntity = $em->getRepository('...')->find($entity->getId());
$entity->setStartTime($oldEntity->getStartTime());
$entity->setEndTime($oldEntity->getEndTime());
}
$em->persist($entity);
$em->flush();
}
The problem here was $oldEntity was exactly same as $entity. My guess is doctrine picked up that it already has the entity that is being asked and just returned me with the same object. Anyways, my attempt to solve this problem failed.
Any idea how to restrict/revert changes on selected properties while allowing changes on rest of the properties of the entity?
Update:
Modifying the form type to disable the field is not an option because I only want them to be read-only/disabled only if entity is confirmed and rest of time I want the form to be as it is.
You must add attribute 'disabled' => true in form builder, not only in twig.
If you don't want a user to modify the value of a field, you can set the disabled option to true. Any submitted value will be ignored.
Reference: http://symfony.com/doc/current/reference/forms/types/form.html#disabled
If you wish modify dynamically, use form events, example:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$entity = $event->getData();
// if confirmed, disable start_time field
if ($entity->getConfirmed()) {
$config = $form->get('start_time')->getConfig();
$options = $config->getOptions();
// set disabled option to true
$options['disabled'] = true;
// replace origin field
$form->add(
'start_time',
$config->getType()->getName(),
$options
);
}
});
I think I understand your problem now #Starx, I didn't read very carefully at first, and your update helped.
Maybe you need to detach your Entity?
Check this link about (Entities in Session)[http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/cookbook/entities-in-session.html]. Maybe storing the Entity in a session will work. Detaching as a separate Entity might work, and do a comparison on the detached Entity to your updated Entity.
I found two ways to solve this:
You can retrieve original data of the entity. It returns an array with old data of an entity which can be used to reset the data.
if($form->isSubmitted() && $editForm->isValid()) {
// The form was submitted
if($confirmed === true) { // if the entity was confirmed previously
$oldData = $em->getUnitOfWork()->getOriginalEntityData($entity);
$entity->setStartTime($oldData['start_time']);
$entity->setEndTime($oldData['end_time']);
}
$em->persist($entity);
$em->flush();
}
Using Form Events
The following is a Symfony 3 Solution, try maximkou's answer for Symfony 2.
class EntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ....
// ....
// Your form fields
$builder->addEventListener(FormEvents::POST_SET_DATA, array($this, 'onPreSetData'));
}
public function onPreSetData(FormEvent $event) {
/** #var YourEntity $entity */
$entity = $event->getData();
$form = $event->getForm();
if($entity instanceof YourEntity) {
if ($entity->getTimesheetEntry()->getTimeApproved() === true) {
$config = $form->get('start_time')->getConfig();
$options = $config->getOptions();
$options['disabled'] = true;
$form->add('start_time', get_class($config->getType()->getInnerType()), $options);
$config = $form->get('end_time')->getConfig();
$options = $config->getOptions();
$options['disabled'] = true;
$form->add('end_time', get_class($config->getType()->getInnerType()), $options);
}
}
}
}
Source

Data retrieval and display in Symfony

I am new to Symfony, I have a table users with two columns: user_name and first_name, I want to display all users whose names (user_name & first_name) contains $search:
<?php
namespace Login\LoginBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Login\LoginBundle\Entity\Users;
use Login\LoginBundle\Modals\Login;
use Doctrine\DBAL\DriverManager;
public function homeAction(Request $request) {
$session = $this->getRequest()->getSession();
if ($request->getMethod() == 'POST') {
$search_for = $request->get('search');
//what to write here --save my life guys
}
return $this->render('LoginLoginBundle:Default:home.html.twig');
}
It's like a full process of querying and fetching data, passing the results to the template. What you need to do is following below steps:
1) Get the repository of your entity (table) and call your custom search function which is created in the repository (of course you can merge this step and next one to have all in your controller homeAction function) I assume your entity name is Users
public function homeAction(Request $request) {
$session = $this->getRequest()->getSession();
$results = array();
if ($request->getMethod() == 'POST') {
$search_for = $request->get('search');
$em = $this->getDoctrine()->getManager();
$results = $em->getRepository('LoginLoginBundle:Users')->searchPhrase($search_for);
}
return $this->render('LoginLoginBundle:Default:home.html.twig', array(
'results' => $results
));
}
2) Now you need to build a repository class for you entity and implement below function in it Entity Repository in Symfony (or merge the code below to your controller)
public function searchPhrase($phrase) {
$query = $this->createQueryBuilder('U');
$result = $query->where(
$query->expr()->like('U.username', $query->expr()->literal("%$phrase%"))
)
->andWhere(
$query->expr()->like('U.firstName', $query->expr()->literal("%$phrase%"))
)
->getQuery()
->getResult();
return $results;
}
Keep in mind because you mention "AND" I used andWhere whereas you can use orWhere; because you said "CONTAIN" I used like expression with % and that's the way you can create expression in DQL Here is a full list of Doctrine2 expressions
3) last step is to show the results in your twig template; I assume you want to show them in table rows
<table>
<tr>
<th>Username</th><th>First Name</th>
</tr>
{% if results|length > 0%}
{% for item in results %}
<tr>
<td>{{ item.getUsername }}</td><td>{{ item.getFirstName }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="2">No matching results found!</td>
</tr>
{% endif %}
</table>
Hopefully this helps
Thank you guys, But I this worked for me:
$repository = $this->getDoctrine()->getRepository('LoginLoginBundle:Users');
$query = $repository->createQueryBuilder('u')
->where("u.userName LIKE '%".$search_for."%' or u.firstName LIKE '%".$search_for."%'")
->getQuery();
$Myusers = $query->getResult();
if ($Myusers) //test if there are results returned
{
foreach ($Myusers as $user)
{
echo "E-mail : ".$user->getUserName()." -- Name : ". $user->getFirstName()."<br>";
}
}
else
{
echo "No matching results found!!";
}
//end-display

Symfony 2.1 app.session.flashbag.get('something') returns empty value

I have a trouble with using app.session.flashbag.get('notice').
In the controller I make
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('SomeBundle:SomeEntity')->find($id);
$editForm = $this->createForm(new SomeEntityType(), $entity);
$editForm->bind($request);
if ($editForm->isValid()) {
$em->persist($entity);
$em->flush();
$flash = $this->get('translator')->trans('Some Entity was successfully updated');
$this->get('session')->getFlashBag()->add('notice', $flash);
return $this->redirect($this->generateUrl('some_entity_edit', array('id' => $id)));
}
In editAction I'm getting information from the session:
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$flashes = $this->get('session')->getFlashBag()->get('notice', array());
//...
//...
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'flashes' => $flashes
);
}
And i'm trying in the TWIG get information from the session :
TWIG: {% for flashMessage in app.session.flashbag.get('notice') %}{{ flashMessage }}{% endfor %}
PHP: {% for flashMessage2 in flashes %}{{ flashMessage2 }}{% endfor %}
The app.session.flashbag.get('notice') is empty, the flashes has a value.
Do you have any ideas, why I can't get data from the app.session.flashbag.get('notice')?
Its normal behavior. You access flash in controller first, so it is returned and unset then. When you access it again then key does not exists in flashbag that way is empty.
See FlashBag::get at github
There is an easy way to handle (add/display) Symfony flash messages with FlashAlertBundle, it is standalone Symfony2 bundle implemented with pure JavaScript, so you don't have to worry about using JS libraries.
You just need the following code to render flash messages on your twig template:
{{ render_flash_alerts() }}
Available through
https://github.com/rasanga/FlashAlertBundle
https://packagist.org/packages/ras/flash-alert-bundle

symfony form : how to show the parameter in the view, "variable does not exist..."

I'm using a form with 2 classes ("ArticleType" and "ArticleHandler") for my class Article.
I would like to send the id of the article I've just created, but I can't manage to show this id parameter in the view :
In the controller, I send my article's id :
$handler = new ArticleHandler($form, $request, $em);
if ($handler->process()){
return $this->redirect($this->generateUrl('myproject_show', array('id' => $article->getId())) );
}
and in the view, I've got an error with :
{% block body %}
<p>the id :</p>
{{ id }}
{% endblock %}
or entity.id (as in the CRUD) :
Variable "id" does not exist...
Variable "entity.id" does not exist...
Do you know how to fix this?
Thanks
EDIT :
here's my method :
public function addAction()
{
$article = new Article();
$form = $this->createForm(new ArticleType(), $article);
$request = $this->getRequest();
$em = $this->getDoctrine()->getEntityManager();
$handler = new ArticleHandler($form, $request, $em);
if ($handler->process()){
return $this->redirect($this->generateUrl('myproject_show', array('id' => $article->getId())) );
}
return $this->render('ProjBlogBundle:Blog:add.html.twig', array(
'form' => $form->createView(),
));
}
and here's the view :
{% extends "ProjBlogBundle::layout.html.twig" %}
{% block title %}
the title - {{ parent() }}
{% endblock %}
{% block sousbody %}
<p>here's the article i've just created :</p>
{{ id }}
{% endblock %}
EDIT N°2 :
myproject_show:
pattern: /show/{id}
defaults: { _controller: ProjBlogBundle:Blog:show, id:5 }
To use a variable in a template you need to pass it when you render your template:
//ProjBlogBundle:Blog:show
public function showAction($id)
{
return $this->render('ProjBlogBundle:Blog:show.html.twig', array(
'id' => $id
));
}
$this->redirect($this->generateUrl('myproject_show', array('id' => $article->getId())) ); returns only HTTP 302-response without rendering a template, and the browser is redirected to the generated url...

Categories