Laravel Eloquent Query Not Working - php

$demos = Demo::whereIn('store_id', [1,2,4], function($query){
$query->where('status', 1);
})->paginate(10);
I know that this thats not working, But how can I work with this logic..?
[Select * from 'demos' where store_id in 1,2,4 and status = 1 ]

If I understand correctly you need something like this.
$demos = Demo::whereIn('store_id', [1, 2, 4])->where('status', 1)->paginate(10);
Chained "where" Eloquent methods == "AND" database query conditions.

Sometimes, it is better not use ORM`ish approach.
They say, old plain SQL is your best friend. So.
$data = \DB::select(
\DB::raw("SELECT * FROM `demos` WHERE `store_id` IN (:id1, :id2, :id3)"), array( ':id1' => 1, ':id2' => 2, ':id3' => 3 )
);
Or, if you have unknown count of store_id entries, you could:
$ids = array(1, 2, 3, 4, ...); // looks like unknown ammount of entries
$data = \DB::select(
\DB::raw("SELECT * FROM `demos` WHERE `store_id` IN (".rtrim(str_repeat('?,', count($ids)),',').")"), $ids
);

Related

Laravel Eloquent Multiple Where with count

Following is the SQL query that I need to perform on laravel eloquent. SQL returns expected output.
SELECT
orders.id,
orders.`status`,
order_type,
COUNT(order_type) as count
FROM
orders
WHERE
orders.`status` = 0 && order_type = 1
ORDER BY
orders.id DESC
what I have tried on laravel is below
$receved = Order::select('status', 'order_type')->where('status',0);
$relase = $receved->where('order_type', 1)->get();
$bulk = $receved->where('order_type', 2)->get();
$distiribute = $receved->where('order_type', 3)->get();
return response()->json([
'success' => true,
'message' => 'Statement Updated',
'orderStatment' => [
'relaseCount' => count($relase),
'bulkCount' => count($bulk),
'distiributeCount' => count($distiribute)
],
], 200);
I seeking recommendation/suggestion to operate this in a correct way
The output I getting on laravel is
'orderStatment' => [
'relaseCount' => 14,
'bulkCount' => 0,
'distiributeCount' => 0
],
the output of expectation and SQL produce is
'orderStatment' => [
'relaseCount' => 14,
'bulkCount' => 5,
'distiributeCount' => 4
],
There are 8 Different type of status and 3 different types of order_type available on Table I want to get each order_type count of every status
You might have better luck doing it all in one query, then getting the data back out.
$receved = Order::select('status', 'order_type', DB::raw('COUNT(id) as order_count'))->where('status',0)
->groupBy('order_type')
->get();
This will give you a collection of all of the order types and their counts in one query. After that, you can get the data back out.
$bulk = $relase = $distiribute = 0;
foreach($receved as $rec) {
if($rec->order_type == 1) $relase = $rec->order_count;
elseif($rec->order_type == 2) $bulk = $rec->order_count;
elseif($rec->order_type == 3) $distiribute = $rec->order_count;
}
The problem you're facing is due to the fact that all of the following statements are manipulating the same query builder object:
$receved = Order::select('status', 'order_type')->where('status',0);
$relase = $receved->where('order_type', 1)->get();
$bulk = $receved->where('order_type', 2)->get();
$distiribute = $receved->where('order_type', 3)->get();
So the actual queries created will be something like this:
All start with: select status, order_type from orders where status = 0 and
order_type = 1;
order_type = 1 and order_type = 2;
order_type = 1 and order_type = 2 and order_type = 3;
This is why the last two queries return 0. It's expected once you see the resulting query.
You can verify this by logging the query (see this answer for details, or the docs here).
$receved is actually getting the where clauses attached to it each time. So you're not just starting with the original statement, but building onto it each time you call where.

Eloquent/SQL - Get the row number of a query (rank)

I would like to know the rank based on my DB structure:
I have a model Post that belongs to a model called Edition (also one Edition has many Post).
One Post has many Like.
I would like to know the rank of a Post based on the Like count inside a particular Edition.
The code:
// Define the id of an edition
$edition_id = 53;
// The id of the post to retrieve rank
$post_id = 132;
// Compose the query by select all posts, of interested edition ...
$query = App\Models\Post::where('edition_id', $edition_id)
// ... with like count (this produce an additional field named likes_count) ...
->withCount('likes')
// ... in descendig order by this count.
->orderBy('likes_count', 'desc');
// By execute it I can get right results.
$query->get();
For people who are not familiar with Laravel Eloquent ORM, I report the sql query executed from code above:
select `posts`.*, (select count(*) from `likes` where `posts`.`id` = `likes`.`post_id` and `likes`.`deleted_at` is null) as `likes_count`
from `posts`
where `edition_id` = '53' and `posts`.`deleted_at` is null
order by `likes_count` desc
I report the query results:
=> Illuminate\Database\Eloquent\Collection {#994
all: [
App\Models\Post {#993
id: 135,
likes_count: 4,
},
App\Models\Post {#1075
id: 134,
likes_count: 3,
},
App\Models\Post {#1091
id: 133,
likes_count: 2,
},
App\Models\Post {#997
id: 132,
likes_count: 1,
},
App\Models\Post {#1038
id: 131,
likes_count: 0,
},
],
}
How can I get the row position of the record with a certain id from the results of the composed query?
For example, how to retrieve the rank result of the record with id = 132?
You can use a subquery:
$query = Post::where('edition_id', $edition_id)
->withCount('likes')
->selectRaw('#rank := #rank + 1 rank')
->from(DB::raw('`posts`, (SELECT #rank := 0) vars'))
->orderBy('likes_count', 'desc');
$posts = Post::fromSub($query, 'posts')->paginate();
$post = Post::fromSub($query, 'posts')->find($post_id);
Workaround for Laravel < 5.6:
Builder::macro('fromSub', function($query, $as) {
$this->bindings = array_merge(
array_slice($this->bindings, 0, 1),
['from' => $query->getBindings()],
array_slice($this->bindings, 1)
);
$sql = '('.$query->toSql().') as '.$this->grammar->wrap($as);
return $this->from(DB::raw($sql));
});
You can use the search() method to find the key:
The search method searches the collection for the given value and returns its key if found. If the item is not found, false is returned.
$id = 132;
$key = $query->search(function($post,$id) {
return $post->id === $id;
});

Yii2 Delete Query Using Relations

I have defined a relation in Yii2 in which every website can have multiple feeds:
public function getFeeds() {
return $this->hasMany(Feed::className(), ['website_id' => 'id']);
}
Now consider following query:
$ids = [2, 3];
$feeds = Website::find()->where(['user_id' => 1])->with(['feeds' => function($query) use ($ids) {
$query->where(['id' => $ids);
}])->all();
The corresponding raw SQL queries are:
SELECT * FROM `website` WHERE `user_id`= 1 // returns 4, 5, 6
SELECT * FROM `feed` WHERE (`id` IN (2, 3)) AND (`website_id` IN (4, 5, 6))
My questions is, can I have delete version of this query using Active Record? Something like this:
SELECT * FROM `website` WHERE `user_id`= 1
DELETE FROM `feed` WHERE (`id` IN (2, 3)) AND (`website_id` IN (4, 5, 6))
Any help would be appreciated.
You may do as this:
$query = Website::find()
->select('id')
->where(['user_id' => 1]);
Feed::deleteAll([
'id' => [2, 3],
'website_id' => $query
]);
In this case could be better a CreateCommand
for do this you should bild raw query using join eg:
select *
from `feed`
join `website` on `website`.id = `feed`.`website_id`
WHERE website`.`user_id`= 1
AND `feed`.id IN (2, 3)
or for delete
delete
from `feed`
join `website` on `website`.id = `feed`.`website_id`
WHERE website`.`user_id`= 1
AND `feed`.id IN (2, 3)
then for Yii2
$sql = "delete
from `feed`
join `website` on `website`.id = `feed`.`website_id`
WHERE website`.`user_id`= 1
AND `feed`.id IN (2, 3);"
Yii::$app->db->createCommand($sql)->execute();

