Twig - Looping through tweet text from twitter API - php

I am using Abraham's TwitterOAuth library along with Twig to build a mini app where users authorize then search for tweets based on their input.
I can successfully dump the return from the API to my page, but when I try to isolate just the tweet text for each tweet returned I'm having no luck.
Here's the relevant code for my dashboard.php file:
$user = $connection->get("account/verify_credentials");
if(isset($_POST['query'])) {
$query = $_POST['query'];
$statuses = $connection->get("search/tweets", array("q" => "$query"));
echo $twig->render("dashboard.html", array("access_token" => $access_token, "user" => $user, "statuses" => $statuses));
} else {
echo $twig->render("dashboard.html", array("access_token" => $access_token, "user" => $user));
}
And then the problem code in my twig template:
{% if statuses %}
<ul>
{% for status in statuses %}
<li>{{ statuses.text|e }}</li>
{% endfor %}
</ul>
{{ dump(statuses) }}
{% endif %}
The {{ dump(statuses) }} works, but nothing is spit out inside the UL. I'm very new to all of this, so I've just been looking at Abraham's example code here, where he does this:
{% if user.status %}
{{ user.status.text }}
{% else %}
{{ user.description }}
{% endif %}
So I figured I could do the same thing, but it's not working for me. What am I missing?

