How to define mulitple orWhere queries with Doctrines Query Builder - php

I want to create a query using Doctrines QueryBuilder.
The User can choose the database fields which shall be searched by checking or unchecking checkboxes in an HTML form. That is why $_POST contains 'filters' and 'like'.
$_POST['filters'] looks like this:
array(2) { [0]=> string(4) "rack" [1]=> string(5) "shelf" }
I'm trying to get the following query work to result in
SELECT * FROM `inventories` WHERE (`rack` OR `shelf` LIKE '%01%') AND `checkedOutAt` IS NULL ORDER BY `lastChangedAt`
I'm using Doctrine in Version 2.5.5 and PHP in Version 7. My controller looks like this:
public function searchAction()
{
$filters = array();
$em = $this->getEntityManager();
$vendors = $em->getRepository('Entities\Vendor')->findAll();
if ($_POST)
{
$filters = $_POST['filters'];
$like = trim($_POST['like']);
$inventories = $em
->getRepository('Entities\Inventory')
->findInventoriesBySearch($like, $filters)
;
$this->addContext('like', $like);
}
else
{
$inventories = $em
->getRepository('Entities\Inventory')
->findInventories()
;
}
$count = count($inventories);
$this->addContext('filters', $filters);
$this->addContext('vendors', $vendors);
$this->addContext('inventories', $inventories);
$this->addContext('count', $count);
$this->setTemplate('inventoryAction');
}
And the according repository (the "findInventories()" repository function works fine):
public function findInventoriesBySearch($like, $filters)
{
$em = $this->getEntityManager();
$orExpr = $qb->expr()->orX();
foreach ($filters as $filter)
{
$orExpr->add($qb->expr()->like($filter, $like));
}
$qb ->andWhere('i.checkedOutAt is NULL');
$qb->setParameter('like', '%' . $like . '%');
$qb->select('i')->where($orExpr)->addOrderBy('i.lastChangedAt', 'DESC');
return $qb->getQuery()->getResult();
}
When I run the script I receive the following error message:
Fatal error: Uncaught Doctrine\ORM\Query\QueryException: SELECT i
WHERE rack LIKE 01 OR shelf LIKE 01 ORDER BY i.lastChangedAt DESC in
.../vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php:41
Stack trace: #0
.../vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(483):
Doctrine\ORM\Query\QueryException::dqlError('SELECT i WHERE ...') #1
.../vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(971):
Doctrine\ORM\Query\Parser->semanticalError('line 0, col 15 ...',
Array) #2
.../vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(1702):
Doctrine\ORM\Query\Parser->AbstractSchemaName() #3
.../vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(1557):
Doctrine\ORM\Query\Parser->RangeVariableDeclaration() #4
.../vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php(1292):
Doctrine\ORM\Query\Parser->IdentificationVariableDeclaration() in
.../vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php on
line 63

Try check up & change it.
(Just, an advice) Don't work with $_POST/ request type/ access to it/etc. via "your way". Use typehinted Request e.g. :
public function searchAction(Request $request){
if ($request->isMethod('POST')) {
$filters = $request->request->get('filters');
//.....
}else{
}
}
Guess, the problem there is:
//...
foreach ($filters as $filter)
{
$filter = 'i.'.$filter; // <== 'i.rack','i.shelf', so on
$orExpr->add($qb->expr()->like($filter, $like));
}

Related

Retrieving data from database and passing it as instance of entity

I'm trying to pass id from query from one database table to another table to which is related.
But, since they are related I have to pass it as instance of the entity(class) to which is related.
This is error I got:
Argument 1 passed to App\Entity\KeywordRating::setKeywordId() must be an instance of App\Entity\Keywords, integer given, called in C:\xampp\htdocs\ratingAPI\src\Service\KeywordRatingService.php on line 26
This is my code:
public function insertRating($params, ObjectManager $manager, KeywordsRepository $keyRep, ProvidersRepository $provRep)
{
$keywordId = $keyRep->checkKeyword(strtolower($params['keyword']))->getId();
$providerId = $provRep->checkProvider($params['provider'])->getId();
$rating = new KeywordRating();
$rating->setKeywordId(<Keywords instance> $keywordId);
$rating->setProviderId(<Providers instance> $providerId);
if($params['attr'] === 'rocks')
{
$rating->setRocksRating($params['rating']);
$rating->setSucksRating(0);
} else
{
$rating->setRocksRating(0);
$rating->setSucksRating($params['rating']);
}
$rating->setRocksVotes(10);
$rating->setSucksVotes(8);
$rating->setSumVotes(18);
$rating->setScore(2.50);
$manager->persist($rating);
$manager->flush();
}
This is sql query:
public function checkKeyword($keyword)
{
return $this->createQueryBuilder('k')
->where('k.keyword_name = :val')
->setParameter('val', $keyword)
->getQuery()
->getOneOrNullResult();
}
checkProvider() is the same, only different parameters.
How do I do that?
Assuming you have a namespace called Entities where you have all your entities classes, you can try something like this:
$entityManager = $this->getDoctrine()->getManager();
$queryBuilder = $entityManager->createQueryBuilder();
$queryBuilder->select('keyword')
->from('App\Entity\Keywords', 'keyword')
->where($queryBuilder->expr()->eq('keyword.keyword_name', $queryBuilder->expr()->literal($keyword)));
$result = $queryBuilder->getQuery()-> getOneOrNullResult();
return $result;

