I have a php snippet in Symfony2 where I say:
If the user exists -> return these data sets in an array to the template
else -> return name=> 'user not found'. Below is the only way this can work if I have in my twig only the variable 'first_name' being used.
Clear Problem Explanation:
If the user doesn't exist in the database, I cannot call user.name, user.username, user.password. Even if the if conditional isn't satisfied, twig still tries to evaluate that inside statement.
What I want to say is:
if (user) {
{{ user.name }}<br>
{{ user.username }}<br>
{{ user.password }} <br>
}
else {
User not found
}
However, if the user isn't found, it will still try and execute the DB access from the variable user ... user.name.. etc. How can I fix this?
PHP Snippet
/**
* #Route("/login/{username2}/{password2}")
* #Template()
*/
public function indexAction($username2, $password2)
{
$em = $this->getDoctrine()->getEntityManager();
$respository = $em->getRepository("SchachteUserBundle:user");
$username = $username2;
$password = $password2;
$user = $respository->findOneBy(array("username"=>$username, "password"=>$password));
if ($user) {
return array('exists'=>true, 'first_name' => $user->getName(), 'username' => $user->getUserName(), 'password'=>$user->getPassword());
}
return array('exists'=>false, 'first_name' => 'USER NOT FOUND', 'username' => 'USER NOT FOUND', 'password'=>'USER NOT FOUND');
}
}
TWIG
{% if exists == true %}
Hello {{ first_name }}!
{% else %}
Sorry, that user does not exist!
{% endif %}
Why not simply inject the return of your findOneBy in the template :
$user = $respository->findOneBy(array("username"=>$username, "password"=>$password));
return array('user'=>user);
Then in the template
{% if user %}
{{ user.name }}<br>
{{ user.username }}<br>
{{ user.password }}
{% else %}
User not found
{% endif %}
Moreover if you query the database with a password it means you have stored the clear password. It is very bad practice.
Related
For the purpose of a user-management ui I want to get all users with resulting permissions. I use the native implementation of Cartalyst\Sentinel and tried:
$users = Sentinel::getUserRepository()->with('roles')->get();
$permissions = array();
foreach ($users as $user) {
$user_permissions = Sentinel::getResultingPermissionsFor($user);
$permissions[$user['id']] = $user_permissions;
}
But the function "getResultingPermissionsFor()" seems not to be available anymore in V5.
I solved this by passing the roles-Object to the twig template:
router.php
$app->get('/admin/users', function (Request $request, Response $response) {
$loggedUser = Sentinel::check();
$users = Sentinel::getUserRepository()->with('roles')->get();
$roles = Sentinel::getRoleRepository()->get();
if (!$loggedUser) {
// do sth.
}
if (!$loggedUser->hasAccess('user.*')) {
// do sth.
}
$view = Twig::fromRequest($request);
$view->render($response, 'admin.users.html.twig', array(
'loggedUser' => $loggedUser,
'users' => $users,
'roles' => $roles
));
return $response;
});
twig-template:
{% for user in users %}
{% set rolePermissions = [] %}
{% for role in user.roles %}
{% set rolePermissions = rolePermissions|merge(role.permissions) %}
{% endfor %}
{% set resultingPermissions = rolePermissions %}
{% set resultingPermissions = resultingPermissions|merge(user.permissions) %}
{% endfor %}
// followed by output html
Using Symfony 4 to build a support ticket form:
Created route and functions in page controller
/**
* #Route("/support/ticket")
*/
public function ticket(){
return $this->render('support/ticket/ticket.html.twig');
}
public function new(Request $request)
{
// creates a Ticket and gives it some dummy data for this example
$ticket = new Ticket();
$form = $this->createFormBuilder($ticket)
->add('category', ChoiceType::class, array(
'choices' => array(
'ROMAC eHR' => 1,
'ROMAC Website' => 2,
'ROMAC Guide' => 3,
)
))
->add('comment', TextareaType::class)
->add('save', SubmitType::class, array('label' => 'Submit Ticket'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// $form->getData() holds the submitted values
// but, the original `$task` variable has also been updated
$ticket = $form->getData();
// ... perform some action, such as saving the task to the database
// for example, if Ticket is a Doctrine entity, save it!
// $entityManager = $this->getDoctrine()->getManager();
// $entityManager->persist($task);
// $entityManager->flush();
return $this->redirectToRoute('ticket_success');
}
return $this->render('support/ticket/ticket.html.twig', array(
'form' => $form->createView(),
));
}
And then render the form in the twig template:
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.category) }}
{{ form_row(form.comment) }}
{{ form_end(form) }}
When I load the page I get a Symfony error stating that "Variable form does not exist".
I have followed the documentation https://symfony.com/doc/current/forms.html. Where/how can I find the issue?
I assume you get this error while accessing "/support/ticket"
You have "form" variable missing in this function
public function ticket(){
return $this->render('support/ticket/ticket.html.twig');
}
I will suggest to wrap your code in twig template in a "if" block
{% if form is defined %}
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.category) }}
{{ form_row(form.comment) }}
{{ form_end(form) }}
{% endif %}
Or you need to adjust your controller functions accordingly
In my case i have 30 entities that there are no relation between them and every entities have two columns. I wanted to have 6 or 7 entities in the one form, but i don't know what is the best way to do it? this is my code ...
this is my Controller:
public function general1Action(Request $request)
{
$example1 = new Example1();
$example2 = new Example2();
$example3 = new Example3();
$example4 = new Example4();
$formexample1 = $this->createForm('...Bundle\Form\Example1Type', $example1);
$formexample2 = $this->createForm('...Bundle\Form\ Example2Type', $example2);
$formexample3 = $this->createForm('...Bundle\Form\ Example3Type', $example3);
$fprmexample4 = $this->createForm('...Bundle\Form\Example4Type', $example4);
$example1->handleRequest($request);
$example2->handleRequest($request);
$example3->handleRequest($request);
$example4->handleRequest($request);
$em = $this->getDoctrine()->getManager();
if ($example1->isSubmitted() && $example1->isValid()) {
/**
* To generate the value example1 first column(e1fc) and second column(e1sc)
*/
$prefix=$this->container->getParameter('prefix');
$e1fcCle=$em->getRepository("...Bundle:Example1")->genereCle('Example1',$prefix);
$example1->sete1fc($e1fcCle);
/**
* To generate the value example1 second column(e1sc)
*/
$example1->sete1sc("e1sc".($e1fcCle));
/**
* to check, the fields are not empty
*/
if(($formexample2["e2sc"]->getData())!=""){
$example2->sete1fc($e1fcCle);
$em->persist($example2);
}
if(($formexample3["e3sc"]->getData())!=""){
$example3->sete1fc($e1fcCle);
$em->persist($example3);
}
if(($formexample4["e4sc"]->getData())!=""){
$example4-> sete1fc($e1fcCle);
$em->persist($example4);
}
$em->persist($example1);
$em->flush();
return $this->forward('...Bundle:General...: general2',
array('E1FC' => $e1fcCle));
}
return $this->render('.../general1.html.twig', array(
'example1' => $example1,
'formExample1' => $formexample1->createView(),
'formExample2' => $formexample2->createView(),
'formExample3' => $formexample3->createView(),
'formExample4' => $formexample4->createView(),
));
}`
and this is my general1.html.twig :
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(formExample1) }}
{{ form_row(formExample2.e2sc) }}
{{ form_row(formExample3.e3sc) }}
{{ form_row(formExample4.e4sc) }}
<input type="submit" value="Next" />
{{ form_widget(formExample1._token) }}
{{ form_end(formExample1, {"render_rest":false}) }}
<ul>
<li>
Back to the list
</li>
</ul>
{% endblock %}`,
I have another question : when i try to use isValid() for the other form like this
if(($formexample2["e2sc"]->getData())!=""&& $example2->isValid())
i have this error: Fatal error: Call to a member function get...() on null
I have a list of friends which should be displayed 3 in a page. Each friend has a category and I also have a drop down menu to choose to view only the friends which are from the chosen category. They should also be display 3 in a page. The way in which filtered and not filtered friends are displayed is the same so I didn't want to have two almost actions in my controller and two identic templates, so I tried to make this in one controller's action and template, but there is a problem. I can't make the pagination for the second and following pages of the filtered friends. Pleae help! :( The problem is that I use a form and when I click on the second page, the variable which was filled in the form and binded, become undefined. Here is the code:
Controller's action
public function displayAction($page, Request $request)
{
$em = $this->getDoctrine()->getEntityManager();
$user = $this->get('security.context')->getToken()->getUser();
$cat = new Category();
$dd_form = $this->createForm(new ChooseCatType($user->getId()), $cat);
if($request->get('_route')=='filter')
{
if($request->getMethod() == 'POST')
{
$dd_form->bindRequest($request);
if($cat->getName() == null)
{
return $this->redirect($this->generateUrl('home_display'));
}
$filter = $cat->getName()->getId();
if ($dd_form->isValid())
{
$all_friends = $em->getRepository('EMMyFriendsBundle:Friend')
->filterFriends($filter);
$result = count($all_friends);
$FR_PER_PAGE = 3;
$pages = $result/$FR_PER_PAGE;
$friends = $em->getRepository('EMMyFriendsBundle:Friend')
->getFilteredFriendsFromTo($filter, $FR_PER_PAGE, ($page-1)*$FR_PER_PAGE);
$link = 'filter';
}
}
}
else
{
$all_friends = $user->getFriends();
$result = count($all_friends);
$FR_PER_PAGE = 3;
$pages = $result/$FR_PER_PAGE;
$friends = $em->getRepository('EMMyFriendsBundle:Friend')
->getFriendsFromTo($user->getId(), $FR_PER_PAGE, ($page-1)*$FR_PER_PAGE);
$link = 'home_display';
}
// Birthdays
$birthdays = null;
$now = new \DateTime();
$now_day = $now->format('d');
$now_month = $now->format('m');
foreach ($all_friends as $fr)
{
if($fr->getBirthday() != null)
{
if($fr->getBirthday()->format('d') == $now_day && $fr->getBirthday()->format('m') == $now_month)
{
$birthdays[]=$fr;
$fr->setYears();
}
}
}
// Search
$search = new Search();
$s_form = $this->createFormBuilder($search)
->add('words', 'text', array(
'label' => 'Search: ',
'error_bubbling' => true))
->getForm();
// Renders the template
return $this->render('EMMyFriendsBundle:Home:home.html.twig', array(
'name' => $name, 'friends' => $friends, 'user' => $user, 'birthdays' => $birthdays, 'pages' => $pages, 'page' => $page, 'link' => $link,
'dd_form' => $dd_form->createView(), 's_form' => $s_form->createView()));
}
Template
{% if birthdays != null %}
<div>
<img class="birthday" src="http://www.clker.com/cliparts/1/d/a/6/11970917161615154558carlitos_Balloons.svg.med.png">
<div class="try">
This friends have birthday today:
{% for bd in birthdays %}
<p>
{{ bd.name }}
<span class="years">
({{ bd.years }} years)
</span>
</p>
{% endfor %}
</div>
</div>
{% endif %}
{% for fr in friends %}
{# TODO: Fix where are shown #}
{% if fr.getWebPath()!=null %}
<a href="{{ path('friend_id', {'id': fr.id}) }}">
<img class="avatar" src="{{ fr.getWebPath }}">
</a>
{% endif %}
{% if loop.index is odd %}
<p class="list1">
{% else %}
<p class="list2">
{% endif %}
<a class="friends" href="{{ path('friend_id', {'id': fr.id}) }}">{{ fr.name }}</a>
</p>
{% endfor %}
{# TODO: Pagination #}
{% if pages>1 %}
<p>
{% for i in 0..pages %}
{% if page == loop.index %}
<span class="pagination">{{ loop.index }}</span>
{% else %}
<span class="pagination">{{ loop.index }}</span>
{% endif %}
{% endfor %}
</P>
{% endif %}
<p>Choose category:</p>
<form class="search" action="{{ path('filter') }}" method="post" {{ form_enctype(s_form) }}>
{{ form_widget(dd_form.name) }}
{{ form_rest(dd_form) }}
<input type="submit" value="Show friends" />
</form>
Repository
class FriendRepository extends EntityRepository
{
public function getFriendsFromTo ($user, $limit, $offset)
{
return $this->getEntityManager()
->createQuery('SELECT f FROM EMMyFriendsBundle:Friend f WHERE f.user='.$user. 'ORDER BY f.name ASC')
->setMaxResults($limit)
->setFirstResult($offset)
->getResult();
}
public function filterFriends ($filter)
{
$q = $this->createQueryBuilder('f');
$q->select('f')
->where('f.category = :filter')
->setParameter('filter', $filter);
return $q->getQuery()->getResult();
}
public function getFilteredFriendsFromTo ($filter, $limit, $offset)
{
$q = $this->createQueryBuilder('f');
$q->select('f')
->where('f.category = :filter')
->setMaxResults($limit)
->setFirstResult($offset)
->setParameter('filter', $filter);
return $q->getQuery()->getResult();
}
}
I tried a lot of things, but there is always a problem. In this code it says that the variable $all_friends in the birthday for loop is not defined - and yes, it isn't. Maybe I have to store it in session and I tried this:
$session = $this->getRequest()->getSession();
$session->set('all_friends');
and then passing $friends=$session->get('all_friends'); to the for loop, but it doesn't work and isn't the variable $all_friends too big to store it?
Any ideas will be apreciated! Thank you for your time and effort!
EDIT
When I use the way with the session and
$session = $this->getRequest()->getSession();
$session->set('all_friends');
$fri=$session->get('all_friends');
foreach ($fri as $fr)
{ .... }
the error I get is
Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\MyFriends\src\EM\MyFriendsBundle\Controller\HomeController.php line 100
and also
Warning: Missing argument 2 for Symfony\Component\HttpFoundation\Session::set(), called in C:\xampp\htdocs\MyFriends\src\EM\MyFriendsBundle\Controller\HomeController.php on line 71 and defined in C:\xampp\htdocs\MyFriends\app\cache\dev\classes.php line 148
When I don't use session I get
Notice: Undefined variable: all_friends in C:\xampp\htdocs\MyFriends\src\EM\MyFriendsBundle\Controller\HomeController.php line 100
when I choose a category to show the friends from it, and I click its second page.
P.S. The lines from the errors don't corespond to the lines in the code I pasted, bacause I skipped some parts of the action, repository and template, because they don't have a part in this problem and they work correctly. If someone wishes, I can send him or update here all the code.
You are setting nothing on session :
$session->set('all_friends');
You should be doing this instead:
$session->set('all_friends', $data);
You should really start respecting Symfony2 coding standards too.
My eyes are melting when I try to read your code. You should read this and don't forget to create form class instead of creating form in your controller.
EDIT: If your $data is a result from a Doctrine2 query, I suggest that you store only the entity id and the entity class in order to fetch them later when you need it.
EDIT2: Here's some code that might help you saving on session filters data. PS, don't forget to add the missing use ....
/**
* Set filters
*
* #param array $filters Filters
* #param string $type Type
*/
public function setFilters($name, array $filters = array())
{
foreach ($filters as $key => $value) {
// Transform entities objects into a pair of class/id
if (is_object($value)) {
if ($value instanceof ArrayCollection) {
if (count($value)) {
$filters[$key] = array(
'class' => get_class($value->first()),
'ids' => array()
);
foreach ($value as $v) {
$identifier = $this->getDoctrine()->getManager()->getUnitOfWork()->getEntityIdentifier($v);
$filters[$key]['ids'][] = $identifier['id'];
}
} else {
unset($filters[$key]);
}
} elseif (!$value instanceof \DateTime) {
$filters[$key] = array(
'class' => get_class($value),
'id' => $this->getDoctrine()->getManager()->getUnitOfWork()->getEntityIdentifier($value)
);
}
}
}
$this->getRequest()->getSession()->set(
$name,
$filters
);
}
/**
* Get Filters
*
* #param array $filters Filters
* #param type $type Type
*
* #return array
*/
public function getFilters($name, array $filters = array())
{
$filters = array_merge(
$this->getRequest()->getSession()->get(
$name,
array()
),
$filters
);
foreach ($filters as $key => $value) {
// Get entities from pair of class/id
if (is_array($value) && isset($value['class'])) {
if (isset($value['id'])) {
$filters[$key] = $this->getDoctrine()->getManager()->find($value['class'], $value['id']);
} elseif (isset($value['ids'])) {
$data = $this->getDoctrine()->getManager()->getRepository($value['class'])->findBy(array('id' => $value['ids']));
$filters[$key] = new ArrayCollection($data);
}
}
}
return $filters;
}
EDIT3: Why you're not using KnpPaginatorBundle for pagination ?
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...