Well I figured it out by comparing the example responses from the GET account/verify_credentials (the request being sent out in Abraham's user code) and the GET search/tweets.
If you compare the beginnings of the responses, you will notice that there is an extra level to traverse with the search/tweets response.
So instead of doing:
{% for status in statuses %}
<li>{{ statuses.text|e }}</li>
{% endfor %}
I did:
{% for status in statuses.statuses %}
<li>{{ statuses.text|e }}</li>
{% endfor %}
I realize the naming there isn't great, but to break it down for any other newbs like me: the first "statuses" is the variable I sent to twig, the second "statuses" is from the response I'm getting from the API.
In my original code there was nothing to loop through because I hadn't gone far enough down to reach the information about the individual tweets, I was basically trying to loop through the parent.

Related

Symfony Undefined variable (contexterror exception) when array empty in controller

Here is the thing. A trainer can speak zero to many languages. I want to display the languages for one or several trainers on a page. Note that I'm working on a code I didn't start from scratch.
In my controller :
foreach ($trainers as $trainer){
$trainer_entity = $doctrine->getRepository('AppBundle:Trainer')->find($trainer["id"]);
$listLangues = $this->getDoctrine()
->getManager()
->getRepository('AppBundle:TrainerLangues')
->findByTrainer_id($trainer["id"]);
}
return [
'user' => $user,
'listLangues' => $listLangues,
'trainers' => $trainers,
];
In my twig file:
{% if listLangues %}
<b>Langues</b> :
{% for l in listLangues %}
{{ l.langue.name }}
{% endfor %}
{% endif %}
This works when the person is linked to languages, so listLangues not empty.
Otherwise I get
Notice: Undefined variable: listLangues 500 Internal Server Error -
ContextErrorException
I tried {% if listLangues is defined %} as well, but the system seems to block in the controller. It never happened to me before.
note that initializing $listLangues only leads to no display on the twig page.
Any idea?
what do you really want to display in your view?
Here is a simple tips, you could try in your controller:
/***/
public function yourAction()
{
return $this->render('your-template.html.twig', [
'user' => $this->getUser(),
'trainers' => $this->getDoctrine()->getRepository(Trainer::class)->findAll()
]);
}
/***/
Then, in your view (basic implementation)
{% for trainer in trainers %}
<h4>{{ trainer.name }}</h4>
{% if trainer.languages %}
<ul>
{% for language in trainer.languages %}
<li>{{ language.name }}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
Hope, it will help you.
If your array $trainers is empty, the foreach nevers loops so the $listLangues var is never defined.
Try declaring it as an empty array BEFORE the foreach :
$listLangues = array();
You need to instantiate $listLangues because if there isn't trainers the variable can't exist and code is broke.
Try to add this before your foreach:
$listLangues = null;
Or instantiate It with a value or what you want but declare It before your foreach to be sure that exists

OctoberCMS Backend User Permissions with Twig

I'm using OctoberCMS which uses Twig.
The way I retrieve user permissions is by getting the information in php then pass a twig variable.
Is there a way to do this using just Twig?
Permissions Docs
PHP
if (BackendAuth::check()) {
# Get User Info
$backend_user = BackendAuth::getUser();
# Superuser
$this['is_superuser'] = $backend_user->is_superuser;
# Permissions
$this['permissions_allow_edit'] = $backend_user->hasPermission(
[
'mycomponent.gallery.allow_edit'
]);
}
Twig
{% if is_superuser or permissions_allow_edit %}
//edit button
{% endif %}
Twig (Standalone)
//another way to backendauth check in twig?
if (BackendAuth::check()) {
$this['backend_user'] = BackendAuth::getUser();
}
//////
{% if backend_user.is_superuser or backend_user.permissions.mycomponent.gallery.allow_edit %}
//edit button
{% endif %}
{{ backend_user }} gives the user information array
{"id":2,"first_name":"Matt","last_name":"","login":"matt","email":"user#example.com","permissions":{"mycomponent.gallery.allow_edit":1},"is_activated":false,"activated_at":null,"last_login":"2017-03-11 09:59:48","created_at":"2017-02-11 10:32:14","updated_at":"2017-03-11 10:03:45","is_superuser":0}
{{ backend_user.permissions }} throws an "Array to string conversion" error.
{{ backend_user.permissions.mycomponent.gallery.allow_edit }} shows nothing.
How do I get the values inside the permissions array?
I have not tested this but you should be able to use the hasPermission method to check if backend user has a specific permission:
{% if backend_user.is_superuser or backend_user.hasPermission('mycomponent.gallery.allow_edit') %}
//edit button
{% endif %}

Limit, pagination in Symfony

I am trying to add pagination to my current project. I am pretty new to Symfony so I am not sure if there is something out there that can help me build such. My current code looks like this:
Controller class:
class MovieDisplayController extends Controller
{
public function showAction()
{
$movies = $this->getDoctrine()->getEntityManager()->getRepository('AppBundle:Movie')->FindAll();
return $this->render('movies/index.html.twig', array(
'movies' => $movies
));
}
}
Twig template:
{% block body %}
{% if movies|length == 0 %}
There are no movie items available. Add a movie here to get started.
{% elseif movies|length != 0 %}
These are the results: <br />
<ul>
{% for x in movies %}
<li>Title: {{ x.title }} - Price: {{ x.price }} - Edit - Details - Delete</li>
{% endfor %}
</ul>
Add more movie entries
{% endif %}
{% endblock %}
This will return all results within the database. I would like to only show 5 results (rows per page) and add paging buttons below the list and I wonder how/if this is possible?
The findAll() function will not work if you want to set limit.
You can try KnpPaginatorBundle to add pagination in symfony. It will work with fine to add pagination.
https://github.com/KnpLabs/KnpPaginatorBundle

Name of Twig variable in a Twig variable

I get a list of collections right from Doctrine and I store them into an array.
For example:
$data['collList'] = $heyDoctrine->giveMeMyColls();
But I also want to retrieve some informations about these collections.
I store it into $data['collectionId'].
Until this point, everything works fine.
But in my Twig template, I want to create ordered lists with the name of my collection and every item of this list would be an information about this collection.
So, in PHP, I would do this:
foreach($data['collList'] as $collItem){
echo $collItem['name'];
echo '<ul>';
foreach($data[$collItem['id']] as $collItemData){
echo '<li>'.$collItemData.'</li>';
}
}
My problem is: how to do this with Twig?
I don't know how to say to Twig «hey, use «coll.id» as THE NAME of an other variable!
I've looked a bit and I've found the «attribute» function, but I wasn't able to make it work.
How should I do that?
Thanks a lot.
So, try next twig code:
{% for key, collItem in data.collList %}
{{ collItem.name }}
<ul>
{% for collItemData in data[collItem.key] if key == 'id' %}
<li> {{ collItemData }} </li>
{% endfor %}
</ul>
{% endfor %}

Avoid repeating the same query in controllers for parent template

I am trying to make a messaging system and I'm facing a small problem. I have a bigger template that displays my menu and my content. The menu includes the number of new messages, and the content can be any page(compose a new message, inbox, sent).
The problem is that I have to render each of the small templates by passing the number of new received messages to each of them, calling the doctrine each time and repeating code. Is there any way to send the number only to the parent template?
Here are my templates:
This is the parent containing the newmsg variable that gives me problems.
{% extends "::base.html.twig" %}
{% block body %}
inbox : {{ newmsg }}
sent
compose
{% endblock body %}
Here is an example of child template:
{% block body %}
{{ parent() }}
{% if messageList %}
{% for message in messageList %}
<li>title = {{ message.title|e }}</li>
<li>cont= {{ message.content|e }}</li>
<li>data= {{ message.date|date('d-m-Y H:m:s') }}</li>
<li>sender= {{ message.sender|e }}</li>
<hr>
{% endfor %}
{% else %}
<div>no messages</div>
{% endif %}
{% endblock body %}
The problem is that each child template is asking me for the newmsg variable
$messages = $this->getDoctrine()->getRepository('MedAppCrudBundle:Message');
$newMessagesNo = count($messages->findBy(array('seen' => '0', 'receiver' => $this->getUser())));
return $this->render(
'MedAppCrudBundle:UserBackend\Message:new.html.twig',
array(
'form' => $form->createView(),
'newmsg' => $newMessagesNo,
)
);
And I have to write this in every single controller. Any way I can shorten this problem?
You could implement a service that gives back the newmsg value and call it on your parent template. Then it would not be necessary to pass the variable.
You can add a service in your bundle's services.yml with something like:
services:
newmessages:
class: Full\Class\Name\NewMessagesService
arguments: ["#doctrine.orm.entity_manager"]
Then, implement the Full\Class\Name\NewMessagesService class. Keep in mind that this class will need a constructor that receives an EntityManager argument. Something like:
<?php
namespace Full\Class\Name;
class NewMessagesService{
private $entityManager;
public function __construct($entityManager){
$this->entityManager = $entityManager;
}
public function methodToCalculate(){
//Perform calculation and return result
}
}
Then, in your parent template, replace {{newmsg} with:
{{ newmessages.methodToCalculate() }}

Categories