Doctrine - conditional andWhere in query - php

I want to bind a condition in my function. I have a function MarketersGet which give me marketers name . Here is my code :
public function MarketersGet(string $marketerId = ''):array
{
$marketerId = (int)$marketerId;
$userRoles = config('constantTypes.blah');
$marketerRole = $userRoles['MARKETER'];
$userRepository = App::make( DoctrineUserRepo::class );
$result = $userRepository
->selectFrom(' model ')
->where(' model.rolesRole = '.$marketerRole)
->getQuery()
->getResult();
$marketers = [];
foreach ($result as $user) {
$marketers[] = [
'name' => $user->getUserName(),
'id' => $user->getId()
];
}
return $marketers;
}
I want to conditional on $marketerId, if it has value I added
->andWhere(' model.id = '.$marketerId)
I tried like this :
$result = $userRepository
->selectFrom(' model ')
->where(' model.rolesRole = '.$marketerRole);
if ($marketerId != '')
$result->andWhere(' model.id = '.$marketerId);
$result->getQuery()
->getResult();
Above result is :
[]
No Properties
Actually if I put andWhere in default query like this :
$result = $userRepository
->selectFrom(' model ')
->where(' model.rolesRole = '.$marketerRole)
->andWhere(' model.id = '.$marketerId)
->getQuery()
->getResult();
Real result would be like this :
{name: "blah blah", id: 28}
Surely my conditional query is false , Any suggestion to resolve it?

No way to tell if this might make any difference but you might try it:
$result = $userRepository
->selectFrom(' model ')
->where(' model.rolesRole = '. $marketerRole);
if( isset($marketerId) && $marketerId){
$result->where(' model.id = '.$marketerId);
}
$result->getQuery()
->getResult();

You can use this approach. If marketedId is empty string - andWhere has no effect. It always passing. But if it has value then model.id condition is checked.
$result = $userRepository
->selectFrom(' model ')
->where(' model.rolesRole = '.$marketerRole)
->andWhere(':marketerId = "''" OR model.id = :marketerId')
->setParameter('marketerId', $marketerId)
->getQuery()
->getResult();

Related

Sympfony Request (AndWhere, OrWhere) with conditions

