Laravel Relations One to One and One to Many - json

I have three models Class, Students and Studentinfo. Class and students are in a One to Many relationship and Sudents and studentinfo are in a one to one relationship.
While getting students from certain Class I get a list of data in an array.
What is the best way to get data from studentinfo for each student in the array?
I am trying to get this data in json format.

You'd set up relationships like the following on the models, the important one being the hasManythrough relation:
// Class.php
public function students() {
return $this->hasMany(Student::class);
}
public function studentInfo()
{
return $this->hasManyThrough(StudentInfo::class, Student::class);
}
// Student.php
public function studentInfo() {
return $this->hasOne(StudentInfo::class);
}
public function classes() {
return $this->belongsToMany(Class::class);
}
// StudentInfo.php
public function student() {
return $this->belongsTo(Student::class);
}
... you may cast a model or collection to a string, which
will automatically call the toJson method on the model or collection:
$json = (string)$class->studentInfo;
Laravel Docs: Serialization

Related

laravel morphToMany of parent model how to use in subquery?

Current laravel models relations: ParentModel can have many documents, ChildModel can have many documents, same Documents can be belonged to any of ParentModel and ChildModel.
Also ChildModel always belongs to one ParentModel. ParentModel can have multiple ChildModels.
App\ParentModel relationships
...
public function childmodels()
{
return $this->hasMany('App\ChildModel');
}
public function documents()
{
return $this->morphToMany('App\Document', 'documentable');
}
...
App\ChildModel relationships
...
public function parentmodel()
{
return $this->belongsTo('App\ParentModel');
}
public function documents()
{
return $this->morphToMany('App\Document', 'documentable');
}
...
App\Document
...
public function parentmodels()
{
return $this->morphedByMany('App\ParentModel','documentable');
}
public function childmodels()
{
return $this->morphedByMany('App\ChildModel','documentable');
}
...
Now I'm trying to get all records of ChildModels (1) which have documents with specific type and (2) its ParentModel can also have documents.
The (1) first goal can be reached with such ChildModel method.
/* checking GET param to join this condition to final query */
if($request->has('report') && $request->input('report') == 'on') {
/* get all documents related to CurrentModel */
$query->whereHas('documents',function (Builder $query) {
$query->where('type', 1);
});
}
But this obviously doesnt include records of ChildModels, ParentModel of which has documents with specific type.
So the question is: how to include such condition into ChildModel query builder?
Found the easy way to access relations in builder
$query->whereHas('parentmodels.documents', function(Builder $query){
$query->where('type',1);
});

hasOne with null-able in laravel not working

I have a customer table which has a field called 'policy_id', where policy_id points to policy table. It is a null-able field, ie. Some customers may not have a policy.
I have a relationship code like this in Customer.php
public function policy() {
return $this->hasOne('App\Models\Policy', "id", "policy_id");
}
But when I issue a search request I am getting error like this:
Illuminate\Database\Eloquent\ModelNotFoundException: No query results for model [App\Models\Policy]
If I modify the function like this:
public function policy() {
if ($this->getAttribute('policy_id')) {
return $this->hasOne('App\Models\Policy', "id", "policy_id");
} else {
return null
}
}
But I am getting an error like this:
Call to a member function getRelationExistenceQuery() on null
Here is my search code:
$c = new Customer();
return Customer::doesntHave('policy')->orWhere(function (Builder $query) use ($req) {
$query->orWhereHas('policy', function (Builder $query) use ($req) {
$p = new Policy();
$query->where($req->only($p->getFillable()))
->orWhereBetween("policy_period_from", [$req->policy_period_start_from, $req->policy_period_start_to])
->orWhereBetween("policy_period_to", [$req->policy_period_end_from, $req->policy_period_end_to])
->orWhereBetween("payment_date", [$req->payment_date_from, $req->payment_date_to]);
});
})->where($req->only($c->getFillable()))->get();
Am I missing something or are there any other ways to do this?
PS: While debugging the above search code is returning successfully, but the exception happening from somewhere inside Laravel after the prepareResponse call.
Thanks in advance.
return $this->hasOne('App\ModelName', 'foreign_key', 'local_key');
Change the order, put the foreign_key policy_id in front of id
In your Customer Model, you need to use belongsTo method:
public function policy() {
return $this->belongsTo('App\Models\Policy', "policy_id", "id");
}
And In your Policy Model, use hasOne:
public function customer() {
return $this->hasOne('App\Models\Customer', "policy_id", "id");
}
First of all, you placed the wrong params.
$this->belongsTo('App\Models\Policy', "FK", "PK");
public function policy() {
return $this->belongsTo('App\Models\Policy','policy_id', 'id');
}
And for null value of policy_id you can use withDefault();
public function policy() {
return $this->belongsTo('App\Models\Policy','policy_id', 'id')->withDefault([
'name' => 'test'
]);;
}
there's a number of problems there but can you perhaps specify the namespace and the class of both your models - Customer and Policy.
By default, the models you create with php artisan make:model will use the \App namespace e.g. \App\Customer and \App\Policy.
Just double check that.
Also, with regards to the relationship, if the Laravel conventions have been followed you could just:
In the Customer model
public function policy() {
return $this->belongsTo(Policy::class);
}
In the Policy model
public function customer() {
return $this->hasOne(Customer::class);
}
of if a multiple customers can be under one policy
public function customers() {
return $this->hasMany(Customer::class);
}
Good luck

