Laravel Eloquent pagination on relationships - php

I am trying to paginate a Eloquent relationship like this:
$query = Product::find(1)->options()->paginate();
But I get the following error:
Fatal error: Call to a member function getCurrentPage() on a non-object
I have confirmed that the code $query = Product::find(1)->options() returns a collection of options. The $query object seems to be of type hasMany. Below are the model classes I am using.
class Product extends Eloquent
{
protected $table = 'products';
public function options ()
{
return $this->hasMany('ProductOption', 'product_id');
}
}
class ProductOption extends Eloquent
{
protected $table = 'product_options';
public function product()
{
return $this->belongsTo('Product', 'product_id');
}
}
Does eloquent not return paginated results for relationships?

You can not lazy load relational pagination like that, instead in your Product Model put the following function below your options has many relationship
public function getOptionsPaginatedAttribute()
{
return $this->options()->paginate(10);
}
This will allow you to call the pagination on your relational data by
$product->options_paginated

Create a custom length-aware paginator.
$options = new LengthAwarePaginator(Product::find(1)->options()->
->skip(($request->input('page', 1) - 1) * 10)->take(10)->get(),
Product::find(1)->options()->count(),
10, $request->input('page', 1),
[
// paginator options here
]);

$query = Product::find(1)->get()->options()->paginate();
Try adding get

Related

Sort belongsToMany relation base on field in belongTo relation Laravel Eloquent

I have a scenario where User has a belongsToMany relation with PortalBreakdown, PortalBreakdown has a belongsTo relation with Portal. Portal has order column in it. I have a method listing_quota($id) in UserController which returns all breakdowns of the user. I want to sort these breakdowns based on order column of the portal. Below are the code of classes and a method I have tried.
class User extends Model {
protected $table = 'user';
public function listing_quota() {
return $this->belongsToMany('App\PortalBreakdown', 'user_listing_quota')->withPivot(['quota']);
}
}
class PortalBreakdown extends Model {
protected $table = 'portal_breakdown';
public function portal() {
return $this->belongsTo('App\Portal');
}
}
class Portal extends Model {
protected $table = "portal";
protected $fillable = ['name', 'description', 'order'];
}
Below is the method where I am trying to return sorted by order. I tried few things some of which can be seen in commented code but not working.
class UserController extends Controller {
public function listing_quota($id)
{
$user = User::with(['listing_quota' => function ($query) use ($id) {
// $query->sortBy(function ($query) {
// return $query->portal->order;
// });
}, 'listing_quota.portal:id,name,order'])->findOrFail($id);
// $user = User::with(['listing_quota.portal' => function ($q) {
// $q->select(['id', 'name',order']);
// $q->orderBy('order');
// }])->findOrFail($id);
return $this->success($user->listing_quota);
}
}
I also tried chaining orderBy directly after relation in Model class but that's also not working from me. Thank you in advance.
NOTE: I am using Laravel Framework Lumen (5.7.8) (Laravel Components 5.7.*)

How in laravel to add a condition for a eager load relation?

there are the following models:
class Page extends Model {
protected $with = ['blocks'];
public function blocks() {
return $this->belongsToMany('\App\Block');
}
}
class Block extends Model {
protected $with = ['fields'];
public function fields() {
return $this->hasMany('\App\Fields');
}
}
class Field extends Model {
protected $with = ['data'];
public function data() {
return $this->hasOne('\App\Data');
}
}
And there is a controller in which I get the data:
public function get() {
$page_id = 1;
$data = Page::find($page_id);
}
The result is the following structure:
Page
- Block 1
- field 1
- Some data
- field 2
- More data
- Block 2
- Field 1
- Other data
The block may belong to multiple pages.
The field belongs to the block.
But the data stored in this field belong to both the field and the page at the same time.
So, I need to pass the variable $page_id to the data() function of the Field model. To get something like this:
public function data() {
return $this->hasOne('\App\Data')->where('page_id', '=', $page_id);
}
Tell me, please, how to do this?
I solved this problem by removing $with from models and selecting the data with this code:
Page::with(['blocks.fields.data'=> function($query) use ($page_id){
$query->where('page_id', $page_id);
}])->find($page_id);
But it's not beautiful. I just want to write Page::find($page_id);
Thanks!
I like force loading relation but in your case maybe this what you looking for :
https://laravel.com/docs/master/eloquent-resources#conditional-relationships
you can do this as the following :
Page::whereHas('blocks.fields.data', function($query) use ($page_id){
$query->where('page_id', $page_id);
})->find($page_id);

How to apply relationship with two id's in laravel

