How to stop array from being overwritten? - php

I'm using Symfony2, version 2.7. But anyone should be able to answer this because it's not entirely relevant to symfony.
I have a function. I want that function to add a new item (once clicked on from a form) to an array. Instead, my array keeps getting overwritten with the new item that was clicked.
I tried a few foreach loops but couldn't get it right. Please, any help is appreciated.
Below is relevant function.
/**
* Displays Bought Items
*
* #Route("/buy/{id}", name="item_buy")
* #Method("GET")
* #Template()
*/
public function buyAction(Request $request, $id)
{
$session = $request->getSession();
$cart[] = $id;
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('AppBundle:Item')->find($id);
$entities = $em->getRepository('AppBundle:Item')->findAll();
$session->set('cart', $cart);
if (!$entity) {
throw $this->createNotFoundException('No Item ');
} else {
$cart[$entity->getId()] = $entity->getName();
}
$session->set('cart', $cart);
return array(
'cart' => $cart,
'entity' => $entity,
'entities' => $entities,
);
}
How it is being used in twig:
{% extends '::base.html.twig' %}
{% block body -%}
<h1>Items Bought...</h1>
<table class="record_properties">
<h3>You Bought...</h3>
{# {% if entity is defined %} #}
{% for key, cartValue in cart %}
<tr>
<td>{{ key }}: {{ cartValue }}</td>
{{ dump(entity.name) }}
{{ dump(cart) }}
</tr>
{% endfor %}
{# {% endif %} #}
<tbody>
{% for entity in entities %}
<tr>
<td>{{ entity.id }}</td>
<td>{{ entity.name }}</td>
<td>
<ul>
<li>
Buy
</li>
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<ul class="record_actions">
<li>
<a href="{{ path('item') }}">
Back to the list
</a>
</li>
{% endblock %}

Maybe I am wrong, but I guess that this line is problem:
$cart[] = $id;
You initialize here new array, every time. If I am wright You shuld get this array from session.
Try
$cart = $this->get('session')->get('cart', []);

For better formats of code I am answering to Your last comment here.
Above You're writting about adding new elements and I helped You solve this problem. Now (if I understand correclty) You have problem with added elements to array which You saved in session. I'm surprised your surprise. If You want delete something now from array which You saved in session YOU HAVE TO IMPLEMENT IT. It's not difficult - to clear a cart You should write something like this:
public function clearCartAction(Request $request)
{
$session->set('cart', array()); //set empty array
//return something here..
}
To delete single object from cart something like this (very simple implementation):
public function removeAction(Request $request, $id)
{
$session = $request->getSession();
$em = $this->getDoctrine()->getManager();
$cart = $session->get('cart', array());
if (isset($cart[$id]) {
unset($cart[$id]);
}
$session->set('cart', $cart);
//return something here
}
I can see that You have many very basic problems - definatelly You need a lot of learn and study programming.
Btw. I guess that I helped You solve problem describing in topic - so You should mark my comment as helpfull and topic as resolved.

Related

How to display RangeType values as a table in twig?

I would like to display the values in tmp ,tmp2 ,tmp3 as a table using the list.html.twig file. I tried using a form to display the values but I can't understand how to pass the values to the twig file to make a table containing these values (name , age , task)
The only way I can display these values is by using echo for each value in all__users
Here is the code of my controlleur:
/**
* #Route("/list", name="list_Users")
*/
public function list()
{
$form = $this->createFormBuilder()
->add('name', RangeType::class)
->add('age', RangeType::class)
->add('task', RangeType::class)
->getForm();
$all_Users = $this->getDoctrine()
->getRepository(User::class)
->findAll();
if (!$all_Users) {
throw $this->createNotFoundException(
'database is empty or there was an error connecting to db'
);
}
for ($x =0; $x < count($all_Users); $x++ ){
echo "$x";
$tmp = $all_Users[$x]->getName();
$tmp2 =$all_Users[$x]->getAge();
$tmp3 = $all_Users[$x]->getTask();
echo "$tmp ,$tmp2 , $tmp3 \n";
echo "\n";
}
return $this->render('User/list.html.twig', [
'form' => $form->createView(),
]);
}
This should work. But you need to render 'users' too. Or you could write your own extension.
<tr>
{% for property_title in users|keys %}
<td>{{ property_title }}</td>
{% endfor %}
</tr>
{% for user in users%}
<tr>
{% for field in users|keys %}
<td>{{ attribute(user, field) }}</td>
{% endfor %}
</tr>
{% endfor %}
If you want render form as table. Look here. It should answer all your questions.

Simple pagination with twig

I'm trying to create a simple pagination with a twig view.
I'm not using Symfony.
Here is my method from my manager :
public function getAllPosts()
{
if(isset($_GET['p']) && (!isset($_GET['page']))){
$currentPage = 1;
}
else {
$currentPage = $_GET['page'];
}
$q= $this->_db->query('SELECT COUNT(id) AS numberposts FROM posts');
$data = $q->fetch(PDO::FETCH_ASSOC);
$number_posts= $data['numberposts'];
$perPage = 1;
$numberPages = ceil($number_posts/$perPage);
$q = $this->_db->query("SELECT * FROM posts ORDER BY date DESC LIMIT ".(($currentPage-1)*$perPage).",$perPage");
while($data = $q->fetch(PDO::FETCH_ASSOC))
{
$datas[] = new Post($data);
}
return $datas;
}
I want to create a loop in my view, this is what I'm doing
{% for posts in allPosts %}
{% for i in 1..numberPages %}
{{ i }}
{% endfor %}
{% endfor %}
But it's not working. It seems like I can't access to numberPages and I don't know why.
If anybody can help me !
Thanks a lot
EDIT
My pagination is working now.
I had this in my method like #darkbee :
return array(
'records' => $datas,
'numberPages' => $numberPages,
);
And in my view :
{% for i in 1.. allPosts.numberPages %}
<li>{{ loop.index}}</li>
{% endfor %}
But now I have another issue. I only get the same posts in all the pages.
EDIT
I forgot the page= on my pages links ...
<li>{{ loop.index}}</li>
It's working now !
Thanks !
You need to return the number of pages as well.
An aproach could be this,
public function getAllPosts() {
/** ... code .. **/
return array(
'records' => $data,
'numberPages' => $numberPages,
);
}
{% for posts in allPosts.records %}
{% for i in 1.. allPosts.numberPages %}
{{ i }}
{% endfor %}
{% endfor %}

How to recursively display comments using twig?

I'm rewriting an application using the Silex framework. In this application, users can comment on posts and comments. In the non-MVC application, inspired by this question, I wrote it like this:
function display_comments($postid, $parentid=0, $level=0){
// Get the current comment from DB and display with HTML code
display_comments($needid, $comment['id'], $level+1);
}
However, in the Silex application, I want to retrieve them comment(s) from the database in a repository, send it to a twig-template in the controller and finally display the HTML code in the template. This makes the previous solution incompatible.
What is a good solution for this problem in Silex? What do I put in the view, what in the controller and what in the model?
EDIT
I wrote the function in the controller now:
$app->get('/needdetail/{id}', function ($id) use ($app) {
$need = $app['need']->findNeed($id);
function display_comments($app, $needid, $comments=array(), $parentid=0, $level=0){
$replies = $app['comment']->findByNeed($needid, $parentid);
foreach($replies as $reply){
$reply['level'] = $level;
array_push($comments, $reply);
display_comments($app, $needid, $comments, $reply['id'], $level+1);
}
return $comments;
}
return $app['twig']->render('needdetail.html', array('need' => $need, 'comments' => display_comments($app, $id)));
})
The level 0 comments are now shown, but a deeper level isn't.
I managed to get the required result with a slightly different approach. The controller as well as the view contains a recursive function:
Controller:
$app->get('/needdetail/{id}', function ($id) use ($app) {
$need = $app['need']->findNeed($id);
function get_comments($app, $needid, $parentid=0){
$comments = array();
$replies = $app['comment']->findByNeed($needid, $parentid);
foreach($replies as $comment){
$comment['replies'] = get_comments($app, $needid, $comment['id']);
array_push($comments, $comment);
}
return $comments;
}
return $app['twig']->render('needdetail.html', array('need' => $need, 'comments' => get_comments($app, $id)));
})
View:
{% for comment in comments %}
{% include 'comment.html' with {'level': 0} %}
{% endfor %}
Comment.html:
<div class="comment">
//Comment HTML
</div>
{% if comment.replies %}
{%for reply in comment.replies %}
{% include 'comment.html' with {'comment': reply, 'level': level+1} %}
{% endfor %}
{% endif %}

Pagination, session and a controller's action - Symfony2

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 ?

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