symfony2 twig render, exception thrown - symfony

So in my base template, I have: {% render "EcsCrmBundle:Module:checkClock" %}
Then I created the ModuleController.php...
<?php
namespace Ecs\CrmBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Ecs\CrmBundle\Entity\TimeClock;
class ModuleController extends Controller
{
public function checkClockAction() {
$em = $this->getDoctrine()->getEntityManager();
$user = $this->get('security.context')->getToken()->getUser();
$today = time();
$start = date('Y-m-d 00:00:00');
$entities = $em->getRepository('EcsCrmBundle:TimeClock');
$query = $entities->createQueryBuilder('tc')
->select('tc.in1, tc.out1, tc.in2, tc.out2, tc.in3, tc.out3')
->where('tc.noteBy = :user')
->andWhere('tc.daydate >= :start')
->setParameter('user', $user->getid())
->setParameter('start', $start)
->setMaxResults('1')
->getQuery();
$entities = $query->getSingleResult();
if (empty($entities)) {
$ents = "clocked_out";
$this->get('session')->set('clockedin', 'clocked_out');
} else {
for ($i=1; $i <= 3; $i++) {
if ($entities["in$i"] != NULL) {
$ents = "clocked_in";
if ($i == 1) {
$this->get('session')->set('nextclock', "out$i");
} else {
$x = $i+1;
$this->get('session')->set('nextClock', "out$x");
}
if ($entities["out$i"] != NULL) {
$ents = "clocked_out";
$x = $i+1;
$this->get('session')->set('nextclock', "in$x");
}
if ($entities["out3"] != NULL) {
$ents = "day_done";
}
}
}
}
return $this->render('EcsCrmBundle:Module:topclock.html.twig', array(
'cstat' => $ents,
));
}
}
The problem is, if there is nothing in the database for the specific day for the specific user yet.. i keep getting:
An exception has been thrown during the rendering of a template ("No result was found for query although at least one row was expected.") in ::base.html.twig at line 161.
500 Internal Server Error - Twig_Error_Runtime
1 linked Exception: NoResultException ยป
I know it has something to do with the fact that is no 'result' from the database... but isn't that what i've accomplished by having the if (empty($entities)) { ?? I have no clue to fix it... any help appreciated...

Replace:
$entities = $query->getSingleResult();
With
$entity = $query->getOneOrNullResult();
If you look in Doctrine\ORM\AbstractQuery you will see that getSingleResult expects one and only one results. 0 will through an exception.
I looked at your code a bit more closely and it looks like you actually expect an array of entities. in which case use:
$entities = $query->getResult();

Related

Drupal 8 - Get All Nodes With a Part of Url Alias

I try to find a way to get all nodes by a part of the url alias in the nodes. I know i get a specific node by the complete url alias. For example:
$path = \Drupal::service('path.alias_manager')->getPathByAlias('/this-is-the-alias');
if(preg_match('/node\/(\d+)/', $path, $matches)) {
$node = \Drupal\node\Entity\Node::load($matches[1]);
}
And I know I can find multiple nodes by entity query:
$nids = \Drupal::entityQuery('node')
->condition('type','page')
->condition('status',1)
->sort('created', 'DESC')
->range(0, 20)
->execute();
But I want to know how I can implement an additional condition to filter nodes by a part of the URL alias for example "/news/*". I need all nodes with this url fragment.
Can try this-
Reference https://www.jonkamke.com/blog/2019/5/load-a-node-via-url-alias
<?php
/** #var Drupal\Core\Url $url */
$url = $variables['url'];
if ($url instanceof Drupal\Core\Url) {
$nid = $url->getRouteParameters()['node'];
/** #var \Drupal\node\Entity\Node $node */
$node = Node::load($nid);
if ($node instanceof Node) {
$type = $node->getType();
}
}
$input = '/this-is-the-alias';
$node_query_result = [];
$path_query = \Drupal::database()->select('path_alias', 'a');
$path_query->addField('a', 'path');
$path_query->condition('a.alias', '%' . $input . '%', 'LIKE');
$path_query_result = str_replace('/node/', '', $path_query->execute()->fetchCol());
if ($path_query_result) {
$node_query = \Drupal::database()->select('node_field_data', 'n');
$node_query->addField('n', 'nid');
$node_query->addField('n', 'type');
$node_query->addField('n', 'title');
$node_query->condition('n.status', NodeInterface::PUBLISHED);
$node_query->condition('nid', $path_query_result, 'IN');
$node_query_result = $node_query->execute()->fetchAll(\PDO::FETCH_ASSOC);
}
return $node_query_result;

Timber - extend data to context (WordPress)

So I'm trying to make this functions data available to each context there this, but I'm stuck with how to actually get the data itself now that its part of the context.
I have the following:
add_filter( 'timber_context', 'fancySquares_get_instagram_images' );
function fancySquares_get_instagram_images( $context ) {
$context['instaImages'] = [];
$api = wp_remote_request("testUrlHere");
$api = json_decode($api['body']);
for($i = 0; $i < 20; $i++)
{
$images[$i] = [];
$images[$i]['image'] = $api->data[$i]->images->standard_resolution->url;
$images[$i]['url'] = $api->data[$i]->link;
$images[$i]['likes'] = $api->data[$i]->likes->count;
}
return $context;
}
I am them trying to print out the result to make sure I'm doing it right, it returns an empty Array():
{{ instaImages|print_r}}
Any help would be appreciated. Thank you!
Here is the for the above question, hope this helps someone in the future.
You'll add the filter:
inside the function passed to the filter, you'll set the CONTEXT variable to the function where you'll run all your magic
and then return the CONTEXT so you can use it throughout the site at your discretion
code sample:
add_filter( 'timber_context', 'fancySquares_show_instagram_results' );
function fancySquares_show_instagram_results( $context ) {
$context['fancySquaresInstagram'] = fancySquares_get_instagram();
return $context;
}
function fancySquares_get_instagram()
{
if(get_transient('instagram'))
{
return get_transient('instagram');
}
else
{
$api = wp_remote_request("instagram-api-url");
$api = json_decode($api['body']);
$images = [];
for($i = 0; $i < 20; $i++)
{
$images[$i] = [];
$images[$i]['image'] = $api->data[$i]->images->standard_resolution->url;
$images[$i]['url'] = $api->data[$i]->link;
$images[$i]['likes'] = $api->data[$i]->likes->count;
}
set_transient('instagram', $images, 60*60*24); // expires every day
return $images;
}
}
You will then output with:
{% for insta in fancySquaresInstagram %}
{{insta['url']}}
{% endfor %}
or could print the whole thing to get a better idea of whats inside:
{{ fancySquaresInstagram|print_r }}

Doctrine DQL query produces Error: Expected Literal, got end of string

I am currently trying to build a blog website following a course that uses
Symfony 2.5.2. (PHP -v 7.0)
To retrieve a post I am using a following Controller
/**
* #Route(
* "/{slug}",
* name = "blog_post"
* )
* #Template()
*/
public function postAction($slug)
{
$PostRepo = $this->getDoctrine()->getRepository('AniaBlogBundle:Post');
$Post = $PostRepo->getPublishedPost($slug);
if(null === $Post){
throw $this->createNotFoundException('Post not found');
}
return array(
'post'=> $Post
);
}
and here is my getPublishedPost function :
public function getPublishedPost($slug){
$qb = $this->getQueryBuilder(array(
'status' => 'published'
));
$qb->andWhere('p.slug = :slug')
->setParameter('slug', $slug);
return $qb->getQuery()->getOneOrNullResult();
}
and getQueryBuilder function :
public function getQueryBuilder(array $params = array()){
$qb = $this->createQueryBuilder('p')
->select('p, c, t')
->leftJoin('p.category', 'c')
->leftJoin('p.tags', 't');
if(!empty($params['status'])){
if('published' == $params['status']){
$qb->where('p.publishedDate <= :currDate AND p.publishedDate IS NOT NULL')
->setParameter('currDate', new \DateTime());
}else if('unpublished' == $params['status']) {
$qb->where('p.publishedDate > :currDate OR p.publishedDate IS NULL')
->setParameter('currDate', new \DateTime());
}
}
if(!empty($params['orderBy'])){
$orderDir = !empty($params['orderDir']) ? $params['orderDir'] : NULL;
$qb->orderBy($params['orderBy'], $orderDir);
}
if(!empty($params['categorySlug'])){
$qb->andWhere('c.slug = :categorySlug')
->setParameter('categorySlug', $params['categorySlug']);
}
if(!empty($params['tagSlug'])){
$qb->andWhere('t.slug = :tagSlug')
->setParameter('tagSlug', $params['tagSlug']);
}
if(!empty($params['search'])) {
$searchParam = '%'.$params['search'].'%';
$qb->andWhere('p.title LIKE :searchParam OR p.content LIKE :searchParam')
->setParameter('searchParam', $searchParam);
}
return $qb;
}
}
However i get the 500 error saying : [Syntax Error] line 0, col -1: Error: Expected Literal, got end of string.
Thank you in advance for any suggestions!

