Extending Eloquent model with different model - php

<?php
class Page extends Eloquent {
}
class Article extends Page {
function __construct($attributes = []) {
parent::__construct($attributes);
$this->where('type', 'article');
}
}
$articles = Article::all();
// SELECT * FROM pages WHERE type = 'article'
The page table has many types of data, I want to separate these data by model class, I tried the above query but where() function isn't even being called in __constructor()

You simply want implement scope in Model. So check Query Scope but It must be defined in the model class. If you want a seperate class that uses that scope as the basis for querying check out global scope. https://softonsofa.com/laravel-how-to-define-and-use-eloquent-global-scopes/

<?php
class Page extends Eloquent {
}
class Article extends Page {
function __construct($attributes = []) {
if($attributes) {
$attributes['type'] = 'article';
}
parent::__construct($attributes);
}
public function newQuery() {
return parent::newQuery()->where('type', 'article');
}
}
$articles = Article::all();
// SELECT * FROM pages WHERE type = 'article'

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

Touching Eloquent model via polymorphic relationship

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

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 orm database query inside model function

I am new in Laravel. I want to make some custom functions in models which is related to database query.
Class A Extends Controller{
public function view(){
B::get_user();
}
}
Class B Extends Model{
protected $table = "user";
public function get_user(){
//Here is my database query
}
}
How can I use database query in get_user() function? I know this method:
B::table('user')->get();
You can define query scopes for adding the query on the model as:
public function scopeUser($query)
{
return $query->where('some_field', 'some_value');
}
Then you can use it in you controller as:
B::user()->get();
Docs

information about related models in Laravel

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

Categories