Yii2 : Can I bind an array to an IN() condition in join?

I will try below query, but not sure is prevent sql injection?
$status = [1, 2, 3];
$param = implode(', ', $status);
$rows = (new \yii\db\Query())
->select('*')
->from('user')
->leftJoin('post', "post.user_id = user.id AND post.some_column = $value AND post.status IN ($param)");
->all();
return expected results but may be occur sql injection. My IN condition look like is IN (1, 2, 3)
$rows = (new \yii\db\Query())
->select('*')
->from('user')
->leftJoin('post', "post.user_id = user.id AND post.some_column = :sid AND post.status IN (:param)", [':param' => $param, ':sid' => $value]);
->all();
only compare first element in array because is look like this IN ('1, 2, 3') its consist single string not check second element in array only work on first element.
I refer below link but no idea for how to implement this condition.
Can I bind an array to an IN() condition?
Please give the solution for how to use IN() Condition in On part of join(PDO/Yii2/mysql).
Based on this issue:
$rows = (new \yii\db\Query())
->select('*')
->from('user')
->leftJoin('post', ['post.user_id' => new \yii\db\Expression('user.id'), 'post.some_column' => $sid, 'post.status' => $statuesArray]);
->all();
Yii2 can create a parametrized IN condition by passing the condition as an array i.e:
['post.status' => $status]
However, converting your join condition to the array format will not work as explained in the Yii guide:
Note that the array format of where() is designed to match columns to values instead of columns to columns, so the following would not work as expected: ['post.author_id' => 'user.id'], it would match the post.author_id column value against the string 'user.id'. It is recommended to use the string syntax here which is more suited for a join:
'post.author_id = user.id'
Since you are using an INNER JOIN the result of putting the join condition in WHERE instead of in ON will be syntactically equal as explained in INNER JOIN condition in WHERE clause or ON clause?. For readability and ease of maintenance, you can leave the comparison for the tables columns in the join condition:
$rows = (new \yii\db\Query())
->select('*')
->from('user')
->innerJoin('post', 'post.user_id = user.id')
->where(['post.some_column' => $value, 'post.status' => $status])
->all();

laravel: multiple select query

I understand that to do a select query is
$bearLawly = Bear::where('name', '=', 'Lawly')->first();
but how to I do a select query such as
SELECT * FROM bear where name = 'abc' AND age => '5' AND title = 'kid' ORDER BY name LIMIT 5, 10
Thanks!
You may try this:
$bearLawly = Bear::where('name', 'abc') // By default = will be used, so optional
->where('age', '>=', '5')
->where('title', 'kid')
->orderBy('name') // or orderBy('name', 'desc') for reverse
->take(5)->skip(10)->get();
According to following query:
SELECT * FROM bear where name = 'abc' AND age => '5' AND title = 'kid' ORDER BY name LIMIT 5, 10
Just chain them:
$bearLawly = Bear::where('name', 'Lawly')->where('age', '5')->first();

Categories