Multiple select DQL

I have:
if (count($data['paymentTypes'])<5) {
$arr = array();
foreach (array_values($data['paymentTypes']) as $value) { $arr[]=$value->getId(); }
$query = $query->leftJoin('p.payments','g')->where('g.id IN(:num)')->setParameter('num', $arr);
}
if (count($data['expertise']->toArray())>0) {
$arr = array();
foreach (array_values($data['expertise']->toArray()) as $value) { $arr[]=$value->getId(); }
$query = $query->leftJoin('p.expertise','g')->where('g.id IN(:num)')->setParameter('num', $arr);
}
How may I stop the query from breaking in case both statements are true? I would expect leftjoins and wheres to congregate but they throw an exception instead. What is the cleanest way of accomplishing this?
Use different alias and parameter name in the second part than in the first.

Symfony2 / Typecasting query results to simpeler object

I am using Stof's DoctrineExtension bundle to retrieve my Tree, now I want to convert that tree to an array (which will then in turn get converted to json).
The format of NestedTreeRepository->childrenHierarchy() is not in the correct format though, I want to modify the output so only the node "title" property and the "id" property is returned, and put any children in a "children" subarray. In compliance with this format (JSON):
{
label: 'node1',
children: [
{ label: 'child1' },
{ label: 'child2' }
]
},
{
label: 'node2',
children: [
{ label: 'child3' }
]
}
}
I have tried to following code, this returns the same as childrenHierarchy() but would allow me to modify the query.
$query = $em
->createQueryBuilder()
->select('node')
->from('MyBundle:Page', 'node')
->orderBy('node.root, node.lft', 'ASC')
->getQuery()
;
$nodes = $query->getArrayResult();
[Do magic here]
$tree = $pagerepo->buildTree($nodes);
Is it possible to typecast every node into a much simpler object containing only the following property's:
id
title
a few other ints used for positioning
if I would then run that through json_encode() I would have exactly what I needed.
Any other solutions are of course welcome.
my code for this purpose (just made this a few hours ago)
it's a remake of stof's buildTreeArray function
in the controller (I'm writing this for symfony2):
function gettreeAction {
$query = .... // do your query
$tree = $this->buildTree($query->getArrayResult());
$response = new Response(json_encode($tree));
return $response;
}
private function buildTree($nodes)
{
$nestedTree = array();
$l = 0;
if (count($nodes) > 0) {
// Node Stack. Used to help building the hierarchy
$stack = array();
foreach ($nodes as $child) {
$item = array();
$item['name'] = $child['title'];
$item['id'] = 'page_'.$child['id'];
$item['level'] = $child['level'];
$item['children'] = array();
// Number of stack items
$l = count($stack);
// Check if we're dealing with different levels
while($l > 0 && $stack[$l - 1]['level'] >= $item['level']) {
array_pop($stack);
$l--;
}
// Stack is empty (we are inspecting the root)
if ($l == 0) {
// Assigning the root child
$i = count($nestedTree);
$nestedTree[$i] = $item;
$stack[] = &$nestedTree[$i];
} else {
// Add child to parent
$i = count($stack[$l - 1]['children']);
$stack[$l - 1]['children'][$i] = $item;
$stack[] = &$stack[$l - 1]['children'][$i];
}
}
}
return $nestedTree;
}
works perfectly with jqTree...
I have solved it as following:
public function getPageTreeAction() {
$pagerepo = $this->getDoctrine()->getRepository('MyBundle:Page');
$em = $this->getDoctrine()->getEntityManager();
$query = $em
->createQueryBuilder()
->select('node')
->from('MyCorpBundle:Page', 'node')
->orderBy('node.root, node.lft', 'ASC')
->getQuery();
$flatnodearray = $query->getArrayResult();
$flatsimplenodearray = array();
foreach ($flatnodearray as $currentNode) {
$currentSimpleNode = array();
$currentSimpleNode['id'] = $currentNode['id'];
$currentSimpleNode['lft'] =$currentNode['lft'];
$currentSimpleNode['rgt'] = $currentNode['rgt'];
$currentSimpleNode['lvl'] = $currentNode['lvl'];
$currentSimpleNode['title'] = $currentNode['title'];
$flatsimplenodearray[] = $currentSimpleNode;
}
$tree = $pagerepo->buildTree($flatsimplenodearray);
$response = new Response(json_encode($tree));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
I would use the Stofs Repository function to get the nodes in an hierarchical array:
$repo = $em->getRepository('MyBundle:Page');
$arrayTree = $repo->childrenHierarchy();
And I think there is no other solution than modify that array manually. After you have removed some properties that you dont need, you can json_encode the array and return it.

Resources