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.
Related
I am learning Symfony so I am testing various ways to work with database. The idea is to make select dropdown list that contains data from table in database. Each option in select returns value that is id of column from table. Dropdown list is defined in View in this way ('find_res' in action is route to controller):
<form action="{{ path('find_res') }}" method="POST" name="formpt">
<select name="patientId">
{% for patient in patients %}
{{dump(patient)}}
<option value="{{patient.id}}">{{patient.lastname}}{{patient.firstname}}</option><br />
{% endfor %}
</select>
<button type="submit" name="submit">Find results</button>
</form>
so that for chosen patient.id it should show results in table which is defined in code bellow this as standard html table.
In controller method I created list of all patients from table in database and sent it as parameter to this view. And that works just fine. Also, I would not get into details how query is built because the problem is that any $request I try does not return anything, just null. I tried:
$request->request->get('patientId'); //returns null always
$request->get('patientId'); //also null
I even tried to give name to form in view like for instance 'formpt' and then tried it with:
$request->request->get('formpt')['patientId'];
still nothing. This test code:
if($request->getMethod() == 'POST' ) {
\Doctrine\Common\Util\Debug::dump($request->request->get('patientId'));
exit;
}
always returns NULL or string(0) "" for whatever I put in "dump".
What I am doing wrong?
Thanks!
The following is a simple way to implement what you're trying to do with the standard form component (note that I explicitly didn't create a dedicated form type!).
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Constraints\NotBlank;
use AppBundle\Entity\Patient;
class DefaultController extends Controller
{
/**
* #Route("/", name="index")
*
* #param Request $request
*
* #return Response
*/
public function indexAction(Request $request)
{
$form = $this->createFormBuilder()
->add('patient', EntityType::class, [
'required' => false,
'placeholder' => '--- Select ---',
'class' => Patient::class,
'choice_label' => function (Patient $patient) {
return sprintf(
'%s, %s',
$patient->getLastname(),
$patient->getFirstname()
);
},
'constraints' => [
new NotBlank()
],
])
->getForm()
->handleRequest($request)
;
if ($form->isSubmitted() && $form->isValid()) {
/** #var $selected Patient */
$selected = $form->get('patient')->getData();
dump($selected);
}
return $this->render('default/index.html.twig', [
'form' => $form->createView()
]);
}
}
the view being:
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(form) }}
{{ form_widget(form) }}
<button>Find results</button>
{{ form_end(form) }}
{% endblock %}
I understand that the form component (especially form customization) has it's learning curve, but ultimately, if you want to use symfony fully you'll end up using it anyway (why reinvent the wheel). So the sooner you start with it the better.
Maybe try this
For mapped field
public function yourAction(Request $request){
$patient = new Patient();
$form = $this->createForm('AppBundle\Form\PatientType', $patient);
$form->handleRequest($request);
if ($form->isSubmitted())
{
$patientId = $patient->getId();
}
}
If you need to get a non mapped field (field that's not a Patient property)
public function yourAction(Request $request){
$patient = new Patient();
$form = $this->createForm('AppBundle\Form\PatientType', $patient);
$form->handleRequest($request);
if ($form->isSubmitted())
{
$patientCustomField = $form['customField']->getData();
}
}
I have models User and Diares set up with the hasMany and BelongTo relstionship. I'm trying to fetch data from the Diaries table associated with a particular user. I tried auth but it didnt work for me. How can i achieve that and display it in the blade view as well. Here is my current code:
public function index(User $id)
{
$user = User::find($id);
$record = $user->diary;
return view('home')->with('record', $record);
}
The blade file it should display to:
#foreach ($record as $diary)
{{ $diary->error }}
{{ $diary->fix }}
#endforeach
In your index function the $id is not integer - this is a User instance, so you can try use this:
public function index(User $user)
{
$record = $user->diary;
return view('home')->with('record', $record);
}
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 %}
Here is my table structure for permissions, roles, and permission_role
permission:
id
name
roles:
id
name
permission_role:
role_id,
permission_id
Here permission_role is my pivot table.
In my frontend which i have setup something like this,
welcome.blade.php
<form method="POST" action="/give/permission">
{!! csrf_field() !!}
<select name="role" class="selectpicker" multiple data-max-options="2">
#foreach($roles as $r)
<option value="{{$r->id}}">{{$r->name}}</option>
#endforeach
</select>
<div class="checkbox">
#foreach ($perm as $p)
{!! Form::checkbox('p[]', $p->id, in_array($p->id, $all_data)) !!}
{!! Form::label('permisssion', $p->name) !!}<br>
#endforeach
</div>
<button type="submit" class="default">Submit</button>
</form>
in my controller.php
public function postrolperm(Request $request,$id){
$p = Role::find($id);
$role = $request->role;
//dd($input1);
$permission = $request->p;
//dd($input2);
//
//$role = Role::where("name", "admin")->get();
if(isset($permission) && isset($role)){
$role->givePermissionTo($permission);
$role->save();
}
return redirect::back();
}
role.php
public function givePermissionTo(Permission $permission)
{
return $this->permissions()->save($permission);
}
I am not able to save the data into the pivot table.
I have tried in php artisan tinker with following commands:
$role = Role::first(); //which gives me the first role with id of 1
$role->givePermissionTo(Permission::first()); // it will save the first permission to the role.
What i am doing wrong in my controllers ?
Also to note that, that this routes works fine.
Route::get("/pivot", function(){
$permission = new Permission;
$permission->name = "can to";
$permission->save();
$role = new Role;
$role->name = "admin2";
$role->save();
$role->givePermissionTo($permission);
return "true";
});
The reason it isn't working is because you haven't created a Role and Permission object based on the ids passed back from the view. A working example is given below:
$role_id = $request->role;
$permission_ids = $request->p; // This comes back as an array.
if(isset($permission_ids) && isset($role_id)){
$role_object = Role::where('id', $role_id)->firstOrFail();
foreach ($permission_ids as $permission_id) {
// loop through each permission id
// find the corresponding permission object in the database
$permission_object = Permission::where('id', $permission_id)->firstOrFail();
// assign the object to the role
$role_object->givePermissionTo($permission_object);
}
$role_object->save();
}
return Redirect::back()
Note that this will throw an exception if the role and permission passed back from the view don't correspond to a valid id in the database. Usefirst() instead of firstOrFail() if you want failures to be silent, i.e. not thrown an exception.
Make sure to add use App\Role; and use App\Permission to the top of your Controller file.
Your version fails due to the fact that you are trying to call the givePermissionTo function on a string representing the role id passed from the view - $role. You missed the step in between of getting the Role object from the database.
Curiously, you were on the right track with your $p variable, however you also needed to grab the corresponding $permission object from the database as shown in my example.
Did you added
use App\Role;
in controller.php file?
I would like to generate page with list of users names and next to every user I would like to have button which would activate/deactivate this user.
I could of course create link with user ID and GET method in controller which would perform operation when link would be clicked. As far as I know it is not recommended though to do it this way due to security concerns. So instead of links to route which would perform operation I would like to have forms and buttons to submit request to PUT route which would change user status.
QUESTION: how to generate such forms (buttons) based on list of users returned by Doctrine?
Form code used to create form/button in user profile:
/**
* Creates a form to activate/deactivate a User entity by id.
*
* #param mixed $id The entity id
*
* #return \Symfony\Component\Form\Form The form
*/
private function createActivationDeactivationForm($id)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('user_activate', array('id' => $id)))
->setMethod('PUT')
->add('submit', 'submit', array('label' => 'Activate/Deactivate'))
->getForm()
;
}
Controller code used for user profile:
/**
* #Route("/user/{id}", name="user_show")
* #Method("GET")
* #Template()
*/
public function showUserAction($id)
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('TestUserBundle:User')->find($id);
if (!$user) {
throw $this->createNotFoundException('Unable to find user');
}
$deleteForm = $this->createDeleteForm($id);
$activateForm = $this->createActivationDeactivationForm($id);
return array(
'user' => $user,
'delete_form' => $deleteForm->createView(),
'activate_form' => $activateForm->createView(),
);
}
Controller PUT method to perform operation from user profile:
/**
* Activate a user.
*
* #Route("/{id}", name="user_activate")
* #Method("PUT")
*/
public function activateAction(Request $request, $id)
{
$form = $this->createActivationDeactivationForm($id);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('TestUserBundle:User')->find($id);
if (!$user) {
throw $this->createNotFoundException('Unable to find user');
}
$current_user_activity_flag = $user->getActive();
$user->setActive(abs($current_user_activity_flag-1));
$em->persist($user);
$em->flush();
}
return $this->redirect($this->getRequest()->headers->get('referer'));
}
Controller code to be used for users list:
/**
* #Route("/users", name="users_list")
* #Method("GET")
* #Template()
*/
public function listUsersAction()
{
$em = $this->getDoctrine()->getManager();
$users = $em->getRepository('TestUserBundle:User')->findExistingUsers();
//$deleteForm = $this->createDeleteForm($id);
//$activateForm = $this->createActivationDeactivationForm($id);
return array(
'users' => $users,
//'delete_form' => $deleteForm->createView(),
//'activate_form' => $activateForm->createView(),
);
}
I can not pass ID to form like I did for operation from profile cause for every user there is different ID and more of that Symfony generates only first form and ignores rest.
Any idea how to handle it? Or maybe my approach with form/buttons is incorrect and I should just use links instead?
I found solution which works though I am not sure about if it's compliant with best practices.
Instead of passing one form object in controller I generated an array of them with keys based on user ID. Than when looping through array in TWIG template I use user ID to refer form object created for current user.
Mentioned in question controller for user listing should than look like this:
/**
* #Route("/users", name="users_list")
* #Method("GET")
* #Template()
*/
public function listUsersAction()
{
$em = $this->getDoctrine()->getManager();
$users = $em->getRepository('PSUserBundle:User')->findExistingUsers();
$activate_forms = array();
$delete_forms = array();
foreach($users as $user)
{
$activate_forms[$user->getId()] = $this->createActivationDeactivationForm($user->getId())->createView();
$delete_forms[$user->getId()] = $this->createDeleteForm($user->getId())->createView();
}
return array(
'users' => $users,
'delete_forms' => $delete_forms,
'activate_forms' => $activate_forms,
);
}
... and in TWIG form within foreach should be refered like this:
{{ form_start(activate_forms[user.id], {'attr': {'novalidate': 'novalidate'}}) }}
{% if user.active %}
{{ form_widget(activate_forms[user.id].submit, {'attr': {'class': 'btn btn-xs btn-warning btn-block'}, 'label' : 'Deactivate'}) }}
{% else %}
{{ form_widget(activate_forms[user.id].submit, {'attr': {'class': 'btn btn-xs btn-success btn-block'}, 'label' : 'Activate'}) }}
{% endif %}
{{ form_end(activate_forms[user.id]) }}