PHP Fatal Error 'yii\base\ErrorException' with message 'Class 'Model Name' not found

I trying migration my project from yii1 to yii2.
I have some model function I make when I still use Yii1, is among others is generate id uniq function's, like this:
public static function generateID($tableName, $modelName) {
$dateNow = date("Ymd");
$checkLastID = $modelName::findBySql(
"SELECT SUBSTR(MAX(id),-4) AS id FROM $tableName WHERE id LIKE '%$dateNow%'"
)->one();
$lastNumber = (int)substr($checkLastID["id"], 8,4);
if($checkLastID["id"] == '') {
$id = $dateNow.sprintf("%04s", 1);
} else {
$lastNumber = $checkLastID["id"];
$lastNumber++;
if($lastNumber < 10) $id = $dateNow.sprintf("%04s", $lastNumber);
elseif($lastNumber < 100) $id = $dateNow.sprintf("%04s", $lastNumber);
elseif($lastNumber < 1000) $id = $dateNow.sprintf("%04s", $lastNumber);
elseif($lastNumber < 10000) $id = $dateNow.sprintf("%04s", $lastNumber);
else $id = $lastNumber;
}
return $id;
}
and I access the function from controller like this:
$model->id = Helper::generateID('table_name', 'ModelName');
and than, show error when I want create data:
<pre>PHP Fatal Error 'yii\base\ErrorException' with message 'Class 'ModelName' not found'
in C:\xampp\htdocs\kampunginggrispare.com\common\models\Helper.php:61
Stack trace:
#0 [internal function]: yii\base\ErrorHandler->handleFatalError()
#1 {main}</pre>
But, If I change
$checkLastID = $modelName::findBySql("SELECT SUBSTR(MAX(id),-4) AS id FROM $tableName WHERE id LIKE '%$dateNow%'")->one();
to be:
$checkLastID = ModelName::findBySql("SELECT SUBSTR(MAX(id),-4) AS id FROM table_name WHERE id LIKE '%$dateNow%'")->one();
It's work, but doesn't work when I use Parameter like function above
In Yii1, not error, but error in Yii2
Any body can help me ??
Thanks ...
Try to load $ModelName before use it in the Helper class. You can either
...
$dateNow = date("Ymd");
$className = '\common\models\\' . $modelName; // replace this with your model's namespace
$checkLastID = $className::findBySql(
"SELECT SUBSTR(MAX(id),-4) AS id FROM $tableName WHERE id LIKE '%$dateNow%'"
)->one();
....
Or simply put your helper in the same namespace with the $ModelName (less recommended). I still don't understand the purpose of your Helper class.
Yii2 didn't find ModelName class.
Please read more about upgrading: Upgrading from Version 1.1: Namespace and Yii2 autoloaders.

How to put pagination on search result using symfony2?

I am working on a project using symfony2. I already have my search function and it is already working. But what I want is to have pagination on the search results since there are times that there are a lots of data being retrieve. How can I possibly do it?
Here is my code :
public function searchAction (Request $request) {
$request = $this->getRequest();
$data = $request->get('search');
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery (
'SELECT a,b,c FROM SampleBundle:transactDetail a
JOIN a.transact b
JOIN b.transactType c
WHERE b.pNumber LIKE :data
OR b.senderId LIKE :data'
)
->setParameter('data', "%$data%");
$result = $query->getResult();
if ($result == null ) {
return $this->render('SampleBundle:Sample:noresult.html.twig');
}
return $this->render('SampleBundle:Sample:search.html.twig', array('result' => $result));
}
Thanks in advance.
This is an example of your code with Paginator :
public function searchAction(Request $request, $firstResult = 0, $maxResults = 100)
{
$request = $this->getRequest();
$data = $request->get('search');
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT a,b,c FROM SampleBundle:transactDetail a
JOIN a.transact b
JOIN b.transactType c
WHERE b.pNumber LIKE :data
OR b.senderId LIKE :data'
)
->setParameter('data', "%$data%")
->setFirstResult($firstResult)
->setMaxResults($maxResults);
$result = new Paginator($query);
if ($result == null) {
return $this->render('SampleBundle:Sample:noresult.html.twig');
}
return $this->render('SampleBundle:Sample:search.html.twig', array('result' => $result));
}
And if you would like to count the total just count($result);.
Paginator has Countable et IteratorAggregate interfaces.
So you can loop on your result without problem.

