Different Variables/Functions for one twig.html - php

Since 3 weeks i try to learn php with the symfony framework.
I want to build an application with which i can track my expanses.
I made good progress but since 2 days i have a little logic problem so maybe someone can help me here.
I want to make a dashboard.(the main side of the project) There the user can monitor the expenditures.
This works. Now i want also a form at the dashboard, so the user can add new expenditures. I already implement a form but with a extra route. So in my ExpenditureController i have the functions dashboard and the function addExpenditure which generate different twig.html templates.
So the user can monitor his expenditures with ...budgetapp/expenditure/dashboard
and he can add new Expenditure with ...budgetapp/expenditure/addexpenditure
My Dashboard-Function
#[Route('/dashboard/', name: 'dashboard')]
public function dashboard(ExpenditureRepository $ar)
{
$user = $this->getUser();
$expenditures = $ar-> findexpendituresOfUser($user);
return $this->render('expenditure/dashboard.html.twig', [
'expenditures' => $expenditures,
]);
}
The expenditure/dashboard.html.twig shows the Expentiures of the current user in a table
My addExpenditure-Function
public function addExpenditure (ManagerRegistry $doctrine, Request $request){
$em = $doctrine->getManager();
$expenditure = new Expenditure();
$form = $this->createForm(ExpenditureType::class, $Expenditure);
$form->handleRequest($request);
if($form->isSubmitted()){
$em->persist($expenditure);
$em->flush();
}
return $this->render('expenditure/addexpenditure.html.twig', [
'addexpenditureForm' => $form->createView()
]);
}
The expenditure/addexpenditure.html.twig looks like this:
{% block body %}
<div class="container">
{{form(eintragenForm)}}
</div>
{% endblock %}
My problem /mistake in thinking:
How can i implement the form to the dashboard? So of course i can take the code from the addexpenditure function and put it 1:1 in the dashboard-funciton. but i dont think this is the right way? I also tried to including template fragments with the offical Embedding Controllers Documentation of Symfony, but this also dont work.
So someone can help me with a suggestion how you would handle this in your project?
Best regards
Markus

