problem when use withCount and cursorPaginate together in laravel - laravel

I have two tables :
profiles table
+----+-------+--------+
| id | title | verify |
+----+-------+--------+
And profile_followers table
+------------+---------+
| profile_id | user_id |
+------------+---------+
I want to get profile list with orderBy count followers together cursorPaginate in Laravel
I use this code :
$profile = Profile::where('verify', '=', 1)
->withCount('followers')
->orderBy('followers_count', 'desc')
->cursorPaginate(20);
I get the first 20 rows, but when I try to return the next 20 rows with Cursor(nextPageUrl), an error like this occurs:
Column not found: 1054 Unknown column 'followers_count' in 'where clause'
It works with Paginate, but not with cursorPaginate.

Related

Laravel ordering and limit results of a left join

One to many relationships, each product has many prices
table products
id | name | slug | created_at | update_at
table prices
id | product_id | title | price | link
I want to get the data limit of product limit 20 table and order created_at and each product get the lowest price, order column price. I want to use the query builder.
i tried
$products = DB::table('products')
->leftJoin('prices', 'products.id', '=', 'prices.product_id')
->select('products.id', 'products.name')->distinct()
->selectRaw('max(prices.price) as price')
->groupby('products.id')
->orderby('products.updated_at')
->get();
but it get all products and table prices order column id
You can use Eloquent Like This
public function price() {
return $this->hasMany('App\model\Prices' , 'product_id' ,'id');
}
and get like this , It will give you the mapped price only for your specific product
$product = Product::with('price')
->where(do the stuffs)
->orderBy(do the stuffs)
->get();
Or you can use the callback as well in with()

laravel get unique results filter by a column value

I have a user table in which there is column Membership Id. I need to fetch rows which do not have duplicate value for Membership Id column. For Example, this is my table structure
ID Name Membership Id
1 xxx 123
2 xxx 124
3 xxx 124
4 xxx 125
In output, I want to skip rows which have duplicate values for Membership Id and want to fetch only last row so output should be row 1,3,4 from above example
Use a subquery JOIN:
$join = User::select('membership_id', DB::raw('max(id) id'))
->groupBy('membership_id');
$sql = '(' . $join->toSql() . ') as latest';
$users = User::join(DB::raw($sql), function($join) {
$join->on('users.membership_id', 'latest.membership_id')
->on('users.id', 'latest.id');
})->get();
In Laravel 5.6.17 you can use joinSub():
$join = User::select('membership_id', DB::raw('max(id) id'))
->groupBy('membership_id');
$users = User::joinSub($join, 'latest', function($join) {
$join->on('users.membership_id', 'latest.membership_id')
->on('users.id', 'latest.id');
})->get();
Via eloquent
User::select('Membership_Id')->distinct()->get();
Vie db facade
DB::table('users')->select('Membership_Id')->distinct()->get();
For Eloquent
MyModel::distinct()->get(['column_name']);
for you
User::distinct()->get(['Membership Id']);

Eloquent in Laravel-Datatables, select in select?

I have 3 tables, the 1st has a FK from the 2nd, and the 2nd has a FK from the 3rd:
Table 1: [admin_demandas]
-------------------------
id_demanda| projec_id
-------------------------
Table 2: [admin_projec]
-------------------------
id_projec | sub_id
-------------------------
Table 3: [admin_sub]
-------------------------
id_sub | name
-------------------------
What I need is to get the 'name' from Table 3 but starting with the Model of the table 1.
I was trying something like this:
$data = AdminDemanda::select([
'id_demanda',
'admin_projec.sub_id AS sub_id',
'admin_sub.name AS name',])
->join('admin_projec', 'admin_demandas.projec_id', '=', 'admin_projec.id_projec')
->join('admin_sub', 'admin_projec.sub_id', '=', 'admin_sub.id_sub')
->get();
return Datatables::of($data)->make(true);
I've done my Datatables with only 1 JOIN (2 tables) but not sure how to do those 2 JOIN (3 tables). I got this error:
[Err] 1054 - Unknown column 'admin_projec.sub_id' in 'on clause'
What should I modify in my query?
Should I need to use query builder instead Eloquent, with a DB::raw() query?
Solved with this:
Inner join between three tables in mysql
it was simple... now in case anyone need it, my Datatable query is:
$datos = AdminDemanda::select([
'id_demanda',
'admin_dis.nombre AS nombre_dist',
'admin_sub.nombre AS nombre_subes',
'mes AS mes_demanda',
'admin_sistemas.nombre AS nombre_sistema',
'admin_demandas.demanda_mwh AS mwh'])
->join('admin_projec', 'admin_demandas.proyeccion_demanda_id', '=', 'admin_projec.id_proyeccion_demanda')
->join('admin_sub', 'admin_projec.subestacion_id', '=', 'admin_sub.id_subestacion')
->join('admin_dis', 'admin_projec.dist_id', '=', 'admin_dis.id_dist')
->join('admin_sistemas', 'admin_projec.sistema_id', '=', 'admin_sistemas.id_sistema')
->get();
You should edit your models
By exemple in AdminSub model
public function projec(){
return $this->hasMany(AdminProjec::class , 'sub_id');
}
You should be able to do
\AdminSub::first()->projec();
And continue by editing your AdminProjec model with the same kind of relationship
public function demandas(){
return $this->hasMany(AdminDemandas::class , 'projec_id');
}
And now you could try
//I do not remember which one will works
\AdminSub::first()->projec()->first()->demandas()->name
//or
\AdminSub::first()->projec()->first()->demandas()->get()->name

