I didn't know how to ask the question so, the question is not as clear as the description. But here it goes.
I want to query the parent Model, by quering the child Model. Here is the basic Models:
//Gig.php
class Gig extends Eloquent
{
public function gigable()
{
return $this->morphTo('profile');
}
}
//Band.php
class Band extends Eloquent {
public function gigs()
{
return $this->morphMany('Gig','profile');
}
}
//Musician.php
class Musician extends Eloquent {
public function gigs()
{
return $this->morphMany('Gig','profile');
}
}
Now, I know I can do something like this:
Gig::find(1)->gigable
Is there a way that I can retrieve gigables in one query
and for example for my api I can return all the gigable at once.
Something like:
Gig::where('id','>',1)->gigable
I know thats doesn't work.
Such as in reverse of this I can do something like,
Band::with('gigs')->where('created_at','<',Carbon::now())->get();
Use as follows
//Gig.php
class Gig extends Eloquent {
public function gigable()
{
return $this->morphTo();
}
}
//Band.php
class Band extends Eloquent {
public function gigs()
{
return $this->morphMany('Gig','gigable');
}
}
//Musician.php
class Musician extends Eloquent {
public function gigs()
{
return $this->morphMany('Gig','gigable');
}
}
Then you will be able to get the gigs this way:
$band = Band::with('gigs')->where('created_at','<',Carbon::now())->get();
$gigs = $band->gigs;
If this is what you wanted... your question is unclear
Related
Laravel 5.7. I have two models, Foo and Content. Their relationship is polymorphic because Content can also be related to other models:
class Foo extends Model
{
public function contents()
{
return $this->morphToMany('App\Content');
}
}
class Content extends Model
{
use LastModified;
public function foos()
{
return $this->morphedByMany('App\Foo');
}
}
I want to touch the Foo model whenever the Content model is updated. So I use a LastModified trait for the Content model:
trait LastModified
{
protected static function bootLastModified()
{
static::updating(function ($model) {
static::updateLastModified($model);
});
}
protected static function updateLastModified($model)
{
$foos = $model->foos;
if (count($foos) > 0) {
foreach ($foos as $foo) {
$foo->touch();
}
}
}
}
My problem is that $model->foos returns the correct Foo models, but with the wrong ids. Instead of the Foo's own model id, each Foo has the id of the pivot table row. This means that the wrong Foo row is touched.
Laravel has built-in functionality for touching parent timestamps.
On the content model, you can add a property telling which relationships should be touched when the given model is updated.
The following should work:
class Content extends Model
{
protected $touches = ['foos'];
public function foos()
{
return $this->morphedByMany('App\Foo');
}
}
Edit: Since you are using a static updated event you should manually call $model->touchOwners() from the static::updated
Suppose I got a model with a few relations:
class Author extends Model
{
public function shortStories()
{
return $this->hasMany(ShortStory::class);
}
public function essays()
{
return $this->hasMany(Essay::class);
}
public function books()
{
return $this->hasMany(Book::class);
}
}
Now suppose I got two more models that want to eager load this model with its relations:
class Publisher extends Model
{
public function scopeWithAuthor($query)
{
$query->with('author.shortStories', 'author.essays', 'author.books');
}
}
class Reviewer extends Model
{
public function scopeWithAuthor($query)
{
$query->with('author.shortStories', 'author.essays', 'author.books');
}
}
Problem - if the relations of author change I now need to reflect this in multiple locations.
My question - how do I achieve this in DRY style?
I know that I could add a protected $with to the Author class but then it would always load the relation, not just when required.
With that in mind, one solution I have come up with is to extend the Author model like so:
class AuthorWithRelations extends Author
{
protected $with = ['shortStories', 'essays', 'books'];
}
This then allows me to refactor the scopes of the other models like so:
class Publisher extends Model
{
public function scopeWithAuthor($query)
{
$query->with('authorWithRelations');
}
}
class Reviewer extends Model
{
public function scopeWithAuthor($query)
{
$query->with('authorWithRelations');
}
}
This works well enough but really I was wondering if Laravel provides a better / inbuilt approach to this?
Hello I´m writing an API and I want to display more information about the related model.
Routes.php
Route::resource('makes', 'MakesController');
MakesController.php
class MakesController extends Controller
{
public function index()
{
$data = Make::all();
return response()->json($data);
}
}
This returns only information about the makes (id, name)
but how can I display also how many models has each make?
I have defined these two models
class Make extends Model
{
public function models()
{
return $this->hasMany('App\CarModel');
}
}
class CarModel extends Model
{
public function make()
{
return $this->belongsTo('App\Make');
}
}
You can define $visible field in the Make model's class like this:
protected $visible = ['models'];
This will automatically appends the related model's array to array/json.
You can also use an optional way with makeVisible method:
class MakesController extends Controller
{
public function index()
{
$data = Make::all();
return response()->makeVisible('models')->json($data);
}
}
I have the following problem,
I have four models:
MainArea |Institute|institute_level|students with the following reations:
class MainArea extends Model
{
public function institute(){
return $this->belongsTo('\App\Institute');
}
public function places(){
return $this->hasMany('\App\Place');
}
}
class Institute extends Model
{
public function insLevel(){
return $this->hasMany('\App\InstituteLevel');
}
}
class InstituteLevel extends Model
{
public function students(){
return $this->hasMany('\App\Student','applying_level');
}
}
class Student extends Model
{
public function instituteLevel(){
return $this->belongsTo('\App\InstituteLevel','institute_level_id');
}
public function place(){
return $this->belongsTo('\App\Place');
}
}
Now, I want to get all areas with the count of students registered in it, in the same institute? it should be something like this.
$areas=\App\MainArea::withCount('institute.insLevel.students')->where('institute_id',$id)->get();
Any suggestions ?
Unfortunately, "withCount()" doesn't support nested relationships as of Laravel 5.2.
Here's the comment from the contributor in a Github Pull Request.
I am struggling with working with relationships right now and would like some help as for how to make this relationship work. I am using Laravel.
Lets say you have a staff model that looks like so:
Staff.php
class Staff extends \Eloquent {
protected $fillable = [];
public function status()
{
return $this->belongsTo('Staff_status');
}
}
The database table for the staff is as follows:
Table Name: staff
Fields: id, staffer_name, status_id
You also have a staff status model represented below:
Staff_statuses.php
class Staff_status extends Eloquent {
public function staff()
{
return $this->hasMany('Staff');
}
}
You also have a staff database table like so:
Table Name: staff_statuses
Fields: id, status_name
However when I try and load the staff controller index method it says class Staff_status is not found.
Any idea why?
You have used Staff_statuses.php as the name of your model but you are using Staff_status in the class name and thus you are calling it using Staff_status from your controller as well. This is the problem.
Change the file name to match the class name. For example, use something like this:
// StaffStatus.php
class StaffStatus extends Eloquent{
protected $table = 'staff_statuses';
public function staff()
{
return $this->hasMany('Staff');
}
}
// Staff.php
class Staff extends Eloquent {
protected $table = 'staff';
protected $fillable = [];
public function status()
{
return $this->belongsTo('StaffStatus');
}
}
In the controller you may use something like this:
$staffStatus = StaffStatus::all();
$staff = Staff::all();
namespace App;
use Illuminate\Database\Eloquent\Model;
class Photo extends Model
{
public function imageable()
{
return $this->morphTo();
}
}
class Staff extends Model
{
public function photos()
{
return $this->morphMany('App\Photo', 'imageable');
}
}
class Product extends Model
{
public function photos()
{
return $this->morphMany('App\Photo', 'imageable');
}
}