So I have a model called data_storage and another model entity_states
I have to fetch the record from data_storage with entity_states where entity_state has data_storage_id and state_id.
How can I use eloquent to achieve this ?.
Or Ill have to use Query builder and use innerJoin?
Update1
My Actual Query
$this->values['new_leads'] = $data_storages->with('actions','states','sla')->where('wf_id',$wfid)->get();
My data_storage modal
class data_storages extends Model
{
//
protected $fillable = ['layout_id','member_id','company_id','team_id','data','status','wf_id'];
function actions()
{
return $this->hasMany('App\Models\ActionDataMaps', 'data_id', 'id' );
}
function states()
{
return $this->hasOne('App\Models\workflow_states','id','status');
}
function sla()
{
//Here I have to get those row from entity_states model where , data_storage_id and state_id
}
}
Thanks
Here's the more reasonable way to do it:
class DataStorage extends Model {
public states() {
return $this->belongsToMany(State::class,"entity_states");
}
}
class State extends Model {
public storages() {
return $this->belongsToMany(DataStorage::class,"entity_states");
}
}
Then you can eager-load related models via e.g.:
$storage = DataStorage::with("states")->first();
$storage->states->first()->column_in_related_state;
Or via the state:
$state = State::with("storages")->first();
$state->storages->first()->column_in_related_storage;
If there are additional columns in the pivot table entity_states then you can refer to them in the relationship as e.g.:
public states() {
return $this->belongsToMany(State::class)->withPivot("pivot_column");
}
In your model data_storage you can define a property / method entity_states to get them:
class data_storage extends Model
{
public function entity_states()
{
return $this->hasMany('App\entity_states','data_storage_id')->where('state_id ','=',$this->table());
}
}
Then you can access them in an instance by
$entityStatesOfDataStorage = $yourDataStorageInstance->entity_states;
See this link:
https://laravel.com/docs/5.3/eloquent-relationships
for Query Builder you may use this:
DB::table('data_storage')
->join('entity_states','data_storage.data_storage_id','=','entity_states.state_id')
->get();
For your reference Laravel Query Builder

Laravel querying model relations

I'm still struggeling with the laravel Models. At first I tried doing it all using the tables, but thats not smart, I'll miss out on lots of the laravel functions.
I have the following setup
ProjectTwitterStatus links the projects and the twitter statuses.
TwitterStatus has all the details of a twitter status and has a unique ID ('posted at' datetime of tweet is among the details)
TwitterRetweets has the ID of the TwitterStatus - the actual retweet - and the tweet ID of the retweeted status
TwitterReplies has the ID of the TwitterStatus - that is the actual reply - and/or the user ID if not a reply to a status but to a user.
What I want? To get for each date (DATE(datetime)) the count of the statuses, retweets and replies, using the laravel model relations.
These are the models.
class ProjectTwitterStatus extends Eloquent {
protected $table = 'project_twitter_statuses';
protected $softDelete = true;
public function twitterStatus() {
return $this->belongsTo('TwitterStatus');
}
public function project() {
return $this->belongsTo('Project');
}
}
class TwitterStatus extends Eloquent {
protected $table = 'twitter_statuses';
public function twitterRetweet() {
return $this->hasMany('TwitterRetweet');
}
public function twitterReply() {
return $this->hasMany('TwitterReply');
}
public function twitterUser() {
return $this->belongsTo('TwitterUser');
}
public function projectTwitterStatus() {
return $this->hasMany('ProjectTwitterStatus');
}
}
class TwitterRetweet extends Eloquent {
protected $table = 'twitter_retweets';
public function twitterStatus() {
return $this->belongsTo('TwitterStatus');
}
}
class TwitterReply extends Eloquent {
protected $table = 'twitter_replies';
public function twitterStatus() {
return $this->belongsTo('TwitterStatus');
}
}
I got the count of the twitterStatuses using this:
$twitterStatuses = TwitterStatus::has('projectTwitterStatus')
->groupBy(DB::raw('DATE(datetime)'))
->get(array(DB::raw('COUNT(id) AS tweets'),DB::raw('DATE(datetime) AS date')));
I tried for example this to get the retweet count added but that has no effect (a reference to the model apears in the object -> array().
$twitterStatuses = TwitterStatus::has('projectTwitterStatus')
->with(array('twitterRetweet' => function($query)
{
$query->count();
}))
->groupBy(DB::raw('DATE(datetime)'))
->take(10)
->get(array(DB::raw('COUNT(id) AS tweets'),DB::raw('DATE(datetime) AS date')));
Can anyone point me in the right direction?
Not 100% sure how your intended solution is to be used - Assuming you simply want a count of the number of retweets related to twitterStatus?
$count = $twitterStatus->twitterRetweet()->count();
where $twitterStatus is an already retrieved model - not a collection.
if $twitterStatus is a collection to iterate through you can also eager load the related model using either with() or load()
Then you can iterate through each model in the collection - depends on how you wanted to use the results

Eloquent relationships in Laravel 4

I'm trying to make a mini CMS-type component and I have three models:
Page.php
class Page extends Eloquent {
protected $table = 'pages';
public function content() {
return $this->hasManyThrough('Content', 'PageGroup');
}
public function groups() {
return $this->hasMany('PageGroup');
}
}
PageGroup.php
class PageGroup extends Eloquent {
protected $table = 'page_groups'
public function group() {
return $this->hasMany("Content");
}
}
Content.php
class Content extends Eloquent {
protected $table = 'content';
public function content() {
return $this->hasMany("Content");
}
}
Edit:
I've set up my relationship models with the correct relationships.
$page = Page::find(1);
$page_group = $page->groups()->where('id', '=', 1)->get();
Returns the PageGroup collection belonging to the Page. I guess my new question is if it's possible to get a collection from that collection... Something like:
$content = $page_group->content;
Because that returns:
Undefined property: Illuminate\Database\Eloquent\Collection::$content
Does this make any sense? I apologize for the newbie question; I'm just getting into Laravel!
I feel like an idiot.
The method chain $page->groups()->where("id", "=", 1)->get()->content; will not work because $page->groups()->where("id", "=", 1); returns a list of rows!
$page->groups()->where("id", "=", 1)->first()->content will work.

Categories