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

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!

Related

Maatwebsite 3.1 import, Queue does not work

My file is excel .xlsx contains more than 20,000 rows, im using Centos 7 with Nginx web server. When i upload a small size file with few rows it works but when i introduce ShouldQueue and WithChunkReading interfaces it fails even if the file is small. Please I need help. Thanks for your time
Here is the error in a log file
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php
[2019-07-11 14:48:47] development.ERROR: [0] File "/tmp/laravel-excel-4noteGu1gFjJoFClKJQsLw8SgDShm1nd.xlsx" does not exist. on line 344 of file vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php
[2019-07-11 14:48:47] development.ERROR: [0] File "/tmp/laravel-excel-4noteGu1gFjJoFClKJQsLw8SgDShm1nd.xlsx" does not exist. on line 344 of file vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php
Here is a queue error
[2019-07-12 10:11:47][532] Processing: Maatwebsite\Excel\Jobs\QueueImport
[2019-07-12 10:11:47][532] Processed: Maatwebsite\Excel\Jobs\QueueImport
[2019-07-12 10:11:47][533] Processing: Maatwebsite\Excel\Jobs\ReadChunk
[2019-07-12 10:11:47][534] Processing: Maatwebsite\Excel\Jobs\ReadChunk
[2019-07-12 10:11:47][535] Processing: Maatwebsite\Excel\Jobs\ReadChunk
[2019-07-12 10:11:47][535] Failed: Maatwebsite\Excel\Jobs\ReadChunk
Here is my controller function
public function store(Request $request)
{
Excel::import(new HsCodeImport(),"650.xlsx",'local');
return redirect()->back()->withFlashSuccess(__('label.app_success'));
}
Here is my Import file on App\Imports\HsCodeImport.php
<?php
namespace App\Imports;
use App\Exceptions\GeneralException;
use App\Models\Application\Hscode;
use App\Models\ReceiptCode\ReceiptCode;
use Carbon\Carbon;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
class HsCodeImport implements ToCollection, WithHeadingRow, ShouldQueue, WithChunkReading
{
use Importable;
protected $receiptCode;
protected $chunk = 500;
protected $hscode_key = 'hscode';
protected $description_key = 'description';
protected $regulatory_status_key = 'regulatory_status';
protected $comment_key = 'comment';
protected $headings = ['hscode','description','regulatory_status','comment'];
public function __construct(/*ReceiptCode $receiptCode*/)
{
// $this->receiptCode = $receiptCode;
}
/**
* #param Collection $collection
* #throws GeneralException
*/
public function collection(Collection $collection)
{
/*fetching the first Collection*/
$columns = $collection->first();
if (!$columns->has($this->headings)) {
/*When file has different headings*/
} else {
/*When the file has expected headings*/
/*Truncate temp table*/
DB::table('hs_code_temps')->truncate();
/*Counting rows on a file*/
$original_file_rows_count = $collection->count();
/*Chunk the file data according #var $chunk*/
$chunks = $collection->chunk($this->chunk);
/*read each chunks insert into Temporary table and validate to get if there is error in each row*/
$chunks->each(function ($item) {
/*Iterate on each chunk*/
$item->toArray();
foreach ($item as $row) {
/* start: Validating row entries */
$error_report = "";
$error = 0;
foreach ($row as $key => $value) {
if (trim($key) == $this->hscode_key) {
if (trim($value) == "" Or $value == NULL) {
$error = 1;
$error_report = $error_report . trans('exceptions.backend.upload.entries', ['column' => $key, 'entry' => $value]) . ", \r\n";
$row[$key] = NULL;
}
} elseif (trim($key) == $this->description_key) {
if (trim($value) == "" Or $value == NULL) {
$error = 1;
$error_report = $error_report . trans('exceptions.backend.upload.entries', ['column' => $key, 'entry' => $value]) . ", \r\n";
$row[$key] = NULL;
}
} elseif (trim($key) == $this->regulatory_status_key) {
if (trim($value) == "" Or $value == NULL) {
$error = 1;
$error_report = $error_report . trans('exceptions.backend.upload.entries', ['column' => $key, 'entry' => $value]) . ", \r\n";
$row[$key] = NULL;
}
}
}
/*Inserting into Temp table*/
DB::table('hs_code_temps')->insert([
'code' => $row[$this->hscode_key],
$this->description_key => $row[$this->description_key],
$this->regulatory_status_key => $row[$this->regulatory_status_key],
$this->comment_key => $row[$this->comment_key],
'receipt_code_id' => 1/*$receiptCode->id*/,
'error' => $error,
'error_report' => $error_report,
'created_at' => Carbon::now(),
]);
/* end: Validating row entries*/
}
});
/*compare total rows with no error to total rows of the file*/
$total_temp_rows_count = DB::table('hs_code_temps')->whereError(0)->count();
if ($total_temp_rows_count != $original_file_rows_count) {
/*When there is error and rows are not equal*/
} else {
/*When there is no error*/
$originalHsCode = new Hscode();
$temp_table = DB::table('hs_code_temps')->get(['code', $this->description_key, $this->regulatory_status_key, $this->comment_key])/*->toArray()*/;
/*Iterate throw the rows in a temp row*/
foreach ($temp_table as $object) {
/*copy data from temp table to origin table*/
$originalHsCode->create(get_object_vars($object));
}
/*Truncate temp table*/
DB::table('hs_code_temps')->truncate();
}
}
}
public function headings(): array
{
return ['HSCode','Description','Regulatory_Status','Comment'];
}
/*public function sheets(): array
{
}*/
public function chunkSize(): int
{
return 500;
}
public function batchSize(): int
{
return 500;
}
}
I expect the job to run a large data to a chunk to be processed
pass false as third parameter to chunk() to disable queuing
$data = [];
Excel::filter('chunk')->load($path)->chunk(1000, function ($results) use (&$data) {
foreach ($results as $row) {
$data[] = $row;
}
}, $shouldQueue = false);
return $data;
I have a similar problem when deplying to heroku ,that points to a problem with the path.:
`ERROR: [0] File "/tmp/laravel-excel-4noteGu1gFjJoFClKJQsLw8SgDShm1nd.xlsx"
does not exist. on line 344 of file
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php`
laravel-excel defines local_path variable in config/excel.php, so try changing the path here or check your public_path() where you are geting the problem.
in my case the excemption saved in table failde_jobs is:
"exception": """ InvalidArgumentException: File "/app/storage/framework/laravel-excel/laravel-excel-aCnUQTJT7ADvAnrf1AOEcaCBPLjhauij" does not exist. in /app/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php:135\n
have been trying to see how to change sot that it does not go in the app folder..

accessing repository in symfony

I am using symfony and am inside the controller trying to return a set of records by using a range (rangeUpper, rangeLower).
I am passing the parameters in the request object fine. But when going to route in the controller and trying to access the repository class I am at a loss. My repository looks like;
public function findAllByParams (Request $request)
{
$criteria = $request->query->get('uniflytebundle_material-stock_select');
$criteria = ($request->get('materialId') == 0 ? [] : ['materialId' => $request->get('materialId')]);
$criteria = array_merge(($request->get('gaugeId') == 0 ? [] : ['gaugeId' => $request->get('gaugeId')]), $criteria);
$criteria = array_merge(($request->get('rangeUpper') == 0 ? [] : ['rangeUpper' => $request->get('rangeUpper')]), $criteria);
$criteria = array_merge(($request->get('rangeLower') == 0 ? [] : ['rangeLower' => $request->get('rangeLower')]), $criteria);
$criteria = array_filter($criteria);
$query = $this->createQueryBuilder('ms');
if (!empty($criteria)) {
if (!empty($criteria['materialId']) && !empty($criteria['gaugeId']) && !empty($criteria['rangeUpper']) && !empty($criteria['rangeLower'])) {
$query
->where('ms.material = :materialId')
->andWhere('ms.gauge = :gaugeId')
->andWhere('ms.widthDecimal <= :upperIdentifier')
->andWhere('ms.widthDecimal >= :lowerIdentifier')
->setParameter('materialId', $criteria['materialId'])
->setParameter('gaugeId', $criteria['gaugeId'])
->setParameter('upperIdentifier', $criteria['rangeUpper'])
->setParameter('lowerIdentifier', $criteria['rangeLower'])
;
}
}
$query->orderBy('ms.widthDecimal', 'DESC');
return $query->getQuery()->getResult();
}
My current controller looks like
public function selectStripWidthAction (Request $request)
{
$em = $this->getDoctrine()->getManager();
$materialId = $request->get('materialId');
$gaugeId = $request->get('gaugeId');
$materialStocks = $em->getRepository('UniflyteBundle:MaterialStock')->findAllByParams($request);
return $this->render('materialstock/dialog/select.html.twig', [
'MaterialStocks' => $materialStocks,
]);
}
In the Repository I have the query setup to accept and query by the Range. How do I pass the request object and retrieve the result set from the Repository? FindAllByParams call in the controller is not working.
Undefined method 'findAllByParams'. The method name must start with either findBy or findOneBy!
Thanks in advance for your time and effort.
Check that your MaterialStock have annotation for repository.
<?php
namespace UniflyteBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* MaterialStock
*
* #ORM\Table(name="material_stock")
* #ORM\Entity(repositoryClass="UniflyteBundle\Repository\MaterialStockRepository")
*/
class MaterialStock{
// [...]
}

Symfony 3 : how to reordering an array collection with route action?

I have a Product Entity. Each product can have 0 or N pictures.
I have a ProductPhoto Entity which has a order property (0 = first).
On a page, I list all the pictures of my current product. I would like to manage pictures order with 2 up/down arrows.
When the user clicks on an arrow, it moves up/down the picture compared to the others.
So, on each arrow, there is a link that corresponds to a route action in my ProductController.
It's not very complicated to update only the order of the picture that moved, but I don't know how to update the order of other pictures in the ArrayCollection...
/**
* Manage picture order
*
* #Route("/products/{id}/photos/{idphoto}/move-{direction}", name="prod_move_photo")
*/
public function movePhotoAction($id, $idphoto, $direction, Request $request) {
$em = $this->getDoctrine()->getManager();
$photo = $em->getRepository('AppBundle:ProductPhoto')->find($idphoto);
if ($direction == 'up') {
$order = $photo->getOrder() - 1;
if ($order >= 0)
$photo->setOrder($order);
else
$photo->setOrder(0);
} elseif ($direction == 'down') {
$order = $photo->getOrder() + 1;
$photo->setOrder($order);
} else {
throw $this->createNotFoundException("The type of ordering '" . $direction . "' doesn't exist.");
}
$em->flush();
// redirection
return $this->redirectToRoute('prod_photos', array('id' => $id));
}
Maybe using PHP uksort() ?
It looks like you want to update order fields in two ProductPhotos moved by each other, right? So please try this:
/**
* Manage picture order
*
* #Route("/products/{id}/photos/{idphoto}/move-{direction}", name="prod_move_photo")
*/
public function movePhotoAction($id, $idphoto, $direction, Request $request) {
$em = $this->getDoctrine()->getManager();
$photo = $em->getRepository('AppBundle:ProductPhoto')->find($idphoto);
$order = $photo->getOrder();
switch($direction) {
case 'up':
$newOrder = ($order >= 1) ? ($order - 1) : (int) 0;
break;
case 'down':
$newOrder = $order + 1;
break;
default:
throw $this->createNotFoundException("The type of ordering '" . $direction . "' doesn't exist.");
}
$anotherPhoto = $em->getRepository('AppBundle:ProductPhoto')->findOneByOrder($newOrder);
$photo->setOrder($newOrder);
$anotherPhoto->setOrder($order);
$em->flush();
// redirection
return $this->redirectToRoute('prod_photos', array('id' => $id));
}
The solution of #Snegirekk works very well (and I use it), but here is the solution I found, if it can help...
/**
* Manage picture order
*
* #Route("/products/{id}/photos/{idphoto}/move-{direction}", name="prod_move_photo")
*/
public function movePhotoAction($id, $idphoto, $direction, Request $request) {
$em = $this->getDoctrine()->getManager();
$photo = $em->getRepository('AppBundle:ProductPhoto')->find($idphoto);
// Current order of the photo
$currentPos = $photo->getOrder();
// Determine new order
if ($direction == 'up') {
$newPos = ($currentPos > 0) ? $currentPos - 1 : 0;
} elseif ($direction == 'down') {
$newPos = $currentPos + 1;
} else {
throw $this->createNotFoundException("The type of ordering '" . $direction . "' doesn't exist.");
}
$product = $em->getRepository('AppBundle:Product')->find($id);
// Get product photos with actual order (moveElement() needs an array)
$photos = $product->getPhotos()->toArray();
// Reorder photos in ArrayCollection
$this->moveElement($photos, $currentPos, $newPos);
// Reorder photos in database (with keys of formatted ArrayCollection)
foreach ($photos as $order => $p) {
$p->setOrder($order);
}
$em->flush();
// redirection
return $this->redirectToRoute('prod_photos', array('id' => $id));
}
/**
* Move an array element to a new index
*
* #param array $array Array of elements to sort
* #param integer $currentPos Current position of the element to move
* #param integer $newPos New position of the element to move
* #return void
*/
public function moveElement(&$array, $currentPos, $newPos) {
$out = array_splice($array, $currentPos, 1);
array_splice($array, $newPos, 0, $out);
}

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.

symfony2 twig render, exception thrown

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();

Resources