laravel model static method. it is ok? - laravel

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
protected $dates = ['due_date'];
protected $fillable = ['name', 'project_id'];
public function scopeDueInDays($query,$days)
{
return $query->where('due_date', '>', \Carbon\Carbon::now()
->subDays($days));
}
static public function dueInDays($days)
{
return Task::where('due_date', '>', \Carbon\Carbon::now()
->subDays($days));
}
}
I want to go to method definition on vscode editor.
I can't this with scopeMethod.
Then i create static method. it works. at least until now, fine.
can use static method like below
$task = new Task;
$tasks = $task->dueInDays($day)->get();
$tasks = Task::dueInDays($day)->get();
this way is have problem on using laravel?
is anyone to using static method without scopeMethod?

Related

Why is a observer class not working in model?

I have a Base model that I used to extend in all other Models. I created an observer for it called BaseObserver and registered it at boot method of EventServiceProvider. I have a creating event and would like to put my logic there every time I create a new other Model.
The problem is that the creating method in BaseObserver is not being called. But, when I created a closure for creating in Base model, it worked. What seems to be the problem here?
Base.php
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\Model;
use Jenssegers\Mongodb\Eloquent\SoftDeletes;
class Base extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
// This closure will work but If I commented this out, BaseObserver's creating method won't work
protected static function booted()
{
static::creating(function ($base) {
dd('hellp from base model');
});
}
}
BaseObserver.php
namespace App\Observers;
use App\Models\Base;
class BaseObserver
{
public function creating(Base $base)
{
dd('hello from base obserer');
$base->created_by = auth()->user()?->_id;
}
public function updating(Base $base)
{
dd('hello from base obserer');
$base->updated_by = auth()->user()?->_id;
}
}
EventServiceProvider.php
namespace App\Providers;
use App\Models\Base;
use App\Observers\BaseObserver;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
public function boot()
{
Base::observe(BaseObserver::class);
}
public function shouldDiscoverEvents()
{
return false;
}
}
Team.php
namespace App\Models;
use App\Models\Base;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Team extends Base
{
use HasFactory;
protected $fillable = [
'name',
'leader_id',
'member_ids',
];
}
Result
it has to work
class Base extends Model
{
protected static function booted()
{
static::observe(BaseObserver::class);
}
}

insert an array of data into database with API using laravel 8

I'm new to laravel and just started creation of apis to connect to the database. I'm able to send a single entry at a time to the database, now what i want to do is to pass an array of data to be inserted into the database but don't seem to find my way around
Controller
public function newSaveUser(Request $request) {
$newFood = new Food;
$newFood->name = $request->name;
$newFood->save();
}
Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Food extends Model {
//
public $timestamps = false;
}
Try this here:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Food extends Model
{
//
public $timestamps = false;
protected $fillable = ['name'];
}
and then to insert data:
Food::create([
'name' => $request->get('name')
]);
firstly check the db connection is works or not.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Food extends Model
{
//
public $timestamps = false;
protected $table = "write_table_name_here";
protected $guarded = [];
}
extend model in controller;
$newFood = new Food;
$newFood->name = $request->name;
$newFood->save();

Override Eloquent Relation Create Method

I want to override create method, but with relation, it didn't touch the create method.
There are Two Models:
class User extends Model
{
public function user_detail()
{
return $this->hasOne(UserDetail::class);
}
}
class UserDetail extends Model
{
public static function create(array $attributes = [])
{
//I was trying to do something like
/*
if(isset($attributes['last_name']) && isset($attributes['first_name']))
{
$attributes['full_name']=$attributes['first_name'].' '.$attributes['last_name'];
}
unset($attributes['first_name'],$attributes['last_name']);
*/
Log::debug('create:',$attributes);
$model = static::query()->create($attributes);
return $model;
}
}
When I use UserDetail::create($validated), and there is a log in laravel.log, so I know the code touched my custom create method.
But if I use
$user = User::create($validated);
$user->user_detail()->create($validated);
There is no log in laravel.log, which means laravel didn't touch the create method, then how I supposed to do to override create method under this circumstance?(I'm using laravel 5.7)
Thank you #Jonas Staudenmeir, after I read the documentation, here is my solution.
If the $attributes are not in protected $fillable array, then I do it in the __construct method.
class UserDetail extends Model
{
protected $fillable=['full_name','updated_ip','created_ip'];
public function __construct(array $attributes = [])
{
if (isset($attributes['first_name']) && isset($attributes['last_name'])) {
$attributes['full_name'] = $attributes['first_name'].' '.$attributes['last_name'];
}
parent::__construct($attributes);
}
}
Otherwise, I do it in Observer.
namespace App\Observers;
use App\Models\UserDetail;
class UserDetailObserver
{
public function creating(UserDetail $userDetail)
{
$userDetail->created_ip = request()->ip();
}
public function updating(UserDetail $userDetail)
{
$userDetail->updated_ip = request()->ip();
}
}
Register Observer in AppServiceProvider.
namespace App\Providers;
use App\Models\UserDetail;
use App\Observers\UserDetailObserver;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
UserDetail::observe(UserDetailObserver::class);
}
}
I choose Observer instead of Event&Listener is for easy maintenance.

