How to include an Eloquent relationship into JSON conversion result? - php

I want to return JSON data to my Angular front-end with Laravel 5 but I am stuck with this problem : I have an Alert eloquent model which has a relationship with AlertFrequency model:
class Alert extends Model
{
public function alertFrequency()
{
return $this->belongsTo('App\Models\AlertFrequency');
}
}
but when I try to return the alerts listing as a JSON...
$alerts = Auth::user()->alerts->toJson();
return $alerts;
here is what I get :
[{"id":9,"title":"fqdsgsq","place":"gdqsgq","user_id":1,"alert_frequency_id":3,"job_naming_id":3,"created_at":"2016-07-16 14:09:41","updated_at":"2016-07-16 14:09:41"}]
So I do have the "alert_frequency_id" column value but not the actual AlertFrequency object
The only workaround I found to be working so far is this :
$alerts = Auth::user()->alerts;
foreach ($alerts as $alert) {
$alert->jobNaming = $alert->jobNaming;
$alert->alertFrequency = $alert->alertFrequency;
}
return $alerts;
which is very ugly...

You need to manually load the relationship. This is called lazy eager loading a relationship.
$alerts = Auth::user()->alerts->load('alertFrequency')->toJson();
return $alerts;
When you do Auth::user()->alerts->toJson() you just fetched the data from the Alert model, but you want data from another model (another table) then you need to tell that using the load method.
Bonus
If your code is in a controller method or a router closure instead of calling toJson() you can just return the collection and Laravel will do that for you. Example:
public function controllerMethod() {
return Auth::user()->alerts->load('alertFrequency');
}
Happy coding!

Related

Yii2 model relations not returned in json

Am fetching data with javascript to a yii2 api which i would like to also return model relations.
I have the following
In my user class i have
class User{
//relationship
public function getAuthOptions(){
return $this->hasMany(UserAuthOption::className(),["user_id"=>"id"]);
}
}
Am fetching the data as follows
$users = User::find()->with(['authOptions'])->all();
return $users.
The above returns an array of objects which doesnt contain the authOptions.
I understand that you can access the relationship data via
$users[0]->authOptions
But is there a way the relationship data can be returned on the $users query for javascript api requests which cannot access the $users[0]->authOptions
Currently am able to achieve this by adding a custom field like
class User{
public function fields()
{
$fields = parent::fields();
$fields["authOptions"]=function ($model){
return $model->authOptions;
};
return $fields;
}
public function getAuthOptions(){
return $this->hasMany(UserAuthOption::className(),["user_id"=>"id"]);
}
}
But the above is not optimal because it returns authOptions in all requests but i would like to controll which requests require authOptions to be returned.
class User extends ActiveRecord
{
public function extraFields()
{
return [
'authOptions',
];
}
public function getAuthOptions() {
return $this->hasMany(UserAuthOption::class, ['user_id' => 'id']);
}
}
After that you can use expand param when you need in your API query like this:
/api/controller/action?expand=authOptions
->with(['authOptions']) is not necessary in REST Controller.

Slim 3 with Eloquent ORM - Relationships not exist on collection

I have a problem with Eloquent relationships in my Slim 3 based application. The goal is return $data to view. When I try that:
use App\Models\Favorite as F;
$favs = F::where('user_id',$_SESSION['user_id'])->get()->offer;
foreach($favs as $offer)
{
// not important now...
}
return $data;
I am getting an error:
Property [offer] does not exist on this collection instance.
I made relations in my Offer and Favorite models:
public function offer() // in Favorite model
{
return $this->belongsTo('App\Models\Offer', 'offer_url');
}
public function favorite() // in Offer model
{
return $this->hasMany('App\Models\Favorite', 'url');
}
In database we can see tables: offers (with url column) and favorites (with offer_url column).
How to make that relationships working?
Please for help.
Get method return a Collection instance, not Favorite.
Use:
$favs = F::where('user_id', $_SESSION['user_id'])->get();
then:
foreach($favs as $favorite) {
$offer = $favorite->offer;
}
And don't forget to use eager loader: https://laravel.com/docs/5.4/eloquent-relationships#lazy-eager-loading

