Call to a member function paginate() on array error in laravel - laravel-5

I want to create pagination in laravel but it gives error.
here is error "Call to a member function paginate() on array"
this is my query
$blog = DB::select("select blog_post.*,(select img_name from blog_image WHERE blog_image.bid=blog_post.bid limit 0,1) as img_name,
(SELECT count(*) FROM likes WHERE likes.bid =blog_post.bid) AS likes,
(SELECT count(*) FROM comment WHERE comment.bid =blog_post.bid ) as comments ,
(SELECT count(*) FROM blog_share WHERE blog_share.bid =blog_post.bid ) as share
from blog_post WHERE status=1 AND is_draft=0 AND is_publish=1 AND is_delete=0")->paginate(2);

You first need to rewrite your query using Laravel Eloquent. For example:
$blog = DB::table('blog_post')->where([ 'status' => 1, 'is_draft' => 0, 'is_publish' => 1, 'is_delete' = 0 ])->paginate(2);
You don't strictly need to put all the counts / inner-queries into one query. You can use Eloquent Relationships and Mutators to get that information for you. For example, the following Relationship to get the image:
class BlogPost extends Model
{
public function image()
{
return $this->hasOne('BlogImage');
}
}

Related

Convert "exists and having" SQL query into Laravel Eloquent ORM

I have difficulty to convert raw SQL query to eloquent model with relations.
This is the raw SQL query I have constructed but I cannot read the count inside the whereHas function of the eloquent.
Raw SQL query:
select *
from `subscriptions` where (`user_id` = 1) and
exists (select count(subscription_infos.id) as rec from `subscription_infos` where `subscriptions`.`id` = `subscription_infos`.`subscription_id` and `status` = 0 HAVING rec > 1)
Attempt Laravel Eloquent Model
$chk = Subscription::where(["user_id" => $userId])
->with(['info' => function($q){
return $q->where("status",0);
}])
->whereHas('info', function($q){
return $q->where("status",0);
})
->has('info','>',5)
->get();
I have setup a relation called "info" in the Subscription Model
public function info(){
return $this->hasMany(SubscriptionInfo::class,"subscription_id","id");
}
I really appreciate for those contributor that help me.

Laravel querybuilder withCount relationship

I'm encountering a problem with a script.
I'm working with Laravel 6.x (but there is no big difference).
So, I have a model Order, which has relationship with another model Group like this:
Model Order :
public function groups()
{
return $this->hasMany('App\Models\Order\Group', 'order_id')->orderBy('order_group');
}
Model Group :
public function order()
{
return $this->belongsTo('App\Models\Order\Order', 'order_id');
}
I want all the Orders that have a group where the column 'is_recurrent' inside the group is true AND there are at least 2 line 'is_recurrent' true.
Basically this :
$orders = Order::withCount(['groups' => function ($query) {
$query->where('is_recurrent', true);
}])
->having('groups_count', '>', 1)
->get();
i've try lany things, like Order::whereHas('groups', function ....).
In many cases I got :
SQLSTATE[42803]: Grouping error: 7 ERROR: column "ordergroups.order_group" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: ... "is_recurrent" = $1 group by "order_id" order by "order_gro...
^ (SQL: select "orders"., (select count() from "ordergroups" where "orders"."id" = "ordergroups"."order_id" and "is_recurrent
" = 1 group by "order_id" order by "order_group" asc) as "groups_count" from "orders" having "groups_count" > 1 order by "created_at" desc)
With
$orders = Order::withCount(['groups' => function ($query) {
$query->where('is_recurrent', true)->groupBy('order_group');
}])
->having('groups_count', '>', 1)
->get();
I got :
SQLSTATE[42703]: Undefined column: 7 ERROR: column "groups_count" does not exist
LINE 1: ...roup" asc) as "groups_count" from "orders" having "groups_co...
^ (SQL: select "orders"., (select count() from "ordergroups" where "orders"."id" = "ordergroups"."order_id" and "is_recurrent
" = 1 group by "order_group" order by "order_group" asc) as "groups_count" from "orders" having "groups_count" > 1 order by "created_at" desc)
If someone has any clue :D
The withCount function adds a variable to your model, it isn't available within the query (at least to my knowledge).
Based on the little info of your table structure, this should give the correct result; using whereHas with the same query you will ensure that there is at least 1 group with is_recurrent = true, and using withCount will give you the complete count on the individual order model.
$orders = Order::withCount(['groups' => function ($query) {
$query->where('is_recurrent', true)->groupBy('order_group');
}])
->whereHas(['groups' => function ($query) {
$query->where('is_recurrent', true)->groupBy('order_group');
}])
->get();

Eloquent whereHas Relationship with constraint on particular related Entity

Consider having two models User, and Book the last one has a status column that can obtain different string values active, inactive, deleted, so the user can have multiple books and the book belongs to the user.
how could I get only users that have their last book status = 'inactive'?
The SQL Query for the behavior is given below:
SELECT
*
FROM
`users`
WHERE EXISTS
(
SELECT
*
FROM
`books`
WHERE
`books`.`user_id` = `users`.`id` AND `books`.`status` = 'inactive' AND `books`.`id` =(
SELECT
nested.`id`
FROM
`books` AS nested
WHERE
nested.`user_id` = `users`.`id`
ORDER BY
nested.`created_at` DESC
LIMIT 1
)
)
I'm using Laravel 5.6
Create additional relationship in User model that returns wanted result. Basically you need 1-1 relationship for this.
/**
* #return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function inactiveBookStillLatestPerUser()
{
return $this->hasOne(Book::class)->where(['status' => 'inactive', 'id' => function (\Illuminate\Database\Query\Builder $nested) {
$nested->from('books as nested')
->selectRaw('max(id)')
->whereRaw('nested.user_id = books.user_id');
}]);
}
Then in somewhere in code (i.e. controller) you call it with
$users = User::has('inactiveBookStillLatestPerUser')->get();
// or if books are needed too
// $users = User::has('inactiveBookStillLatestPerUser')->with(['inactiveBookStillLatestPerUser'])->get();
I used id latest order [max(id)] in subquery to avoid unwanted result if one user made multiple books batch insert at same point of time and when all those books would have same time of insert so latest per created_at wouldn't be most accurate, maybe. But you can do that similarly, instead:
/**
* #return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function inactiveBookStillLatestPerUser()
{
return $this->hasOne(Book::class)->where(['status' => 'inactive', 'created_at' => function (\Illuminate\Database\Query\Builder $nested) {
$nested->from('books as nested')
->selectRaw('max(created_at)')
->whereRaw('nested.user_id = books.user_id');
}]);
}
Maybe second example is ok, but first example with id would work fine, though.
User::where('your-conditions')
->whereHas('books', function($query) {
$query->where('books.status', '=', 'inactive')
->orderBy('id', 'desc')
->first();
})->get();

Laravel Pivot Table, Get Room belonging to users

The structure of my pivot table is
room_id - user_id
I have 2 users that exist in the same room.
How can I get the rooms they both have in common?
It would be nice to create a static class to have something like this.
Room::commonToUsers([1, 5]);
Potentially I could check more users so the logic must not restrict to a certain number of users.
Room::commonToUsers([1, 5, 6, 33, ...]);
I created a Laravel project and make users, 'rooms', 'room_users' tables and their models
and defined a static function in RoomUser Model as below :
public static function commonToUsers($ids)
{
$sql = 'SELECT room_id FROM room_users WHERE user_id IN (' . implode(',', $ids) . ') GROUP BY room_id HAVING COUNT(*) = ' . count($ids);
$roomsIds = DB::select($sql);
$roomsIds = array_map(function ($item){
return $item->room_id;
}, $roomsIds);
return Room::whereIn('id', $roomsIds)->get();
}
in this method, I use self join that the table is joined with itself, A and B are different table aliases for the same table, then I applied the where condition between these two tables (A and B) and work for me.
I hope be useful.
I don't know the names of your relations, but I guess you can do like this :
$usersIds = [1, 5];
$rooms = Room::whereHas('users', function($query) use ($usersIds) {
foreach ($usersIds as $userId) {
$query->where('users.id', $userId);
}
})->get();
It should work. whereHas allows you to query your relation. If you need to have a static method, you can add a method in your model.
There might be a more efficient way but laravel collection does have an intersect method. You could create a static function that retrieves and loop through each object and only retain all intersecting rooms. something like this
public static function commonToUsers($userArr){
$users = User::whereIn('id',$userArr)->get();
$rooms = null;
foreach($users as $user){
if($rooms === null){
$rooms = $user->rooms;
}else{
$rooms = $rooms->intersect($user->rooms);
}
}
return $rooms;
}
This code is untested but it should work.
Room has many users, user has many rooms, so you can find the room which have those two users.
If your pivot table's name is room_users, then you can easily get the common room like this:
public static function commonToUsers($user_ids) {
$room = new Room();
foreach($user_ids as $user_id) {
$room->whereHas('users', function($query) use ($user_id) {
$query->where('room_users.user_id', $user_id);
});
}
return $room->get();
}
This code will convert to raw sql:
select *
from `rooms`
where exists (
select * from `rooms` inner join `room_users` on `rooms`.`id` = `room_users`.`room_id` where `rooms`.`id` = `room_users`.`room_id` and `room_users`.`user_id` = 1
)
and exists
(
select * from `rooms` inner join `room_users` on `rooms`.`id` = `room_users`.`room_id` where `rooms`.`id` = `room_users`.`room_id` and `room_users`.`user_id` = 5
)

laravel Model Relations result

admin_roles and admin_permissions table is a many-to-many relationship
Query ID from admin_permission where admin_roles ID in 1,2
Use SQL implementation:
SELECT
DISTINCT`admin_role_permissions`.permission_id
FROM
`admin_permissions`
INNER JOIN `admin_role_permissions` ON `admin_permissions`.`id` =
`admin_role_permissions`.`permission_id`
WHERE
`admin_role_permissions`.`role_id` IN (1, 2)
The result:
$permission_ids = [1,3,4....];
How to use laravel model to the above effect?
AdminRoleController.php
$role_ids = ['1','2'];
$permissions = AdminRole::with('relPermission')->whereIn('id', $role_ids)->get();
AdminRole.php
public function relPermission(){
return $this->belongsToMany('App\Model\AdminPermission', 'admin_role_permissions', 'role_id', 'permission_id');
}
But the result:
How can I obtain a result like
$permission_ids=[1,3,4.....]
use laravel model or laravel collection
You can use the pluck method :
$permissions = AdminRole::with('relPermission')->whereIn('id', $role_ids)->pluck('rel_permission.id');

Resources