Laravel eager not working with select function - laravel

If I use select function the data disappears
$regions = Region::select('id', 'place_id', 'formatted_address')
->where('lang', $lang)
->with(['areas' => function($query) {
return $query
->select('id', 'place_id', 'formatted_address') // << the problem is here
->whereNotNull('area1')->whereNull('locality')->whereNull('area2');
}])
->get();
if you remove the select function, the areas field is filled with data
Relations:
$this->hasMany(Region::class, 'country', 'formatted_address');

The request must contain fields that participate in the relationship
$this->hasMany(Region::class, 'country', 'formatted_address');
->select('place_id', 'country', 'formatted_address')

Related

Why might the Elequent ORM relationship feel empty?

Here is my method available in the controller
public function getProductListAll(){
$products = Product::with('property')
->whereStatus(1)
->where('show', 1)
->where('code', '!=', 1)
->where('is_roketable',true)
->with(['prices_roket' => function ($q) {
return $q->whereNull('user_id');
}]);
$products = $products->whereIn('product_type', ['education', 'consultancy', 'startup']);
$data['products'] = $products->select([
'id', 'name', 'image', 'commission', 'price',
'buy_now', 'type', 'short_desc', 'pricing_desc',
'offer_status', 'period_status', 'period', 'period_frequency',
'endpoint', 'product_type', 'unique_id', 'discount_show_status',
'annual_payment', 'pre_register', 'privacy_status', 'privacy',
'sg_project', 'last_pre_register_date', 'product_desc',
'product_consulting', 'product_status',
])->get();
return response()->json($data);
}
and here is the relationship in my model.
return $this->hasMany(ProductPrice::class)->select('price','created_at','user_id','offer_id')
->orderBy('price')
->where(function ($q) {
$q
->where(function ($q2) {
$q2->whereNull('offer_id');
})
->orWhere(function ($q2) {
$q2->whereNotNull('offer_id');
$q2->where('user_id', auth()->user() ? auth()->user()->id : 0);
});
});
I tried to change my relationship and rewrite it, but when I write select, I cannot access any data. When I remove select, they all come. I can't select at prices relationship.
You can not use ->select() inside your model relationship.
Instead what you can do to limit the selection is by adding it into ->with()
For example
$products = Product::query()
->with(['property' => function ($q) {
$q->select(['price','property.created_at','user_id','offer_id']);
}])
->where( ... )
// no need to add property 'price' inside this select
->select(['id', 'name', 'image', 'commission' ... ])
->get();

Laravel 9. Why does specifying a column limit for a related table not work?

I need get specify columns of the relationship. But both recomended in documentation way don't work for me.
I can do this by specifying the desired columns in the model, but I don't want to do it: maybe in the future I will need this relationship elsewhere with more (or fewer) columns.
Data base: table Author (id, name) and Article (id, title, author_id)
The author_id column is foreign key for id column of Author table.
Controller:
//it display all columns
$pack = Author::with(['Article' => function ($query) {
$query->select('id', 'title');
}])
->where('id', $id)
->get();
//also it display all columns
$pack = Author::query()
->with(['Article' => function ($query) {
$query->select('id', 'title');
}])
->where('id', $id)
->get()
//also it display all columns
$pack = Author::with(['Article:id,title'])
->where('id', $id)
->get();
Model:
class Author extends Model
{
protected $guarded = [];
public function Article()
{
return $this->hasMany('App\Models\Article')
//->select('id', 'title'); //If uncommented, then specifying columns works
;
}
}
Why doesn't specifying columns in the controller work for me?

Laravel 8 eager loading, how to access subquery fields

This is working:
$clients = Client::with([
'contacts' => function ($query) {
$query
->select('client_id', 'first_name', 'last_name')
->where('contact_type_id', '=', 1);
}])
->orderBy('client_name')
->get(['id', 'client_name', 'city', 'state']);
dd($clients);
However, I'm unsure of how to access first_name and last_name on the subquery. They're showing up in the "relations" object in the dump, but in my mind I'm envisioning a dataset that I would access like,
$client->first_name, etc.
When I try to add the fields to the get() method at the end, it doesn't recognize them, so I'm doing something wrong, or I need to access the subquery fields differently.
When you are eager loading the relationships, you are just preloading them.
If your relationship is defined as hasMany (which seems to be the case here, a Client hasMany Contact), then you'll always get a collection from eager loading.
If you defined another relationship in your model in order to get only one result, for instance:
public function contact()
{
return $this->hasOne(Contact::class)->where('contact_type_id', 1)->latest('id');
}
Your new relationship contact would return only one result:
$clients = Client::with('contact')
->orderBy('client_name')
->get(['id', 'client_name', 'city', 'state']);
foreach($clients as $client){
dd($client->contact->first_name);
}
// each Client of $clients would have a ->contact relationship
You should add field id to select() method in subquery and field contact_id to get() method
$clients = Client::with(['contacts' => function ($query) {
$query->select('id', 'client_id', 'first_name', 'last_name')->where('contact_type_id', '=', 1);
}])
->orderBy('client_name')
->get(['id', 'client_name', 'city', 'state', 'contact_id']);
foreach ($clients as $key => $client) {
dd($client->contacts->first_name);
// Or
dd($client->contacts()->first()->first_name);
}