eloquent relation with three tables in laravel 5.4

I have three Models named as Job , JobDetail and Customer.Job has many relation with JobDetail and Customer has many relation with Job.
Below is the structure of tables.
Job
id customer_id jobname
JobDetail
id job_id days
Customer
id name
Below are the models:
class Job extends Model
{
public function job_details()
{
return $this->hasMany('App\JobDetail','job_id','id');
}
}
class Customer extends Model
{
public function customer()
{
return $this->hasMany('App\Job','customer_id','id');
}
}
class JobDetail extends Model
{
//
}
i was trying to execute the below query but its throwing error like Call to undefined relationship [customer] on model [App\Job].
My query :
$data = Job::with(['job_details','customer'])->get();
Can some body suggest me how do i connect these models and get the data ?
Thank You !
You did not specify a relationship for customer in your Job model.
So, something like this should do the trick:
public function customer()
{
return $this->belongsTo('App\Customer','job_id','id');
}

Laravel: saving multiple models at once / json nested input

I am submitting a POST request to my API endpoint using Postman.
In my nested JSON, an artist has one or more albums and each album has one or more songs.
I have two questions:
1) How do I perform nested array validation in Laravel? I am looking for an optimal / standard Laravel way to do so.
2) How do I save multiple models together?
Note: I did create the relationships in my Eloquent models, such as
class Artist extends Eloquent {
public function albums()
{
return $this->hasMany('Album');
}
}
class Album extends Eloquent {
public function songs()
{
return $this->hasMany('Song');
}
}
class Song extends Eloquent {
public function album()
{
return $this->belongsTo('Album');
}
}
class Album extends Eloquent {
public function artist()
{
return $this->belongsTo('Artist');
}
}
1) Use the validator's each method:
$validator = Validator::make(Input::all(), [...rules...]);
$validator->each('albums', [...rules...]);
2) After creating the artist, loop through your albums and call create on the relationship:
$artist = Artist::create(Input::all());
foreach (Input::get('albums') as $album)
{
$artist->albums()->create($album);
}

Get all the attributes related to one Model as JSON

I have this model for Author:
<?php
class Author extends Eloquent {
public function albums()
{
return $this->belongsToMany('Album')->withPivot('city');
}
}
And this model for Album:
<?php
class Album extends Eloquent {
public function artist()
{
return $this->belongsTo('Artist');
}
public function authors()
{
return $this->belongsToMany('Author')->withPivot('city');
}
}
To get a model I can easily do this:
$author = Author::where('name','=','Chester Bennington')->first()->toJson();
and it'll return something like this (as JSON):
{"id":3,"name":"Chester Bennington","created_at":"2014-06-29 16:10:21","updated_at":"2014-06-29 16:10:21"}
See that it won't return the albums related to it. To get the albums I would have to do this: $author->albums->toJson()
Since I'm doing an API and it returns everything as JSON, is there a way to get the model and ALL its attributes without specifying which ones to get??
If you eager load the relationships you want, it'll be included in your JSON:
Author::with('albums')->where('name', 'Chester Bennington')->first()->toJson();