There are two possible solutions: put both view and add logic inside one controller's action, or separate them. Since you probably have some validation, it's reasonable to have both add and view code inside one action (otherwise, you'll have to pass errors via sessions, which is not very pretty). So basically, your dashboard/add action will look like this:
#[Route('/dashboard/', name: 'dashboard')]
public function dashboard(Request $request, ExpenditureRepository $ar, ManagerRegistry $doctrine)
{
$expenditure = new Expenditure();
$form = $this->createForm(ExpenditureType::class, $expenditure);
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $doctrine->getManager();
$em->persist($expenditure);
$em->flush();
return $this->redirectToRoute('dashboard');
}
}
$user = $this->getUser();
$expenditures = $ar-> findexpendituresOfUser($user);
return $this->render(
'expenditure/dashboard.html.twig',
[
'expenditures' => $expenditures,
'addexpenditureForm' => $form->createView(),
]
);
}
What's happening here:
First you check if POST http method was used, if it was - it means
that form has been submitted and you can handle it. There is an alternative solution without checking request method, see comments for more.
If this is a GET request, just show ordinary dashboard
If the form is submitted and it's valid - save data and redirect to
the same page. Otherwise, you'll need to empty all submitted data
from the form, etc. (it's not the right way to do it)
If the form is invalid, do not redirect, just render the page
normally, and all errors will be shown.
Finally, you of course have to render the form on your dashboard.html.twig like you did: {{form(eintragenForm)}}

Related

Symfony 5 - Get old collection data before submit form

In my symfony 5 project I would like when submitting a certain form, compare the entity before and after submission.
So keep a copy of the original entity in order to perform processing.
I've :
$parametresAdmin = $entrepriseService->getParametresAdmin();
$form = $this->createForm(ParametresAdminType::class, $parametresAdmin, [
'entreprise' => $this->getUser()->getEntreprise(),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entrepriseService->updateParametres($parametresAdmin);
return $this->redirectToRoute('admin_parametres');
}
In fact, I want to get a copie of $parametresAdmin->getTypesConges() (which is a collection on OneToMany).
So, when the form is submitted, I want compare the old $parametresAdmin->getTypesConges() and the new $parametresAdmin->getTypesConges().
The "$parametresAdmin->getTypesConges()" part looks like this:
I can add / modify leave types on the fly. Except that I do not want to authorize the possibility of modifying the "Balance type" field for the types of leave that already exist. There is just for those that I add that I leave the possibility in the ChoiceType. So on the front side, it's good. But on the back side, no.
But it doesn't work
What I do :
I change the "Solde initial" for the first line :
But when I submit, I've the same value (the new value : 10 )
EDIT : Currently, I've now :
$parametresAdmin = $entrepriseService->getParametresAdmin();
$typeConges = $parametresAdmin->getTypesConges();
$oldTypesConges = clone $typeConges;
$form = $this->createForm(ParametresAdminType::class, $parametresAdmin, [
'entreprise' => $this->getUser()->getEntreprise(),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$typeConges = $parametresAdmin->getTypesConges(); // update with new data
dd($oldTypesConges, $parametresAdmin->getTypesConges());
$entrepriseService->updateParametres($parametresAdmin);
return $this->redirectToRoute('admin_parametres');
}
You should clone your data like this :
$typeConges = $parametresAdmin->getTypesConges();
$oldTypeConges = clone $typeConges;
// handleRequest(), isValid(), isSubmit() ...
$typeConges = $parametresAdmin->getTypesConges(); // update with new data
dd(oldTypeConges, $parametresAdmin->getTypesConges());
phpdoc says about :
When an object is cloned, PHP will perform a shallow copy of all of the object's properties. Any properties that are references to other variables will remain references.
Take a look at this question on stackoverflow.
Use session variables to store the old data:
To store your data before rendering the form in the controller, use:
$this->get('session')->set('oldTypesConges ', $typesConges );
And after submitting, read the data stored to compare it with the new one:
$oldTypesConges = $this->get('session')->get('oldTypesConges ');
Now, you can compare $typesConges and $oldTypesConges.
This solution was inspired from here: How to set session variables for all the controllers in Symfony2?
$versionsBeforeSubmit = [];
foreach($produit->getVersions()->getIterator() as $version) {
$versionsBeforeSubmit[] = clone $version;
}
$form->handleRequest($request);
if($form->isValid() && !$hasError) {
dump($versionsBeforeSubmit);
}

Symfony | Form | Mail

I've got problem with Symfony and I hope you would help me :)
I created a Form, which takes data from user (email, name, message) and then it saves data in database. Everything works fine but i also want to send e-mail with this data.
I want to use mail function mail(to,subject,message,headers,parameters);.
My Controller class looks like:
public function ContactFormAction(Request $request){
$post = new ContactForm();
$form = $this->createFormBuilder($post)
->setMethod('POST')
->add('email','text',['label' => 'Adres e-mail'])
->add('name','text', ['label' => 'Imię'])
->add('message','text', ['label' => 'Wiadomość'])
->add('save','submit', ['label' => 'Wyślij'])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted()) {
$post = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($post);
$em->flush();
$message=''; //thats my problem
mail('example#example.pl', 'Subject', $message);
return $this->redirectToRoute('onas');
}
return $this->render('default/aboutus.html.twig', ['form' => $form->createView()]);
}
My Problem is: how should the $message variable looks like if I want to get this data from user (from a form on my webpage).
Thanks a lot for all your answers :)
Not sure that I follow, but, you want to send plain text using user's input just do $message = $post->getMessage(); and pass it on to mail. Is that the issue?
E-mail are, by default, sent in text/plain encoding, so you won't be able to use HTML. Personally, I prefer to format it a little better than old-plain-text. To achieve this, I usually create a Twig template, pass the input data to it and render what I need. That template could contain some HTML which could enhance the email's visual look.

CAKEPHP 3.1 clear form after submit

Usually on cakephp2 i used to unset form data and everything was ok.
Some times i use redirects to clear it. But i cant do that in this current page.
Anyone has found this issue or a solution for this?
If you are staying on the "add" page after successfully adding a record, for example to allow entry of multiple records more quickly, you'll need to reset the entity after saving. For example, if you're entering Posts, your controller will look something like:
$post = $this->Posts->newEntity();
if ($this->request->is('post')) {
$post = $this->Posts->patchEntity($post, $this->request->data);
if ($this->Posts->save($post)) {
$post = $this->Posts->newEntity(); // <- Reset the entity
}
}
$this->set(compact('post'));
(Error checking, flash messages, etc. all left out for brevity.)
An alternative is to simply redirect to the same page.
I had the problem that not everything was deleted
$contact = new ContactForm();
if ($this->request->is('post')) {
if ($contact->execute($this->request->data)) {
$this->Flash->success(__('Submited.'));
$this->request->data(null);
$contact = new ContactForm();
return $this->redirect('/(Same Page)');// This did the final trick for me
}
}

Why does CakePHP add New Rows when 'post' is replaced by 'get'?

I edit a row on the Post table or add a new row to it from edit() function in PostsController. The function looks like this:
public function edit($id = null) {
// Has any form data been POSTed?
if ($this->request->is('post')) { //Replaced 'post' by 'get' in this line
// If the form data can be validated and saved...
if ($this->Post->save($this->request->data)) {
// Set a session flash message and redirect.
$this->Session->setFlash('Updated the Post!');
return $this->redirect('/posts');
}
}
// If no form data, find the post to be edited
// and hand it to the view.
$this->set('post', $this->Post->findById($id));
}
I simply replaced 'post' by 'get' to see what would happen and it went on creating new rows without even taking me to the form. I still get the flash message 'Updated the Post!', but without taking any form data.
If the code in edit.ctp is required, here it is:
<?php
echo $this->Form->Create('Post');
echo $this->Form->input('id', array('type' => 'hidden','default'=>$post['Post' ['id']));
echo $this->Form->input('title',array('default'=>$post['Post']['title']));
echo $this->Form->input('body',array('default'=>$post['Post']['body']));
echo $this->Form->end('Update');
?>
Any thoughts on why this might be happening?
Edit: Added CakePHP Version
I am using CakePHP 2.4.5
What you are doing makes no sense.
Why would you want to switch the "post" by "get" here?
Of course it will then generate new rows, as you effectively trigger a save on each page load (GET).
Don't do that.
The code you had there was just fine - IF you also took PUT into consideration.
For edit forms, it is not a post, but:
if ($this->request->is('put')) {}
PS: If you want to make sure it always works for both add/edit, use
if ($this->request->is(array('post', 'put')) {}
But NEVER replace it with "get".

Symfony 1.4 forms using Propel Object '<class here>' not Found

From this page:
main_dev.php/player/new
to (when I click submit):
main_dev.php/player/edit/player_id/(no id)
if I put an id here it displays fine.
When I click the submit button (somehow it saves) but displays this:
404 | Not Found | sfError404Exception
Object Player does not exist().
this is my baseform:
$this->setWidgets(array(
'player_id' => new sfWidgetFormInputHidden(), //primary key auto increment()
'player_name' => new sfWidgetFormInputText(),
'player_gold' => new sfWidgetFormInputText(),
'chara_id' => new sfWidgetFormInputText(),
'open_social_id' => new sfWidgetFormInputText(),
));
im suspecting that the issue here is that player_id is not displayed and is auto increment. that means that when i submit the form player_id is left blank and since symfony cannot find where to get the id for the reference to display a record it goes 404, is there any workaround in this?
and my action.class is left from the default(instance when i generated it) so i think is not an issue
heres what the code for saving the form:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
if ($form->isValid())
{
$Player = $form->save();
$this->redirect('player/edit?player_id='.$Player->getPlayerId());
}
}
and ofcourse for the new page controller:
public function executeNew(sfWebRequest $request)
{
$this->form = new PlayerForm();
}
If the POST request saves a new Player object (in the database), it is not your BasePlayerForm.class, nor the submit url.
If your routing works when manually entered, and not when called within the action class, then your routing.yml is probably not the problem.
If you have not over-written the configure() of the BasePlayerForm.class.php (in PlayerForm.class.php, or anywhere else), then it is not in your lib/form/ classes.
Either this answer is useless (sorry) or you do not actually mean that the action "saves" the object to the database - in which case, check the submit url/request from the newSuccess template; also verify your routing:
Your newSuccess.php form tag action should POST to main_dev.php/player:
<form method="post" action="/main_dev.php/player">
[And pass the id rendered in html as <input type="hidden" name="player[player_id]" id="player_id" />.]
Lastly, the edit routing in the url will normally match player/:player_id/edit - check if you actually have an auto-created "id" column in your schema/database in addition to the "player_id" which might really be what is causing this.

Categories