Laravel running multiple queries instead of join in Eloquent

I am trying to run join between my pages table and users table. Means one user can create multiple pages and in pages table created_by column belongs to my users table column id.
Table Structure:
---------------------------------------------
id | page_title | page_desc | created_by |
---------------------------------------------
1 | Testing | Descripti | 1 |
---------------------------------------------
2 | New Page | Desc | 2 |
User table
-------------------------------------------
id | name | email | pass | created_at |
-------------------------------------------
1 | A | a#g.c | 123 | 2017-10-21 |
-------------------------------------------
2 | B | b#g.c | 123 | 2017-10-21 |
in my Page model i used:
public function createdBy(){
return $this->belongsTo('App\User','created_by','id');
}
now when i am trying to get the data with:
$model = Page::all()
foreach($model as $key => $value){
echo $value->createdBy->name."<br/>";
}
laravel generating multiple queries to get name of each user is that any way to run the join instead of multiple queries?
You're running into the N+1 problem. You need to eager load your relationship to resolve this. You can read more on eager loading here.
Use the with() method on the page query to eager load all the related user records for each page:
$model = Page::with('createdBy')->get();
foreach ($model as $key => $value) {
echo $value->createdBy->name."<br/>";
}
This will now only run 2 queries: one to get all the pages, and one to get all the users related to each page.
For that reason Laravel provides eager Loading
Eager Loading
When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. However, Eloquent can "eager load" relationships at the time you query the parent model
For more info just check this link.
OR Just Use Laravel's database query builder
You can perform join directly on your Table and fetch directly the data
$users = DB::table('pages')
->join('users', 'pages.created_by', '=', 'users.id')
->select('users.name','users.email', 'pages.*') //Specify what parameters you want.
->get();
To Join queries you can use laravel query builder like below
$pages = DB::table('pages')
->join('users', 'pages.created_by', '=', 'users.id')
->select('users.*', 'pages.*')
->get();

How can I define an Eloquent relationship using MySQL functions?

I'm having trouble defining a relationship in Eloquent. I have two tables.
The first table contains email domains. Here is an example:
+-------+----------------+-----------+
| ed_id | ed_domain | ed_isp_id |
+-------+----------------+-----------+
| 17 | | 6 |
| 13 | aim.com | 1 |
| 12 | aol.com | 1 |
+-------+----------------+-----------+
The second table contains information about my users, one of the columns being an email address.
I have tried to set this up using...
public function users()
{
return $this->hasMany('Leadgen\Lead', \DB::raw('SUBSTRING_INDEX(l_email, \'#\', -1)'), 'ed_domain');
}
What I expected to happen is something like the following:
LEFT OUTER JOIN email_domains ON SUBSTRING_INDEX(email, '#', -1) = ed_domain
What I receive though is a SQL error.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'leads.SUBSTRING_INDEX(l_email, '#', -1)' in 'where clause' (SQL: select * from `leads` where `leads`.`SUBSTRING_INDEX(l_email, '#', -1)` in (aol.com))
You cannot use the standard Laravel relations as they require to have related tables having foreign keys paired to primary keys. What you can do is to do the LeftJoin using query builder and return the users manually.
public function users() {
return DB::table('users as u')
->leftJoin('email_domains as ed', DB::raw('SUBSTRING_INDEX(u.email, \'#\', -1)'), '=', 'ed.ed_domain')
->select('u.*');
}
This function will return query builder object so you can do further chaining according to your requirements and finally use ->get() to have the final result. I have not actually run the code but basically this is what you need to do.

Resources