Doctrine QueryBuilder - CASE WHEN - php

I have a question about case when in doctrine.
The problem with this is when uim.isProfileImage is 1 for a user, that returns that row and every other row in user_image table for that user.
What I want is, if there is a profile image (isProfileImage is 1 in user_image table, there can be only one row with that value for same user) give me only that row, and if there isn't something like that give me null for that.
public function searchUsersByIds(array $ids)
{
$qb = $this->createQueryBuilder('user');
$qb->select('user.id', 'user.username');
$qb->addSelect('(CASE WHEN uim.isProfileImage = :isProfileImage THEŠ uim.imageFileName ELSE :null END) AS imageFileName');
$qb->leftJoin('user.userImages','uim');
$qb->add('where', $qb->expr()->in('user.id', ':ids'));
$qb->setParameter('ids', $ids);
$qb->setParameter('isProfileImage', 1);
$qb->setParameter('null', null);
return $qb->getQuery()->getResult();
}
So it should look something like this:
With profile image:
userId => 1,
username => 'Mark',
imageFileName => 'someFileName'
And without profile image:
userId => 1,
username => 'Mark',
imageFileName => null
Also since there is an in expr, it should work with multiple ids that pass to this function.
Thanks in advance.

Try this:
public function searchUsersByIds(array $ids)
{
$qb = $this->createQueryBuilder('user');
$qb->select('user.id', 'user.username');
$qb->addSelect('uim.imageFileName AS imageFileName');
$qb->leftJoin('user.userImages','uim', 'with', 'uim.isProfileImage = :isProfileImage');
$qb->add('where', $qb->expr()->in('user.id', ':ids'));
$qb->setParameter('ids', $ids);
$qb->setParameter('isProfileImage', 1);
$qb->setParameter('null', null);
return $qb->getQuery()->getResult();
}

Related

laravel query update with multiple condition

I have column named flag and I want to update it if value is 1 to null and if value is null to 1 so far is easy to update this column but issue comes where I send multiple data to controller and not only one.
code
public function flagmultiplemessage(Request $request){
$ids = $request->input('ids');
DB::table('messages')->whereIn('id', $ids)
->whereNotNull('messages.flag')->update(['flag' => null])
->whereNull('messages.flag')->update(['flag' => '1']);
}
with function above i get:
message Call to a member function whereNull() on integer
dd
code above is something like this:
ids = [11, 12, 3]
database = [
11->flag = 1,
12->flag = null,
3->flag = 1,
]
the result of code above most change my database like:
database = [
11->flag = null,
12->flag = 1,
3->flag = null,
]
any idea why i get error?
it occurred because you called whereNull method on update method.
You should run 3 separate query like this.
public function flagmultiplemessage(Request $request){
$ids = $request->input('ids');
DB::transaction(function () use ($ids) {
DB::table('messages')->whereIn('id', $ids)
->whereNotNull('messages.flag')->update(['flag' => 0]);
DB::table('messages')->whereIn('id', $ids)
->whereNull('messages.flag')->update(['flag' => 1]);
DB::table('messages')->whereIn('id', $ids)
->where('messages.flag', 0)->update(['flag' => null]);
});
}
but for better performance I suggest you use boolean for flag column and use this simple query
DB::table('messages')->whereIn('id', $ids)->update(['flag' => DB::raw('!flag')]);
The main reason for the error is that the update() method is not chainable
Alternatively, You can do the update in one query by using the mysql Case statement.
public function flagmultiplemessage(Request $request) {
$ids = $request->input('ids');
DB::table('messages')->whereIn('id', $ids)
->update(['flag' => DB::raw('case when flag is null then 1 else null end') ]);
}
You can do this
DB::table('messages')->whereIn('id', $ids)->where(function ($query) {
$query->whereNotNull('messages.flag')->update(['flag' => null])
->orWhereNull('messages.flag')->update(['flag' => '1']);
})

Query in Yi2 and checking a relationship in another table

