information about related models in Laravel - php

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);
}
}

Related

How Can I Use Global Scope in Laravel Query Builder? (No Eloquent Model)

I'm working with too many mysql large views. I don't want to use Eloquent Model for the views.
I created "ViewBalance extends Illuminate\Support\Facades\DB". Everything worked as I wanted.
But i need to set init() method for company scope.
How can I use the global scope without init() method?
ViewModel
<?php
namespace App\Models\Views;
use App\Facades\CoreService;
use Illuminate\Support\Facades\DB;
class ViewBalance extends DB
{
const COMPANY_COLUMN = 'company_id';
const TABLE = 'view_balances';
public static function init()
{
return parent::table(self::COMPANY_COLUMN)
->where(self::COMPANY_COLUMN, CoreService::companyId());
}
}
In Controller
<?php
$data = ViewBalance::init()->get(); // Worked!
I have answered my own question. Because, I don't want to edit my question for more complicate. I want to talk about a solution to this problem.
I added $table_view variable and getView() method in Laravel model. If you want, you can create trait for clean codes.
It can be accessed easily views. Also it is part of the main model.
For example;
Laravel Basic Account Model
class Account extends Model {
protected $table = 'accounts';
protected $table_view = 'view_accounts';
public function getView()
{
return \DB::table($this->table_view)->where('global_scope', 1);
}
}
Laravel Account Controller
class AccountController extends Controller {
public function index()
{
$items = (new Account)->getView()->paginate(20);
}
}
public function scopeActive($query)
{
return $query->where('active', true);
}
or
public function scopeInactive($query)
{
return $query->where('active', false);
}

Laravel 5 - passing variable to relationship model

If I have below models:
class User extends Model{
protected $someDataFromExt = ['taskID0' => 'test', 'taskID1' => 'ting'];
public function tasks() { return $this->hasMany('Task'); }
}
class Task extends Model{
protected $appends = ['ext_data'];
public function user() { return $this->belongsTo('User'); }
public function getExtDataAttribute(){ return $this->external_data; }
}
I would like, when I do: $tasks = auth()->user()->tasks->all(); I want to pass $user->someDataFromExt (based on task ID) to task model, so I later in my $tasks variable I can access:
foreach($tasks as $task){
echo $task->ext_data;
}
Which will return data that was given from user model earlier?
Is this possible? how?
Not completely following why the task data is being stored on the user model, but I think what you’re asking can be achieved via your accessor method on your task model, providing you make the someDataFromExt public:
<?php
class Task extends Model {
public function getExtDataAttribute()
{
return $this->user->someDataFromExt['taskID' . $this->id];
}
}

How to get first row in Laravel relationship

How can i create a method in my model below that consist of first value of pages?
I want my cover method to get he first instance of pages.
Here's my model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
protected $guarded = [];
public function pages()
{
return $this->hasMany('\App\Page');
}
public function cover()
{
//first page of pages here
}
}
Use the first() method on the relationship
public function cover()
{
return $this->pages()->first();
}

Laravel DRY nested eager loading

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?

Laravel Relationships Between Two Models

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');
}
}

Categories