I have 2 DQL queries
I want the user (with a select form) to be able to select:
1 filter at a time. Either party or city
or
several filters at the same time: party + city ... then others afterwards.
In summary :
In my database there are Party and City. With a form of select. The user must be able to choose the filters he wants. If he chose a particular Party without specifying the city, this will display all the Party in all the City. He can also choose a city, in which case he will have all the party of the chosen city. or 3rd case, he chose an Party + a City.
When one works the other is not.
I think I have a problem with my conditions and operators.
I read that using the orWhere () was bad practice.
Thanking you in advance.
public function searchByParty($party, $city)
{
$query = $this->createQueryBuilder('s');
$query = $query
->select( 'party', 'city', 's')
->join ('s.party', 'party ')
->join ('s.city', 'city');
if (!empty($party) === !empty($city)) {
$query = $query
->andWhere('party .id = :sport')
->andWhere('city.id = :city')
->setParameter('party ', $party )
->setParameter('city', $city);
}
if (!empty($party) && !empty($city)) {
$query = $query
->orWhere('party.id = :party')
->orWhere('city.id = :city')
->setParameter('party', $party )
->setParameter('city', $city);
}
return $query->getQuery()->getResult();
You have a logical issue. Your first if checks whether the existence of $party and $city is equivalent, which is true if and only if both exists or both does not exist. It does not make sense to check for their value if they both do not exist. The second if checks whether neither is defined. In that case it does not make sense to check the value against them. Fix:
public function searchByParty($party, $city) {
$query = $this->createQueryBuilder('s');
$query = $query
->select( 'party', 'city', 's')
->join ('s.party', 'party ')
->join ('s.city', 'city');
if (!empty($party)) {
$query = $query
->andWhere('party .id = :sport')
->setParameter('party ', $party )
}
if (!empty($city)) {
$query = $query
->andWhere('city.id = :city')
->setParameter('city', $city);
}
return $query->getQuery()->getResult();
}
EDIT: if you want to check whether any of them matches, then use orWhere:
public function searchByParty($party, $city) {
$query = $this->createQueryBuilder('s');
$query = $query
->select( 'party', 'city', 's')
->join ('s.party', 'party ')
->join ('s.city', 'city');
if (!empty($party)) {
$query = $query
->orWhere('party .id = :sport')
->setParameter('party ', $party )
}
if (!empty($city)) {
$query = $query
->orWhere('city.id = :city')
->setParameter('city', $city);
}
return $query->getQuery()->getResult();
}
Solution :
public function searchBySession($party, $city)
{
$query = $this->createQueryBuilder('s');
$query = $query
->select( 's');
if($party){
$query = $query
->join ('s.party', 'party')
->addSelect('party')
->andWhere('party.id = :party')
->setParameter('party', $party)
;
}
if($city){
$query = $query
->join ('s.city', 'city')
->addSelect('city')
->andWhere('city.id = :city')
->setParameter('city', $city)
;
}
return $query->getQuery()->getResult();
}
Thanks you

How to filter products in e-commerce shop by many inputs when some values can be empty

enter image description here
I have several inputs in order to filter products in the online shop. My question is, how can I filter products if some inputs are left without being filled/chosen. How should I query?
public function find()
{
$categories = Category::all();
if (isset($_GET['submit'])) {
if (!empty($_GET['brand'])) {
$selectedBrand = $_GET['brand'];
echo 'You have chosen: ' . $selectedBrand;
} else {
echo 'Please select the value.';
}
$date = Request::get('date');
$name = Request::get('name');
$selected = $_GET['type'];
$data = DB::table('product')->where('product.type', $_GET['type'])
->where('product.name', $name)
->join('shop', 'product.id', '=', 'shop.product_id')
->where('shop.releasedate', $date)
->get();
return view('pages/catalog')->with(['product' => $data, 'categories' => $categories]);
}
}
You can first check if your fields are filled and continue to query your model with when method
Logic
$date = null;
if($request->filled('date)){
$date = $request->date;
}
// your other values can go here like above
$data = DB::table('product')->where('product.type', $_GET['type'])
->where('product.name', $name)
->join('shop', 'product.id', '=', 'shop.product_id')
->when($date, function ($query, $transmission) {
// this query runs only if $date is `true` (has a value and not empty)
return return $query->where('shop.releasedate','=', $date);
->orderBy('shop.created_at','desc);
}, function ($query) {
// something you want to return if the $date is `false` (empty)
})
->get();

Laravel Eloquent where and order conditions only if needed

Please look at following code. This code I have written with Codeigniter. What I need to highlight it where condition and order conditions works only if those post requests are set. Otherwise it i just select * from student.
Codeigniter Code
$this->db->select('*');
$this->db->from('student');
if($this->input->post('first_name') != NULL){
$first_name = $this->input->post('first_name');
$this->db->where('first_name', $first_name);
}
if($this->input->post('last_name') != NULL){
$last_name= $this->input->post('last_name');
$this->db->where('last_name', $last_name);
}
if($this->input->post('order_by') != NULL){
$order_by= $this->input->post('order_by');
$this->db->order_by($order_by);
}
$query = $this->db->get();
Laravel Code
I am going do the same thing with laravel.
$first_name = $request->input('first_name');
$last_name = $request->input('last_name');
$order_by = $request->input('$order_by');
$students = Student::orderBy($order_by)
->where('first_name',$first_name)
->where('last_name',$last_name);
->paginate(10);
I able to run above code. The code works when there all post requests.
But if there is no first_name post request I need to remove ->where('first_name',$first_name).
If there i no order_by post request, I need to remove orderBy($order_by).
How to do it with above Laravel code.
you can use like,
$students = Student::latest();
if (isset($request->input('order_by'))) {
$students->orderBy($order_by)
}
if (isset($request->input('first_name'))) {
$students->where('first_name',$first_name);
}
if (isset($request->input('last_name'))) {
$students->where('last_name',$last_name);
}
$students->paginate(10);
An approach would be to check if the name is set and then add it to the query builder like so:
$first_name = $request->input('first_name');
...
$students = Student::orderBy($order_by)
if ($first_name) {
$students->where('first_name',$first_name)
}
$students->paginate(10);
However you can clean that up! Since Laravel 5.2.27 you can do as follows:
$students = Student::orderBy($order_by)
->when($request->input('first_name'), function($query) use ($request){
return $query->where('first_name', $request->input('first_name'));
})
->paginate(10);
To make that even more readable you can use a custom macro for if-statements:
$students = Student::orderBy($order_by)
->if($request->input('first_name'), 'first_name', '=', $request->input('first_name'))
->paginate(10);
And the macro:
use Illuminate\Database\Query\Builder;
Builder::macro('if', function ($condition, $column, $operator, $value) {
if ($condition) {
return $this->where($column, $operator, $value);
}
return $this;
});
Source: https://themsaid.com/laravel-query-conditions-20160425
I hope this helps!
You can do it like,
$first_name = $request->input('first_name');
$last_name = $request->input('last_name');
$order_by = $request->input('order_by');
$query = DB::table('student');
if($request->first_name){
$query->where('first_name',$first_name)
}
if($request->last_name){
$query->where('last_name',$last_name);
}
if($request->order_by){
$query->orderBy($order_by);
}
$students = $query->paginate(10);
Hope you understand.
Same approach:
$first_name = $request->input('first_name');
$last_name = $request->input('last_name');
$order_by = $request->input('$order_by');
$query = Student::orderBy($order_by);
if ($first_name) {
$query->where('first_name',$first_name);
}
if ($last_name) {
$query->where('last_name',$last_name);
}
$students = $query->paginate(10);
return $students;
$query = Student::where('last_name',$last_name);
if ($request->has('first_name')) {
$query->where('first_name',$first_name);
}
if ($request->has('order_by')) {
$query->orderBy($order_by);
}
$students = $query->paginate(10);

Doctrine error select in select subquery

That's my problem:
I'm trying to make a sub select inside a select with doctrine but already told me that i have bounded too few parameters.
That's my code:
//eseguo un group by per capire quali diciture mostrare nel select
$repoMappatura = $this->getDoctrine()->getRepository('AppBundle:CombinazioneAlberoMappaCategorieArticoli');
$qb = $repoMappatura->createQueryBuilder('combinazioneAlberoMappaCategorieArticoli')
->leftJoin('combinazioneAlberoMappaCategorieArticoli.albero', 'albero')
->select('combinazioneAlberoMappaCategorieArticoli.valore')
->where('combinazioneAlberoMappaCategorieArticoli.albero = :albe')
->setParameter('albe', $alberoFiglio);
$count = 894;
/** #var $vincolo VincoliControlloAlberiFigliConfiguratore[]*/
foreach ($alberoFiglio->getVincoli() as $vincolo)
{
if (key_exists($vincolo->getAlberoVincolo()->getId(), $arrayChiaviVincoli)) {
$log->info('Esistente in array! Valore: ' . $arrayChiaviVincoli[$vincolo->getAlberoVincolo()->getId()]);
$qb2 = $repoMappatura->createQueryBuilder('qb2Mappa');
$qb = $qb->andWhere(
$qb->expr()->in('combinazioneAlberoMappaCategorieArticoli.id',
$qb2->select('qb2Mappa.id')
->where('qb2Mappa.valore = :val' . $count)
->andWhere('qb2Mappa.albero = :alb')
->setParameters(['val' . $count => $arrayChiaviVincoli[$vincolo->getAlberoVincolo()->getId()], 'alb' . $count => $alberoFiglio])
->getDQL()
)
);
$count++;
}
}
$qb = $qb->groupBy('combinazioneAlberoMappaCategorieArticoli.valore')
->getQuery()->getArrayResult();
That is the returned error by symfony:
Too few parameters: the query defines 3 parameters but you only bound 1
I have also tried to use the
->setParameters(....)
to $qb and not to $qb2 but the result is the same
Too few parameters: the query defines 3 parameters but you only bound 2
I have solved my problem with this code:
$repoMappatura = $this->getDoctrine()->getRepository('AppBundle:CombinazioneAlberoMappaCategorieArticoli');
$qb = $repoMappatura->createQueryBuilder('combinazioneAlberoMappaCategorieArticoli')
->leftJoin('combinazioneAlberoMappaCategorieArticoli.albero', 'albero')
->leftJoin('combinazioneAlberoMappaCategorieArticoli.mappaCategorieArticoli', 'mappaCategorieArticoli')
->select('combinazioneAlberoMappaCategorieArticoli.valore')
->where('combinazioneAlberoMappaCategorieArticoli.albero = ?1')
->setParameter(1, $alberoFiglio);
$count = 2;
/** #var $vincolo VincoliControlloAlberiFigliConfiguratore*/
foreach ($alberoFiglio->getVincoli() as $vincolo)
{
if (key_exists($vincolo->getAlberoVincolo()->getId(), $arrayChiaviVincoli)) {
$log->info('Esistente in array! Valore: ' . $arrayChiaviVincoli[$vincolo->getAlberoVincolo()->getId()]);
$qb2 = $this->getDoctrine()->getRepository('AppBundle:CombinazioneAlberoMappaCategorieArticoli')->createQueryBuilder('qb2Mappa'.$count)
->leftJoin('qb2Mappa'.$count.'.albero', 'alber'.$count)
->leftJoin('qb2Mappa'.$count.'.mappaCategorieArticoli', 'mpc'.$count)
->select('mpc'.$count.'.id')
->where('qb2Mappa'.$count.'.valore = ?' . $count)
->andWhere('alber'.$count.'.id = ?' . ($count + 1));
$qb = $qb->andWhere(
$qb->expr()->in('mappaCategorieArticoli.id',$qb2->getDQL())
)->setParameter($count, $arrayChiaviVincoli[$vincolo->getAlberoVincolo()->getId()])
->setParameter($count + 1, $vincolo->getAlberoVincolo()->getId());
}
$count = $count + 2;
}
$log->info($qb->getQuery()->getSQL());
$log->info(count($qb->getParameters()));
$qb = $qb->groupBy('combinazioneAlberoMappaCategorieArticoli.valore')
->getQuery()->getArrayResult();
Added count parameter to make each for loop different and add manually parameters with ? . $count

Doctrine DQL conditional query with Joins

I'm trying to build a dynamic query with Doctrine's query builder. I have optional parameters. How would I add this conditionally to the statement?I also have associations (eg, Service has many-to-one relation to Category)
$qb = $this->createQueryBuilder('service');
$qb->join('service.category', 'category');
$conditions = array();
if ($categoryId != null) {
$category = $this->getEntityManager()
->getRepository('AppBundle:Category')->find($categoryId);
if($category == null){
throw new ApiException('category not found');
}
$conditions[] = $qb->expr()->like('category.path', $category->getPath().'%');
}
if ($userId != null) {
$user = $this->getEntityManager()->getRepository('AppBundle:User')->find($userId);
if($user == null){
throw new ApiException('user not found');
}
$conditions[] = $qb->expr()->eq('service.user', $userId);
}
if ($rating != null) {
$conditions[] = $qb->expr()->gte('service.rating', $rating);
}
$conditions = call_user_func_array(array($qb->expr(), 'andX'), $conditions);
$qb->where($conditions);
$qb->addOrderBy('service.created', 'DESC');
return $qb;
}
When I try to send query
http://127.0.0.1:8000/api/services?limit=10&categoryId=45
I get following error:
Error: Expected StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression, got "45" (500 Internal Server Error)
Try with the Literal expression of the given argument. So try this:
$conditions[] = $qb->expr()->gte('service.rating', $this->expr()->literal($rating));
Instead of this:
$conditions[] = $qb->expr()->gte('service.rating', $rating);
Hope this help

Categories