one to many relationship in laravel

In my database, i have two tables notification and alertFrequency. The notification has field id and website_url and the alert frequency has id and notification_id. Both tables has models which is one to many. The notification can have one or many alertFrequency.
class Notification extends Model {
public function alertFrequencies() {
return $this - > belongsToMany('AlertFrequency::class');
}
}
namespace App;
use Illuminate\ Database\ Eloquent\ Model;
class AlertFrequency extends Model {
protected $table = 'alertFrequencies';
public function notification() {
return $this - > belongsTo(Notification::class);
}
}
in the notification model, i wrote a function called alert, that will give me the laastest alert associated with a specific websie.
public function alert(){
$alert_frequency = AlertFrequency::find('notification_id')->first();
$o_notification = $this->alertFrequencies()->where('notification_id',$alert_frequency->id)
->select('created_at')->orderBy('created_at')->first();
if($alert_frequency ==null){
return false;
}
return created_at;
}
Is this a right way to extract the data? i would appreciate any suggestions and helps?
Notification hasMany AlertFrequency
public function alertFrequencies(){
return $this->hasMany('App\AlertFrequency');
}
and,
$alert_frequency = AlertFrequency::with('notification')->orderBy('created_at','desc')->first();
loads the latest AlertFrequency along with it's notification.
See One to Many relationship and Eager loading in documentation.
to get laastest alert associated with a specific websie with url $website_url.
Notification::where('website_url', $website_url)->orderBy('created_at')->first();
hasMany relation :
public function alertFrequencies(){
return $this->hasMany('App\AlertFrequency','notification_id');
}

eager load of relations of a specific model in laravel

I have a model named Test like this:
class Test extends Model
{
public $primaryKey = 'test_id';
public function questions ()
{
return $this->belongsToMany('App\Question', 'question_test', 'test_id', 'question_id');
}
}
And a Question model like this:
class Question extends Model
{
public function tests ()
{
return $this->belongsToMany('App\Test', 'question_test', 'question_id', 'test_id');
}
}
As you see there is a ManyToMany relation between this two model.
Now in a controller function, I want to get an specific Test(by id) and send it to a view. then eager load all it's questions related models and send it to another view. like this :
public function beginTest ($course_id, $lesson_id, $test_id)
{
$test = Test::find($test_id);
if ($test->onebyone) {
return view('main/pages/test/test-onebyone', compact('test'));
} else {
$test = $test->with('questions.options')->get();
return view('main/pages/test/test-onepage', compact('test', 'done_test_id'));
}
}
}
Problem is that when I use with() laravel method to eager load relations, it return all Test models with their Question relations while I want to get relations of selected Test model only.
what is your solution to solve that?
You can use 'lazy eager loading'.
$test->load('questions.options');
Using with off the model instance will make it use a new builder and cause a new query to be executed.

Eloquent Eager Load Constraints returning JSON String instead Object

I'm trying to use Laravel 4.1 and do a Eloquent Eager Load with a One-to-Many relationship. Everything seems to work fine with this:
$groups = Group::with(array('points' => function($query) {
$query->orderBy('pts', 'DESC');
}))->get();
But when I try to read the property...
foreach( $groups as $group ) {
echo var_dump($group->points);
}
It returns a JSON String of the object (with correct data in it)
What should I do to get the PHP Object instead JSON?
Edit:
Here are my models
class Group extends Eloquent
{
public $timestamps = true;
public function points() {
return $this->hasMany('Point');
}
}
.
class Point extends Eloquent
{
public function group() {
return $this->belongsTo('Group');
}
}
It seems like the code is right, and Laravel detects how are you displaying the variable an show the more pertinent format for the use case.
var_export() will show the real Object anatomy. If you need to debug it.

Categories