Relationship Between Mongodb and Mysql databases

I am Trying to get data from mysql and mongodb in laravel framework.I am using HybridRelations to fetch data realated data but I stuck.please help me.
I got Error like that.
Call to undefined relationship [Country] on model [App\Models\State].
Here is my code.
country model;
namespace App;
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Country extends Eloquent
{
protected $connection = 'mongodb';
protected $collection = 'countries';
protected $fillable = [ 'country' ];
public function country()
{
return $this->hasMany(State::class,'country_id');
}
}
my state model:
<?php
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\HybridRelations;
use Illuminate\Database\Eloquent\Model;
class State extends Model
{
use HybridRelations;
protected $connection = 'mysql';
protected $table = 'state';
protected $primaryKey = 'state_id';
protected $fillable = [ 'name','code','status' ];
public function state()
{
return $this->belongsTo(Country::class, '_id');
}
}

Laravel 5.6.17 Model hasOne over multiple tables

I'm quite new to Laravel and now I'm trying to move parts of a former application from a small self written framework into Laravel. The address book is multilingual therefor the table structure is a little more complicated.
db-structure
And this is my source code:
AddressBookController.php
namespace App\Http\Controllers;
use App\AddressBook as AB;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class AddressBookController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$entries = AB::all();
return view('addressBook')->with([
'class' => __CLASS__,
'function' => __FUNCTION__,
'line' => __LINE__,
'entries' => $entries,
]);
}
}
Model AddressBook.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class AddressBook extends Model
{
protected $table = 'address';
protected $primaryKey = 'address_id';
protected $keyType = 'int';
public $incrementing = true;
public $timestamps = false;
protected $searchable = [
'columns' => [
'address.address_surname' => 10,
'address.address_company' => 5,
'address.address_vatid' => 2,
],
];
public function country() {
return $this->hasOne('country', 'country_id', 'country_id');
}
public function addresstype() {
return $this->hasOne('addresstype', 'addresstype_id', 'addresstype_id');
}
}
Model Country.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country extends Model
{
protected $table = 'country';
protected $primaryKey = 'country_id';
protected $keyType = 'int';
public $incrementing = true;
public $timestamps = false;
public function translation() {
return $this->hasOne('translations', 'translations_id', 'translations_id');
}
public function addressbook() {
return $this->belongsTo('address', 'country_id', 'country_id');
}
}
Model AddressType
namespace App;
use Illuminate\Database\Eloquent\Model;
class AddressType extends Model
{
protected $table = 'addresstype';
protected $primaryKey = 'addresstype_id';
protected $keyType = 'int';
public $incrementing = true;
public $timestamps = false;
public function translation() {
return $this->hasOne('translations', 'translations_id', 'translations_id');
}
public function addressbook() {
return $this->belongsTo('address', 'addresstype_id', 'addresstype_id');
}
}
Model Translation.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Translation extends Model
{
protected $table = 'translations';
protected $primaryKey = 'translations_id';
protected $keyType = 'int';
public $incrementing = true;
public $timestamps = false;
public function country() {
return $this->belongsTo('country', 'translations_id', 'translations_id');
}
public function addresstype() {
return $this->belongsTo('addresstype', 'translations_id', 'translations_id');
}
}
The request "$entries = AB::all();" works in general but I get the id's and maybe I'm completely wrong here but I thought that data from foreign keys will be replaced with the respective models (if configured correctly). so my question is:
a. did I make a mistake during configuration and if yes, where exactly is the error?
or
b. is my assumption of replacing id's with objects is completly wrong?
Thanks in advance!
Steve
Laravel Eloquent models do not replace the foreign keys of the active records with the relational data, it only appends a new property with the same name as the method relating the classes and in that property it puts all the Model instances of the resulted query, this ONLY if you access the property, its called Eager Loading.
It is explained here (Ofiicial Documentation)
$addressBook = App\AddressBook::find(1); //this only will return the active record with the id 1 and nothig more.
$addressBook->country; // The property "country" does not exist in the AddressBook Classs but eloquent models will return a "fake" property with the value of the result of the query by the method with the same name (only if the method returns an Eloquent Relation).
This Eloquent behavior is natural, and is a very clever way to minimize the number of queries, Eloquent will never load a relation if there is no need to.
If you want to load a relation in a set the models at the same time that those models are retriving from the db you need to explicitly especify wich relations you want to load.
$addressBook = App\AddressBook::with(['country', 'addresstype', 'anotherRelation'])->get(); // this will retrive all the addressBook models and in each one will attach the relations specified.
[EDITED]
Also you have to place the entire namespace of the related model class in the relation methods so you need to replaced like:
class Translation extends Model
{
protected $table = 'translations';
protected $primaryKey = 'translations_id';
protected $keyType = 'int';
public $incrementing = true;
public $timestamps = false;
// ****** You need to put the entire namespace of the Model class
public function country() {
return $this->belongsTo('App\Country', 'translations_id', 'translations_id');
}

Resources