Laravel multiple where clause checking for null values through a variable - php

I am storing a where clause in a variable
if($condition === 1) {
$whereClause = ['mID' => NULL, 'qid' => $listing->lID, 'deleted' => false];
}
else {
$whereClause= ['mID' => $member->mID, 'qid' => $listing->lID, 'deleted' => false];
}
And I get the collection via
$collection = Model::where($whereClause)
BUT on the first condition, I actually want the mID to be either 0 or NULL, I want to retrieve items where mID can be 0 or NULL, so I want orWhere clause, which I did use as shown below, but this does not work, gives an error of memory exhausted so something went wrong
if($condition === 1) {
$whereClause = ['mID' => NULL, 'qid' => $listing->lID, 'deleted' => false];
$orWhereClause = ['mID' => 0, 'qid' => $listing->lID, 'deleted' => false];
$collection = Model::where($whereClause)->orWhere($orWhereClause)
}
else {
$whereClause= ['mID' => $member->mID, 'qid' => $listing->lID, 'deleted' => false];
$collection = Model::where($whereClause)
}
Any ideas of how I can achieve this sort of where condition

This seems like the easiest method. Chaining where() methods is the same as passing them in as an array.
$collection = Model::where('qid', $listing->lID)->where('deleted', false);
if($condition === 1) {
$collection = $collection->whereIn('mID', [0, NULL]);
}
else {
$collection = $collection->where('mID', $member->mID);
}
(Note that according to the documentation, if you wanted to pass an array to the where() method, you were doing it wrong.)

Miken32 is correct, but the code could be written in a single query instead of adding the where() in an if/else statement:
$collection = Model::where('qid', $listing->lID)->where('deleted', false)
->when($condition === 1, function($q){
$q->whereIn('mID', [0, NULL]);
})->when($condition !== 1, function($q){
$q->where('mID', $member->mID);
});

Except for the missing of ";", i think that you should implement it in this way:
$whereClause = [['mID', NULL], ['qid' , $listing->lID] , ['deleted', false]];
$orWhereClause = [['mID', 0], ['qid' , $listing->lID] , ['deleted', false]];
$collection = Model::where($whereClause)->orWhere($orWhereClause);
and if you need other condition, just push an array in the right array where the first parameter is the field and the second the value, or first parameter is the field, the second the operator and the third the value

Related

Fast query to load specific data column

I have this output format for kits result counting:
$out = array(
'in progress' => 0,
're-testing' => 0,
'rejected' => 0,
'negative' => 0,
'positive' => 0,
'inconclusive' => 0,
'failed' => 0,
'tested' => 0,
'available' => 0,
'total' => 0
);
I implemented a loop to query in the kits and then check for corrispondence in result value, like that:
$kits = Kit::where('customerId', Auth::id())->get();
foreach ($kits as $kit) {
if($kit->result !== '' && isset($out[$kit->result])){
++$out[$kit->result];
++$out['tested'];
}
if($kit->status == 'accepted' && !$kit->result){
++$out['in progress'];
}
++$out['total'];
}
unfortunately this solution is very slow. Do you have any suggestions for how to do that? thanks.
EDIT: Is slow because there are too many items.
First you are querying with a condition customerId, so add an index to customerId field will improve query performance a lot.
Then you don't have to count the total, you can use count().
$out['total'] = Kit::where('customerId', auth()->id())->count();
The part where you count the group of results ++$out[$kit->result]; looks like can be done with groupBy()
$kits = Kit::where('customerId', auth()->id())
->groupBy('result')
->select('result', DB::raw('COUNT(*) as no'))
->get();
Then for each result that you want to count, you can look up with firstWhere().
$out['positive'] = $kits->firstWhere('result', 'positive')->no;
$out['negative'] = $kits->firstWhere('result', 'negative')->no;
...
$out['tested'] is just the sum of all count.
$out['tested'] = $out['positive'] + $out['negative'] +...
And need another query for $out['in progress']
$out['in progress'] = Kit::where('customerId', auth()->id())
->where('status', 'accepted')
->whereNotNull('result')
->where('result', '!=', '')
->count();

Laravel Api - how to put like and dislike