Doctrine Query Builder Result: not looping correctly

I'm not sure if it's that I'm not doing correctly but this is giving me an error:
I have 2 Entities: Task and TaskUser. They are connected by a onetoMany.
What I want to do is this:
foreach($tasks as $task){
echo $task->getTitle;
echo $task->getTaskUser()->getFirstName();
}
This is my query in the Task Repository:
public function findTasksByUsers($user = false)
{
if($user){
$qb = $this->_em->createQueryBuilder();
$qb
->select('t', 'tu')
->from('\Entities\Task', 't')
->leftJoin('\Entities\TaskUser', 'tu', \Doctrine\ORM\Query\Expr\Join::WITH, 't.id = tu.task')
->where('tu = :user')
->setParameter('user', $user)
->orderBy('t.createDate', 'DESC');
return $qb->getQuery()->getResult(\Doctrine\ORM\Query::HYDRATE_OBJECT);
}
}
When I do this loop:
$tasks = $this->em->getRepository('\Entities\Task')->findTasksByUsers($user);
foreach($tasks as $task){
echo $task->getTitle();
}
I get the the title of the first task, and then an error like this:
Title of first task
Fatal error: Call to undefined method Entities\TaskUser::getTitle() in D:\sites\db\application\controllers\TasksController.php on line 35
Any idea why this is happening? Thanks!
$qb->select('t', 'tu')
the issue is here as you're selecting both entities.
If you want only Task entity modify your DQL as follows
$qb->select('t')
However, to me, you could only procede that way (in your controller; if you aren't into controller, use DI to access entity manager)
//retrieve all TaskUser object
$em = $this->getDoctrine()->getManager();
$tu_repo = $em->getRepository('YourBundleName:TaskUser');
$tu_array_collection = $tu_repo->findBy(array('user'=>$user));
foreach ($tu_array_collection as $tu) {
$first_name = $tu->getFirstName();
foreach ($tu->getTasks() as $task) {
echo $first_name;
echo $task->getTitle();
}
}
of course you may need to adapt your code with right findBy array, and with correct methods from TaskUser entity

Exception information: Message: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound

I have a code here that, has to search and post back information selected in a table above the add button, the search works but im having a problem with the post back to the table function. These are the lines it shows to have errors.
C:\xampp\htdocs\portal-gep-2\application\models\ServiceProviders.php(68): Zend_Db_Table_Abstract->fetchRow(Object(Zend_Db_Table_Select))
public function getName($id)
{
$select = $this->select();
$select->where('service_provider_id = ?', $id);
$result = $this->fetchRow($select); //this line
return $result['service_provider_name'];
}
#6 C:\xampp\htdocs\portal-gep-2\application\modules\admin\controllers\AjaxController.php(1104): Model_ServiceProviders->getName(NULL)
public function postserviceproviderAction()
{
$form = new Form_IndustrialTable();
$this->view->form = $form;
if(!$form->isValid($_POST))
{
$values=$form->getValues();
}
$sp = $this->getRequest()->getPost('serviceprovider', null);
$mdlserviceprovider = new Model_ServiceProviders();
$serviceprovider = $mdlserviceprovider ->getName($id); //this line
$rtn_array= array( 'sp' => $sp,
'serviceprovider ' => $serviceprovider);
$this->_helper->layout->disableLayout();
$this->_helper->viewRenderer->setNoRender();
echo Zend_Json::encode($rtn_array);
}
You don't put any initial value to $id so it's null which causes error.
You want SQL query to look something like SELECT * FROM service_providers WHERE service_provider_id = 50, but for this you have to provide id which you want to find (50 in this example). You need to add some value to variable $id before using in $select->where('service_provider_id = ?', $id);, but your code you never put any value to variable $id.
If I'm guessing your idea then you need to change line:
$serviceprovider = $mdlserviceprovider ->getName($id);
to:
$serviceprovider = $mdlserviceprovider ->getName($sp);
Also this part of your code probably unnecessary as it does nothing:
$form = new Form_IndustrialTable();
$this->view->form = $form;
if(!$form->isValid($_POST))
{
$values=$form->getValues(); //you never use $values
}

Categories