I am trying to get data in a Yii2 table call Post. This table has an attribute call owner and I want to check whether the value of owner is equal to a particular Value I pass call it userId or the value of owner is equal to the following attribute of the Followship table where the value of the follower attribute of the Followship Table is equal to the the value I pass call it userId.
In implementing the above logically and bit by bit, I have written the following code;
$allpost = Post::find()->all();
$relevantpost = [];
foreach ($allpost as $post) {
if($post->owner == $userId){
$relevantpost[] = $post;
}
else{
$follower = Followship::findOne(['follower'=>$userId, 'following'=>$post->owner]);
if($follower){
$relevantpost[] = $post;
}
}
}
return $relevantpost;
This code works well but I want to write an active query for this such as ;
$allpost = Post::find()
->where(['owner'=>$userId])
->orWhere(['is NOT', $follower = Followship::findOne(['follower'=>$userId]) and 'owner' => $follower->following, NULL])
->all();
or in the worse case,
$allpost = \Yii::$app->db
->createCommand(
"SELECT postId, location, details, created_at FROM Post
WHERE owner = " . $userId. "OR
owner = '0' OR
owner = following IN (
SELECT following FROM Followship WHERE follower = ". $userId . " AND
)
ORDER BY dateCreated DESC"
)
->queryAll();
I keep getting errors with the above queries. I am missing out a fundamental of the Yii2 query builders.
Please any help on this will be greatly appreciated.
First you could make a relation (which connects Post and Followers by post owner) inside your Post class
class Post extends ActiveRecord {
public function getFollowersDataset() {
return $this->hasMany(Followers::className(), ['following' => 'owner']);
}
...
}
And then you can just use it in your queries
Post::find()
->joinWith('followersDataset')
->where(['or',
['owner' => $user_id],
['follower' => $user_id]])
->all()
The condition accept three parameters
[the_condition, the_attribute, the_value]
In case of AND and OR the thing change
[the_condition, first_condition, second_condition]
With the second tried you can make something like that
$allpost = Post::find()
->where(['owner'=>$userId])
->orWhere([
'AND',
['is NOT', $follower, Followship::findOne(['follower'=>$userId]),
['owner', $follower->following, NULL]
])
->all();
You can check in debug bar the querys that you're making, or another way, its to make a mistake in a field, for example if in your where condition you put ->where(['owners'=>$userId]), that trhow an error with the query that you made, so you can see what query you did

how to update Boolean type column - Laravel 5.5

I have a boolean column in my database for image thumbnail. One selected row will be thumbnail (and will have a value 1) and other rows will be 0. How do i update the selected row value into 1 and others 0.
when i run this update function, it will update the row every time against the ID (off course).
public function update(Request $request, $id)
{
$id = (int) $id;
$image = HotelGallery::where('id', $id)
->update(['is_thumbnail' => '1']);
return response()->json(['success' => 'Done']);
}
ID 2 and 3 have value 1, how do i update this is_thumbnail row against the ID which is 3, will be 1 and others is_thumbnail rows should be 0 in one query?
I understand you want in a hotel_id have only is_thumbnail=1:
public function update(Request $request, $id)
{
$id = (int) $id;
$hotelGallery = HotelGallery::where('id', $id)
->pluck('hotel_id')->toArray();
$hotel_id = array_get($hotelGallery, '0', 0);
// Set is_thumbnail = 0 for all image of hotel_id
HotelGallery::where('hotel_id', $hotel_id)
->update(['is_thumbnail' => 0]);
$image = HotelGallery::where('id', $id)->update(['is_thumbnail' => 1]);
return response()->json(['success' => 'Done']);
}
You can use multi queries in PDO or Mysqli.
PDO example :
$db = new PDO("mysql:host=localhost;dbname=test", 'root', '');
// works regardless of statements emulation
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
$thumbnail_id = 2;
$sql = 'UPDATE tab SET tab.is_thumbnail = false;' . "\n" .
'UPDATE tab SET tab.is_thumbnail = true WHERE tab.id = ?';
try {
$stmt = $db->prepare($sql);
$stmt->execute([$thumbnail_id]);
}
catch (PDOException $e)
{
echo $e->getMessage();
die();
}
//To Update row two as shown in above image
query="UPDATE $data_base_name.$data_base_table SET `is_thumbnail`=0 WHERE `id`=2";
result=mysqli_query($conn,(query));
//To Update row two as shown in above image (being more specific)
query="UPDATE $data_base_name.$data_base_table SET `is_thumbnail`=false WHERE `id`=2";
result=mysqli_query($conn,(query));
The above code will change row two is_thumbail to 0 for value as 1 change 'false'or'0' in the above code to '1' or 'true'.
//Update to improved question (updating all rows)
query="
UPDATE $data_base_name.$data_base_table SET `is_thumbnail`=true WHERE `id`=2;
UPDATE $data_base_name.$data_base_table SET `is_thumbnail`=false WHERE `id`!=2;";
result=mysqli_multi_query($conn,(query));
while (mysqli_next_result($conn)){;}//this is to free result set for multi query
The above query will set row two to 'true' or '1' and every other row to 'false' or '0'.
If your new to php please read about SQL injections!!! see also https://secure.php.net/manual/en/mysqli.multi-query.php
//Update to improved question (eloquent format)
Table::where('id', '=',2 )->update(['is_thumbnail' => 'true']);
Table::where('id', '!=',2 )->update(['is_thumbnail' => 'false']);
This not the best way to do it in laravel but this should work for now.
Best Laravel way is to integrate this function in model:
class HotelGallery extends Model
{
protected static function boot ()
{
parent::boot();
self::saving(function($model) {
if($model->attributes['is_thumbnail'] == 1)
{
(new self)->where('hotel_id', $model->attributes['hotel_id'])->where('id', '<>', $model->attributes['id'] ?? 0)->update(['is_thumbnail' => 0]);
}
});
}
}

Laravel query and array

please help me. I want to ask:
Let say I have 2 tables: user_master and people.
Now I am currently build an application in PHP with Laravel 5.1 framework that select the data from user_master table (with some constraint in where clause) and insert into people table.
The code is :
public function handle() {
$results = DB::select(DB::raw("SELECT * FROM user_master WHERE div_id = 1"));
foreach ($results as $res) {
//saving to array
//insert query to table people here.
}
}
My questions are:
How to save the result of select query to array, and
Insert that array into people table using RAW query (INSERT INTO people VALUES (...)).
P.S.: My query is RAW query, not using Eloquent. And please provide answer without Eloquent.
Thank you so much for any answer.
I have done the same scenario like this
$users=DB::table('Users')->where('created_at' ,'>=','2016-09-06')->get();
foreach ($users as $user){
DB::table('users_report')->insert(
array(
'id' => $user->id,
'username' => $user->username,
'lastname' => $user->lastname,
'email' => $user->email,
'created_at' => $user->created_at,
'updated_at' => $user->updated_at,
)
);
}
change your like according to your logic , its works 100% perfectly..
I think that is right
$results = DB::table('user_master')->where('div_id', 1)->get();
if your table and master have the same strucure, you just set the primary key in the below code. If they are not in the same structure, you have to ajust the results to the structure of the people bfore you insert to peopel table.
hope it will helps.
function delete_col(&$array, $offset) {
return array_walk($array, function (&$v) use ($offset) {
unset($v[$offset]);
});
}
public function handle() {
$results = DB::table('user_master')->where('div_id', 1)->get();
delete_col($results, $premiarykeyOfuser_master);
DB::table('people')->insert($results);
}

Checking if the object has values in php/laravel

I almost finished my website, just one more feature to finish and this is so the user can like just once a post/theme/discussion point(whatever).
I have the table new_theme_user:
1 id
2 id_user(integer)
3 id_theme(integer)
4 upVote(tinyint)
So this is the controller:
class Vote extends Controller {
public function VoteTheme($id, $vote){
$Vote = DB::table('New_Theme_User')->where([
['id_theme', '=', $id],
['id_user', '=', Auth::id()],
])->get(); (1!!!)
if (!isset($vote)) { (2!!!)
if ($vote === 'plus')
DB::table('New_Theme_User')->insert([
['id_theme' => $id, 'id_user' => Auth::id(), 'upVote' => 1],
]);
else
DB::table('New_Theme_User')->insert([
['id_theme' => $id, 'id_user' => Auth::id(), 'upVote' => 0],
]);
if ($vote === 'plus') {
DB::table('New_Themes')
->where('id', $id)
->increment('upVotes', 1);
} else {
DB::table('New_Themes')
->where('id', $id)
->increment('downVotes', 1);
}
}
$Themes = NewTheme::paginate(5);
return redirect()->route('welcome', ['Themes'=>$Themes]);
}
};
1!!! - Is the select query which creates an object(in order to find in database if someone has already voted before the theme/post which he wants to vote again.
2!!! - Is the if statement, if the object doesn't have the values - this means the user can vote once so it populates the DB with information.
The problem: I can't figure how to work around the (2!!!), I tried isset, empty, whatever else I could find on internet, it doesn't work, even if the user voted once more the if goes through and it seems I can't find a solution. Every given help, I will greatly appreciate. Thank you!
NewThemeUser model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class NewThemeUser extends Model
{
protected $table = 'new_theme_user';
}
Now in controller you can do like this
App\NewThemeUser::firstOrCreate(['id_theme' => $id, 'id_user' => Auth::id()])->increment($upVotes ? 'upVotes' : 'downVotes');//This will fetch the first record if there any exists for the user then increment if $upVotes then the column to increment is upVotes else upVotes

Categories