how to select specific fields from the tables in laravel

This works but it gives all the fields of account table but only few are required.
$data = Loan::select('*')
->with([
'member' => function ($query) {
$query->addSelect('id', 'name');
},
'member.account'
])
->get();
This gives account: null
$data = Loan::select('*')
->with([
'member' => function ($query) {
$query->addSelect('id', 'name');
},
'member.account'=> function ($query) {
$query->addSelect('id', 'account'); // if this line is commented, all the fields are returned but I just need few fields.
}
])
->get();
Member model:
public function account()
{
return $this->hasOne(Account::class);
}
Account model:
public function member()
{
return $this->belongsTo(Member::class);
}
How can I get only the required fields of account table?
You can define the relationship and set it to give you specific columns like this.
on Member model
public function account()
{
return $this->hasOne(Account::class)->select(['id', 'account']);
}
You can try to define required fields in with:
$data = Loan::select('*')
->with([
'member' => function ($query) {
$query->addSelect('id', 'name');
},
'member.account:id,number'
])
->get();
Your are close you just need to select the foreign key column that points to your account model , I guess it would be account_id, So you basically need to select 3 columns from your table which are select(['id', 'name','account_id'])
$data = Loan::with(['member' => function ($query) {
$query->select(['id', 'name','account_id'])
->with(['account'=> function($query){
$query->select(['id','name']);
}]);
}])
->get();
So if you have another nested relation account -> type and you need specific columns from type so you need to select the foreign key column from accounts models as
with(['account'=> function($query){
$query->select(['id','name','type_id'])
->with(['type'=> function($query){
$query->select(['id','name']);
}]);
}]);

Ordering Results from Related Tables in Eloquent and the Session

I have the following in my Event model in Laravel 4. The reason I am using QueryBuilder and not Eloquent is I need to have links in each column header in my results table in my view, that when clicked, order the results in asc or desc based on that column.
The issue I'm having is, if I use Eloquent, it won't work as most of the data is pulled through via relationships to other tables, so Eloquent can't find the required columns/fields.
public static function getEvents($perPage = 10)
{
$order = Session::get('event.order', 'start_date.desc');
$order = explode('.', $order);
$columns = array(
'events.id as id',
'title',
'locations.city as city',
'suppliers.name as supplier_name',
'venues.name as venue_name',
'start_date',
'courses.price as course_price',
'type',
'status',
'max_delegates as availability',
'tutors.first_name as tutor_first_name',
'tutors.last_name as tutor_last_name',
'contacts.first_name as d_first_name'
);
$events = DB::table('events')
->leftJoin('courses', 'course_id', '=', 'courses.id')
->leftJoin('suppliers', 'supplier_id', '=', 'suppliers.id')
->leftJoin('locations', 'location_id', '=', 'locations.id')
->leftJoin('venues', 'venue_id', '=', 'venues.id')
->leftJoin('event_types', 'event_type_id', '=', 'event_types.id')
->leftJoin('event_statuses', 'event_status_id', '=', 'event_statuses.id')
->leftJoin('tutors', 'tutor_id', '=', 'tutors.id')
->leftJoin('delegate_event', 'delegate_event.event_id', '=', 'events.id')
->leftJoin('delegates', 'delegates.id', '=', 'delegate_event.delegate_id')
->leftJoin('contacts', 'delegates.contact_id', '=', 'contacts.id')->groupBy('events.id')
->select($columns)
->orderBy($order[0], $order[1])
->paginate($perPage);
return $events;
}
If you look at my EventsController at the getOrder method:
public function getOrder($order)
{
Session::put('event.order', $order);
return Redirect::back();
}
You can see I am storing the order in the session and then in my model using that to sort the order of results.
Is there a way to do this in Eloquent the way I need to?
You know you can just add a join() to eloquent right?
So, as an example, if you have users and each user has some blog posts (i.e. user has_many blogs), you can output an eloquent model showing username and blog title, ordered by blog title, as follows:
user::join('blogs', 'blogs.id','=','users.blog_id')
->order_by('blogs.title', 'asc')
->select(array('users.username', 'blogs.title'))
->paginate(10);

Resources