setValue of a form field on twig template - symfony

I try to set the user informations who is logged-in on a twig template but I can't find a way.
In particular, I try to make a comments section and I would like the user to write only the comment text.Doing so, I would like to setAuthor( app.user.username) on the template twig because I cannot get user information on the Controller file.
so on my controller file,in the function show, I put this :
if($form->isSubmitted() && $form->isValid() ){
$comment->setCreatedAt(new \DateTime())
->setExercice($exercice)
//would like to do it but cannot
//->setAuthor(app.user.username);
So I search a way to maybe make something like
{{form_row(commentForm.author,{'attr': {
'value': app.user.username,
'class':hidden
}})}}
Is there a way to do it ?
the error I get is :
Variable "hidden" does not exist.

Your original error, Variable "hidden" does not exist., happens because you've attempted to reference hidden as if it were a variable or constant, rather than a literal string. To use it as a literal string you need to quote it:
{{ form_row(commentForm.author, {attr: {
value: app.user.username,
class: 'hidden'
}}) }}
You do not need to quote the keys of the array (e.g. value: and class:) because non-scalar values cannot be used as keys.
However as #msg pointed out you should not rely on the form on the view to obtain the user details. This opens the form up to manipulation, meaning anyone would be able to impersonate other people in any comment posted. Definitely populate that field of the comment entity directly during the controller. -- If you do this prior to checking if the form is submitted that information will be available to the view also, e.g. exposing $comment to the view would mean {{ comment.username }} would also work.

Related

error when rendering Symfony 4 edit form that includes a File type

I'm following the steps outlined in this documentation https://symfony.com/doc/current/controller/upload_file.html to allow a file to be uploaded. It is working perfectly for adding a new item, but when I try to edit my entity, I'm getting the following error:
The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) string. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) string to an instance of Symfony\Component\HttpFoundation\File\File.
I've tried code like what is suggested in that article to append the path of the folder as File type to the entity like this in my update method:
public function editAction(Request $request, Advertiser $advertiser)
{
$advertiser->setLogo(
new File($this->getParameter('logo_directory') .'/' . $advertiser->getLogo())
);
$editForm = $this->createForm(AdvertiserType::class, $advertiser);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('advertiser_list');
}
return $this->render('advertiser/index.html.twig', [
'form' => $editForm->createView()
]);
}
The logo_directory parameter is properly defined (and working fine for creating new entities).
Please let me know if you have any ideas what I am doing wrong.
Thanks for the help.
UPDATE: In this article The form's view data is expected to be an instance of class ... but is a(n) string there is a proposed solution to include in the form builder code the following:
->add('file', FileType::class, array('data_class' => null))
So I'm doing this now and the edit form will show - but it doesn't prepoulate with the previous selection.
->add('logo', FileType::class, array('data_class' => null), ['label' => 'Logo (JPG or PNG file)'])
Any thoughts on how this can be changed to allow the form to show with the previous selection pre-populated?
Setting a null data_class will remove the warning but it will not work, you don't need it at this point.
This is due to the fact that once your file is persisted, what remains in your database is just a path, not the file itself (which is on disk);
If you want to edit this entity again, the path (a string) must be converted to a File entity again; That's what the error message says.
.. and this is what you did when you wrote :
$advertiser->setLogo(
new File($this->getParameter('logo_directory') .'/' . $advertiser->getLogo())
);
Now, the problem that remains is that you want to prepopulate the file field. In fact, that is not possible, since the file field points to a location in your own computer, not to a file on your server (and you cannot automatically upload something from someone's computer like that, that would be very dangerous).
What you want to do is possibly indicate that a file is already stored, get its path and maybe display it to your user.
So in your Twig template, something like that (change with your real logo directory) :
{% if form.logo.vars.data %}
<img src="{{ asset('/uploads/logos_directory/' ~ form.logo.vars.data.filename) }}"/>
{% endif %}
Hope it's clear.

Object is too big when load from database symfony

I need load and object from the database and need to store it in session .
The problem is that the loaded object is too big that when i print it my browse crushes .
How can i load just the pure object from the database ?
And here is the code :
if ($session->get('record')->getId()) {
$record = $this->container->get('myweb.record_repository')->findOneById($session->get('record')->getId());
$session->set('record', $record);
print_r($session->get('record'));
die;
}
Try to hydrate as array... in symfony there is the option to Query::HYDRATE_ARRAY and then normalize it to an object
You're not dumping your code correctly.
With Symfony, there is the dump() function.
You can either use it in controller, or in twig.
In controller:
//Check if parameter exists first, else you might trigger an error
if($session->has('record') && $session->get('record')->getId() !== null) {
$record = $this->container->get('myweb.record_repository')->findOneById($session->get('record')->getId());
$session->set('record', $record);
dump($session->get('record'));
exit();
}
In Twig (you can pass a variable name)
{{ dump() }}
Then again, like I said in comment, it's most likely pointless to store your object in session.
Doctrine will query for the object most of the time.
Lets say you do this:
$relatedEntity->getRecord();
Doctrine won't look into the session for the object, it will query database.

Symfony 2 - Twig templates - Entity function results

I am looking for best solution how to send value returned by one of entity function's in symfony2 to twig template.
The problem is connecting with getting file url for file uploaded according to "How to Handle File Uploads with Doctrine" manual (http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html). I was following the last example ("Using the id as the Filename").
In controller I am getting one of documents entity.
$document = $this->getDoctrine()->getRepository('AppBundle:Documents')->find($id);
and I provide entity details to twig template:
return $this->render('AppBundle:Documents:details.html.twig', array('document' => $document));
However in the template I need to get link to the file which is generated by getAbsolutePath() function.
public function getAbsolutePath()
{
return null === $this->link
? null
: $this->getUploadRootDir().'/'.$this->id.'.'.$this->link;
}
I may use in controller the following code:
return $this->render('AppBundle:Documents:details.html.twig', array('document' => $document, 'link' => $document->getAbsolutePath()));
but this solution does not seems to tidy for me, as I am already sending $document to twig. What would be your practical solution?
Its simple. In a Twig template you can simply do:
{{ document.getAbsolutePath() }}

Return a value from entity to view file in symfony

I want to return a value from entity to view file. Below is my entity function
public function getVisitorName($id)
{
$repository = $this->getDoctrine()->getRepository('SystemVmsBundle:VisitorsDetails');
$product = $repository->findOneBy(array('id' =>$id));
$name=$product->getFirstname();
return $name;
}
This is the line in my view file which calls that function
{{ entity.visitorName(entity.visitorId) }}
Its not giving me any error. But only a blank page. How can i fix this?
This is my controller code
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('SystemVmsBundle:EntryDetails')->findAll();
return array(
'entities' => $entities,
);
}
I am trying to fetch the visitors name(from visitors table) corresponding to the visitor id(in entry table).How will i do it then?
you have two ways of doing it:
1) Map your SystemVmsBundle:EntryDetails entity, to SystemVmsBundle:VisitorsDetails as OntToOne by adding field details to your EntryDetails; , and then in twig template just call it via
{{ entity.details.name }}
2) instead of creating getVisitorName(), it is better to create twig function for this, with same functionality.
Your indexAction() is not returning a response object, it is just returning an array of entities. Controller actions should return a Response containing the html to be displayed (unless they are for e.g. ajax calls from javascript). If you are using twig templates you can use the controller render() method to create your response, something like this:
return $this->render('<YourBundle>:<YourViewsFolder>:<YourView>.html.twig', array(
'entities' => $entities,
));
When you've corrected that I suspect you'll get an error because $this->getDoctrine() won't work from an entity class. The code you have in the getVisitorName() method just shouldn't be in an entity class.
As #pomaxa has already suggested, I believe there should be a relationship between your EntryDetails and VisitorsDetails entities although I don't know enough about your data from the question to know what type of relationship it should be (OneToOne / ManyToOne). If your EntryDetails entity had a relationship to VisitorsDetails, the EntryDetails class would then contain a $visitorsDetails attribute and methods to get/set it. Then the line in your twig file would look like this:
{{ entity.visitorsDetails.firstName }}
There is a section on Entity Relationships / Associations in the Symfony Manual.
Also, I hope you don't mind me giving you a little advice:
Be careful when you copy and paste code as it appears you have done in getVisitorName(). You have kept the variable name '$product' although there are no products in your system. This sort of thing can cause bugs and make the code more difficult to maintain.
I recommend you avoid tacking 'Details' onto the end of entity names unless you genuinely have two separate and related entities such as Visitor + VisitorDetails and a good reason for doing so. I think the entities in your example are actually 'Visitor' and 'VistorEntry'.
Unless you are writing a re-usable component, I recommend you use specific variable names like '$visitorEntries' rather than '$entities' in your controller and twig.
In general, the more meaningful your variable names, the more readable, maintainable and bug-free your code is likely to be. Subsequently, it will also be much easier for people on SO to understand your code and give you help when you need it.

