I'm wondering when to use the fully qualified class name or when to put a use statement on top of the class.
For example:
namespace App;
use Illuminate\Database\Eloquent\Model;
class ImageStatus extends Model {
public function image(): \Illuminate\Database\Eloquent\Relations\BelongsTo {
return $this->belongsTo( \App\Image::class, 'id' );
}
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo {
return $this->belongsTo( \App\User::class, 'id' );
}
}
At the moment I have this piece of code and my PHPStorm tells me Unnecessary fully qualified name. This hint disappears when I change it to:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class ImageStatus extends Model {
public function image(): BelongsTo {
return $this->belongsTo( \App\Image::class, 'id' );
}
public function user(): BelongsTo {
return $this->belongsTo( \App\User::class, 'id' );
}
}
So I'm wondering what the difference is, performance wise, code readability and if one is better than the other.
When you do use SomeNamespace\ClassName than you do not have later append \SomeNamespace to ClassName. So your example should be
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class ImageStatus extends Model {
public function image(): BelongsTo {
return $this->belongsTo(Image::class, 'id' );
}
public function user(): BelongsTo {
return $this->belongsTo(User::class, 'id' );
}
}
Please note that when you are in same namespace, than you do not need to add namespace to class name. When namespace App; then User::class instead of \App\User::class
Related
I have a model called BrandCodeModell :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BrandCodeModell extends Model
{
use HasFactory;
public function brand()
{
return $this->belongsTo(Brand::class, 'brand_id', 'id');
}
public function modell()
{
return $this->belongsTo(Modell::class, 'modell_id', 'id');
}
public function codeModell()
{
return $this->belongsTo(CodeModell::class, 'code_id', 'id');
}
}
And this is Modell relation with Brand Model :
public function modells()
{
return $this->belongsToMany(Modell::class)->using(BrandCodeModell::class)
->withPivot('code_id');
}
When I try too add new modell to database I get this error :
BadMethodCallException
Call to undefined method App\Models\BrandCodeModell::fromRawAttributes()
Here is my controller to save modell to database :
$brand = Brand::where('id', $id)->first();
$brand->modells()->detach();
$modells = collect($request['modells']);
$modells->each(function ($item) use ($brand) {
if (is_null($item['name'])) return;
$mod = Modell::firstOrCreate([
'name' => $item['name'],
'sort' => $item['sort']
]);
$mod_code = $mod->codeModell()->firstOrCreate([
'name' => $item['code']
]);
$brand->modells()->attach($mod->id, [
'code_id' => $mod_code->id
]);
});
In this code, Modell::firstOrCreate and $mod_code = $mod->codeModell()->firstOrCreate will be create successfully but this part of code $brand->modells()->attach($mod->id, ['code_id' => $mod_code->id]); does not work.
Where is the problem ?
Tell me if you need more details
Per the documentation:
Custom many-to-many pivot models should extend the Illuminate\Database\Eloquent\Relations\Pivot class
So your pivot class should look like this:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\Pivot;
class BrandCodeModell extends Pivot
{
//
}
However, unless you're adding additional methods on to the pivot class, there's no need to define it; Laravel will automatically use the appropriate pivot table. Likewise there's probably no need for it to import the HasFactory trait, as entries would be automatically created by related model creation.
in local host i haven't this problem but in linux host in CPannel i receive this error
Class 'App\Service' not found
it's just an example i have same problem in some models..
my relations doesnt work properly in original host but in local host i haven't got any problem
my models:
<?php
namespace App;
use App\Category;
use App\Project;
use App\Service;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $fillable = [
'title', 'parent_id','title_en',
];
public function category(){
return $this->hasMany(Category::class,'parent_id');
}
public function parent(){
return $this->category('parent');
}
public function project(){
return $this->belongsToMany(project::class);
}
public function service(){
return $this->belongsToMany(service::class);
}
}
my controller :
namespace App\Http\Controllers;
use App\Service;
use Illuminate\Http\Request;
class ServiceController extends Controller
{
public function landpage(){
$services=Service::with('cat')->get();
return view('services.index',compact('services'));
}
public function detail($id){
$services=service::with('cat')->findOrFail($id);
return view('service_detail.index',compact('services'));
}
}
ok as i found .. the models are sensitive to capital words..
i changed all of the models to capital words..
App/service => App/Service
and it worked
got a strange scenario here and going to try my best to explain it, i'm basically merging 2 separate systems which are very similar but use different column names.
So, tablea has got one tableb, however tableb is either selected using column id_1 or id_2.
This check is done within a local scope when using the model directly:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Tableb extends Model
{
protected $table = 'tableb';
public function scopeMode(Builder $query, $id)
{
if (env('DEMO_MODE')) {
return $query->where('id1', '=', $id);
}
return $query->where('id2', '=', $id);
}
}
So to using the above model as follows works fine:
Tablea::mode()->first();
However, using this within a relationship then has issues, as the related column name can change, so I must do the same logic within this relationship, but I want to do all of this logic in one place (tableb) to avoid doing it in other relationships:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Tablea extends Model
{
public function Tableb()
{
if (env('DEMO_MODE')) {
return $this->hasOne(Tableb::class, 'id2', 'tableb_id');
}
return $this->hasOne(Tableb::class, 'id1', 'tableb_id');
}
}
Ideas?
An suggestion would be creating a static function on the tableb that returns which id should be used in tablea, something like the following:
(NOTE: I haven't tested the code yet)
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Tableb extends Model
{
protected $table = 'tableb';
public function scopeMode(Builder $query, $id)
{
return $query->where(self::getId(), '=', $id);
}
public static function getId()
{
return env('DEMO_MODE') ? 'id2' : 'id1';
}
}
and then
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Tablea extends Model
{
public function Tableb()
{
return $this->hasOne(Tableb::class, Tableb::getId(), 'tableb_id');
}
}
I'm trying to create a model that has a relationship which is required for the object to be valid. Querying this model should not return any results that are missing this relationship. It seems like global scopes are the best option for this scenario, however I've been unable to make this work. Am I doing something wrong? Perhaps there's a better way?
Here is a simplified version of the model.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Car extends Model
{
protected static function boot()
{
parent::boot();
static::addGlobalScope('has_details', function ($builder) {
$builder->has('details');
});
}
public function details()
{
return $this->hasOne(Details::class);
}
}
And here is a one-to-many relationship method on another model.
public function cars()
{
return $this->hasMany(Car::class);
}
Without the global scope, this code returns all related "cars", including ones without "details". With the global scope, no "cars" are returned. I want this code to only return "cars" with "details".
Thank you.
You have some mistakes at Anonymous Global Scopes declaration:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class Car extends Model
{
protected static function boot()
{
parent::boot();
static::addGlobalScope('has_details', function (Builder $builder) {
$builder->has('details');
});
}
public function details()
{
return $this->hasOne(Details::class);
}
}
You might try eager-loading the relationship, so that the has() inspection will actually see something. (I suspect because the relationship is not loaded, the details relationship is never populated.)
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class Car extends Model
{
protected $with = ['details'];
protected static function boot()
{
parent::boot();
static::addGlobalScope('has_details', function (Builder $builder) {
$builder->has('details');
});
}
public function details()
{
return $this->hasOne(Details::class);
}
}
Im new in yii. I have question about Active record and bussnes logic in models.
I have model and controller:
namespace app\models;
use yii\db\ActiveRecord;
class Photos extends ActiveRecord
{
}
Controller:
namespace app\controllers;
use Yii;
use app\models\Photos;
class PhotosController extends Controller
{
public function actionIndex()
{
$photos = Photos::find()
->where(['userid' => Yii::$app->user->identity->id])
->all();
return $this->render('index', ['photos' => $photos]);
}
}
I want do that in other way:
namespace app\models;
use yii\db\ActiveRecord;
class Photos extends ActiveRecord
{
public function findOneById($id)
{
return Photos::findOne($id);
}
}
And Controller:
namespace app\controllers;
use Yii;
use app\models\Photos;
class PhotosController extends Controller
{
public function actionIndex()
{
$photos = Photos::findByUserId(Yii::$app->user->identity->id);
return $this->render('index', ['photos' => $photos]);
}
}
What is correct way to do this?
Im about fat model, and tiny controller.
The second option is more true, controllers should be small and all business logic should be rendered in models or functional classes