I’m trying to create an API request for like and dislike in my Laravel project:
Route::post('like', ‘Api\ApiController#like’);
The function in the ApiController look like this:
$post = \App\Post::find($request->id);
$social = SocialPost::where([['user_id', '=', ($request->user_id)],['post_id', '=', ($request->id)]])->first();
$unsocial = SocialPost::where([['user_id', '=', ($request->user_id)],['post_id', '=', ($request->id)],['like', '=', 0]])->first();
if ($social) {
if ($unsocial) {
$social->update(['like' => 1]);
return json_encode(array('status' => true,'msg'=>'like'));
}
else {
$social->update(['like' => 0]);
return json_encode(array('status' => true,'msg'=>'dislike'));
}
}
else {
$join = new \App\SocialPost;
$join->user_id = $request->user_id;
$join->post_id = $post->id;
$join->like = 1;
$join->view = 0;
$join->creator = 1;
$join->save();
return json_encode(array('status' => true,'msg'=>'New table'));
}
The problem is that the first If statement works but the second doesn't. If the row already exists he always put '1' for 'like' also if the message that return is 'dislike'.
Here is an example that should work with you.
<?php
// Get the post from the database
$post = \App\Post::find($request->id);
// Find the SocialPost record if it exists,
// if it doesn't create a new one with no likes
$socialPost = SocialPost::firstOrCreate(
['user_id' => $request->user_id, 'post_id' => $post->id],
['user_id' => $request->user_id, 'post_id' => $post->id, 'likes' => 0, 'view' => 0, 'creator' => 1],
);
// Declare an empty variable that will determine if
// the post is being "liked" or "disliked"
$postAction = '';
// Determine if the post has likes or not
if ($socialPost->likes > 0)
{
// The post has at least 1 like
$postAction = 'dislike';
// Decrement the likes by 1
$socialPost->decrement('likes', 1);
}
else
{
// The post has 0 likes
$postAction = 'like';
// Increment the likes by 1
$socialPost->increment('likes', 1);
}
// Determine if this was a new SocialPost record
if ($socialPost->wasRecentlyCreated)
{
// Override the post action as "New table"
$postAction = 'New table';
}
// Return the goods
return json_encode(['status' => true, 'msg' => $postAction]);
Explanation
You can determine if the SocialPost record exists, or create a new one - all in a single line using firstOrCreate referenced in the documentation here. The first array parameter takes in what you are looking for, and the second array paramater takes in what should be created if the first parameter turned up nothing
// Find the SocialPost record if it exists,
// if it doesn't create a new one with no likes
$socialPost = SocialPost::firstOrCreate(
['user_id' => $request->user_id, 'post_id' => $post->id],
['user_id' => $request->user_id, 'post_id' => $post->id, 'likes' => 0, 'view' => 0, 'creator' => 1],
);
Then you can clean up the adding or subtracting likes by using increment or decrement referenced in the documentation here.
// Determine if the post has likes or not
if ($socialPost->likes > 0)
{
// Decrement the likes by 1
$socialPost->decrement('likes', 1);
}
else
{
// Increment the likes by 1
$socialPost->increment('likes', 1);
}

Find all documents in mongodb

I want to display all documents (select *) with sub-documents in PHP.
I know how to query all find() but I have no idea how to do it when I have sub-documents. I don't know if there's something like find() or I need to make loops fo every sub-documents that I'd have.
This would be the code
$mongodatabase->insertOne(
['name' => 'Alex',
'surname' => 'Turner',
'country' => 'England',
'birth' => array(
'day' => 6,
'month' => 'january',
'year' => 1986
),
]);
Something easy, just to learn. When I try a var_dump of day I get Undefined index and NULL.
$client = new MongoDB\client;
$db = $client->database;
$mongodatabase = $db->document;
$document = $mongodatabase->find();
foreach ($document as $doc) {
var_dump($doc->day);
}
However, I'd like to query all.
Use $exists - It helps us in identifying the elements which are not empty
db.collection_name.find({
"birth.day" : {
$exists : true
}
});
If you need to check not null and empty, then we need to use $type together with $exists, $type can be passed with different values and 10 is for null check
db.collection_name.find({
"birth.day" : {
$not : { $type : 10 },
$exists : true
}
});
when u find the exactly data from mongoldb u can use the shelter to limit the field
eg:
db.xxxxx.find(
{'status':'DELIVRD'}
);

Silverstripe ignoring NULL filter in get command

We have a Silverstripe project that uses the following logic to find duplicate records:
if ($queryString) {
$duplicate = SavedSearch::get()->filter(array(
'RentOrBuy' => $rentOrBuy,
'MemberID' => $member->ID,
'QueryString' => $queryString,
))->first();
} else {
$duplicate = SavedSearch::get()->filter(array(
'RentOrBuy' => $rentOrBuy,
'MemberID' => $member->ID,
'QueryString' => NULL,
))->first();
}
However this doesn't return the expected responses. When $queryString is NULL it doesn't return any objects - even when QueryString is set as "NULL" on matching fields in the database.
Any ideas about why this is happening/ what is going on?
It's fixed for 4.0 from the looks
https://github.com/silverstripe/silverstripe-framework/pull/4196/commits/922d02f5356d5904debaf10003477cdd00306192
so for now..
if ($queryString) {
$duplicate = SavedSearch::get()->filter(array(
'RentOrBuy' => $rentOrBuy,
'MemberID' => $member->ID,
'QueryString' => $queryString,
))
->first();
} else {
$duplicate = SavedSearch::get()->filter(array(
'RentOrBuy' => $rentOrBuy,
'MemberID' => $member->ID
))
->where('QueryString IS NULL')
->first();
}
Be careful when using where, since it wont do any sql escaping. Here its fine but always use the filter when passing in user data.

CakePHP model SQL queries conditions parameter

I have a long query like this:
$a=$this->Signin->find('all',
array(
'fields'=> array(
.....
),
'conditions' => array('mytable.user_type ...),
'order' => ....
'limit' => ....
));
user_type column can take values of 0 or 1.
I have a function parameter $type, regarding to this parameter, I need to change my SQL query. Regarding to $type I will query for
"mytable.user_type"=1,
"mytable.user_type"=0,
"mytable.user_type"=1 OR "mytable.user_type=0
I don't want to write same query three times. I want to change only conditions part. Is it possible?
you can define $type as an array and manage the values in $type
Like for multiple values
$type = array(1,0);
'conditions' => array('mytable.user_type'=>$type)
for single value
$type = array(1);
'conditions' => array('mytable.user_type'=>$type)
Hence you just need to manipulate $type as per condition, Hope this work
Try this:
$user_type = ($type == 'something') ? 1 : 0 ;
then, in your conditions:
'conditions' => array('mytable.user_type' => $user_type);
given that user_type can take only two values, your third query ("mytable.user_type"=1 OR "mytable.user_type=0) is unnecessary
EDIT :
if($type == 'conditions_where_usertype_is_necessary') $user_type = ($type == 'something') ? 1 : 0 ;
then, for your conditions:
if( isset($user_type) ) {
$options['conditions']['mytable.user_type'] = $user_type;
}
$options['conditions']['other_conditions'] = ...;
$this->Signin->find('all', $options);

Categories