How do you define the getter to use in a CRUD form besides defining __toString()?

If you've used Symfony2's generators to create CRUD forms from database entities, you may wind with an error like this on the "create new record" screen:
StringCastException: A "__toString()" method was not found on the objects of type
"ScrumBoard\ServiceBundle\Entity\Users" passed to the choice field. To read a
custom getter instead, set the option "property" to the desired property path.
If I'm reading this correctly, the problem is that it needs to display a dropdown list of users for the record I'm creating, but it doesn't know how to turn a "User" entity into a string.
Defining the __toString() method on my Users entity class fixes the problem. However, I can see right from the text of the error message that there is an alternative: read a customer getter instead, which is accomplished by "[setting] the option "property" to the desired property path."
This sounds like some kind of annotation. But in my searching, I can't figure out what that is. Because I want to have a thorough understanding of Symfony2--can someone help me out?
Thanks!
When creating an entity ( superclass of choice ) field type in a form. You need to specify which property shall be used for the labels/values otherwise the __toString() method of the underlying object will be used.
$builder->add('users', 'entity', array(
'class' => 'AcmeHelloBundle:User',
'property' => 'username',
));
Read more about it in the Form Type Reference for entity field Type.
Additional Info
A __toString() related error generally often comes from twig when generating a route in a template aswell.
if outputting an object an object in twig with {{ object }} ... twig will call the object'S __toString method.
This "trick" is used by the crud generated templates with SensioGeneratorBundle.
{{ path('article_show', {'id': article}) }}
with the route being something like this:
article_show:
pattern: /article/{id}
defaults: { _controller: AcmeArticleBundle:Article:show }
If you have the __toString method in your Article entity set to something like ...
public function __toString()
{
return $this->id;
}
... you dont't need to type
{{ path('article_show', {'id': article.id) }}
Generally Twig will automatically output Article::getId() if you use
{{ article.id }}
Hope this clarifies your findings.

Resources