There is a BelongsTo relationship with Client model in my Invoice model. Both models have an email field, but Client represents detailed information when it exists.
Here is how I get a list:
$invoices = Invoice::with('client');
and I use $invoice->client-> when represent information. I need to set $invoice->client->email into $invoice->email in case if there's no client found. ->withDefault() method works fine, but I can't get a real client's email, which is exist in Invoice model.
Here is my relation:
class Invoice extends Model {
/**
* Get an invoice client.
*/
public function client() {
return $this->belongsTo('App\Client', 'email', 'email')->withDefault(function ($client) {
$client->email = $invoice->email; // How can I get an invoice email?
});
}
version: Laravel 5.5
You've said some invoices do not have a client and you want to email from the current model and not parent one. Use $this in the closure to access to the Invoice model properties:
return $this->belongsTo('App\Client', 'email', 'email')->withDefault(function ($client) {
$client->email = $this->email;
});
But it doesn't work with eager loading. In this case, you can do this by using the optional() helper:
optional($invoice->client)->email ?? $invoice->email
Or you could create an accessor in Invoice model:
public function getAnyEmailAttribute()
{
return optional($this->client)->email ?? $this->email;
}
And use it:
$invoice->anyEmail
Related
I have a model called RealEstate, this model has a relation with another model called TokenPrice, I needed to access the oldest records of token_prices table using by a simple hasOne relation, So I did it and now my relation method is like following:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class RealEstate extends Model
{
public function firstTokenPrice(): HasOne
{
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
}
By far it's fine and no complexity. But now, I need to involve another relation into firstTokenPrice.
Let me explain a bit more:
As my project grown, the more complexity was added it, like changing firstTokenPrice using by a third table called opening_prices, so I added a new relation to RealEstate called lastOpeningPrice:
public function lastOpeningPrice(): HasOne
{
return $this->hasOne(OpeningPrice::class)->latestOfMany();
}
So the deal with simplicity of firstTokenPrice relation is now off the table, I want to do something like following every time a RealEstate object calls for its firstTokenPrice:
Check for lastOpeningPrice, if it was exists, then firstTokenPrice must returns a different record of token_price table, otherwise the firstTokenPrice must returns oldestOfMany of TokenPrice model.
I did something like following but it's not working:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class RealEstate extends Model
{
public function lastOpeningPrice(): HasOne
{
return $this->hasOne(OpeningPrice::class)->latestOfMany();
}
public function firstTokenPrice(): HasOne
{
$lop = $this->lastOpeningPrice;
if ($lop) {
TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount); // this is just a helper function that inserts a new token price into `token_prices` table, if there was none exists already with selected amount
return $this->hasOne(TokenPrice::class)->where('amount', $lop->amount)->oldestOfMany();
}
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
}
I have checked the $this->hasOne(TokenPrice::class)->where('amount', $lop->amount)->oldestOfMany() using by ->toSql() method and it returns something unusual.
I need to return a HasOne object inside of firstTokenPrice method.
You can use ofMany builder for that purpose:
public function firstTokenPrice(): HasOne
{
$lop = $this->lastOpeningPrice;
if ($lop) {
TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount); // this is just a helper function that inserts a new token price into `token_prices` table, if there was none exists already with selected amount
return $this->hasOne(TokenPrice::class)->ofMany([
'id' => 'min',
], function ($query) use ($lop) {
$query->where('amount', $lop->amount);
});
}
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
I used ->oldest() with a custom scope called amounted in TokenPrice model:
class TokenPrice extends Model
{
public function scopeAmounted(Builder $query, OpeningPrice $openingPrice): Builder
{
return $query->where('amount', $openingPrice->amount);
}
/....
}
And then changed my firstTokenPrice
public function firstTokenPrice(): HasOne
{
$lop = $this->lastOpeningPrice;
if ($lop) {
TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount);
return $this->hasOne(TokenPrice::class)->amounted($lop)->oldest();
}
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
It's working, but I don't know if it's the best answer or not
I have a Laravel 5.5 application and I have the following models.
Jobs
JobSheets
Users
I have a relation on my Users model
public function jobs() {
$this->hasMany('App\Job','user_id')->with('jobSheets');
}
I have a relation on my Jobs model
public function jobSheets() {
$this->belongsToMany('App\JobSheet','jobs_jobsheets','job_id','sheet_id');
}
I'm trying to return all my current logged in users' jobs with the latest job sheet.
A job can have many job sheets but I only want to return the latest.
I've tried in my controller
return Auth::user()->jobs;
However that returns all the jobs sheets against the job.
I've also tried creating another method on my job model.
public function latestJobsheet()
{
return $this->jobsheets->first();
}
and amending my jobs method on the user model to:
public function jobs() {
$this->hasMany('App\Job','user_id')->with('latestJobsheet');
}
but I get the following error:
Call to undefined method
Illuminate\Database\Query\Builder::addEagerConstraints()
You could split the BelongsToMany relationship and add a model for the pivot table (jobs_jobsheets):
class Job {
public function latestJobSheetPivot() {
return $this->hasOne(App\JobSheetPivot::class)->orderBy('sheet_id', 'DESC');
}
}
class JobSheetPivot {
protected $table = 'jobs_jobsheets';
public function jobSheet() {
return $this->belongsTo(App\JobSheet::class);
}
}
class User {
public function jobs() {
return $this->hasMany(App\Job::class)->with('latestJobSheetPivot.jobSheet');
}
}
Assuming your jobs_jobsheets table contains an id column it would probably be best to order the jobSheets returned from newest to oldest.
Here's what that would look like:
public function jobSheets()
{
$this->belongsToMany('App\JobSheet','jobs_jobsheets','job_id','sheet_id')->orderBy('id', 'DESC');
}
If you want to limit the number of results returned you can chain ->limit($num_results) to the end of the belongsToMany method
You can override the $with property on your Job model and have it eager load the relation latestJobsheet. From there, when you access the jobs relation on your User model, you should have the latest job sheet available to you. How you determine the latest job sheet is a separate matter.
What i know:
$this->$parent->childs(); //we get childs data
what i want to know how:
$this->child->find($id)->parent(); //how to get childs parent without including model in controller | by just using eloquent
heres my sample code of employee and employeeDependent model:
trait EmployeeRelationships{
public function dependents(){
return $this->hasMany(\App\DB\EmployeeDependent\EmployeeDependent::class);
}
}
trait EmployeeDependentRelationships{
/**
* #return mixed
*/
public function employee(){
return $this->belongsTo(\App\DB\Employee\Employee::class, 'employee_id');
}
}
If you want to get the reverse of a BelongsTo relationship you need to specify the inverse of the relationship on the corresponding model. For example:
Employee Class
class Employee extends Model
{
public dependents()
{
return $this->hasMany(Dependant::class);
}
}
Dependent Class
class Dependent extends Model
{
public employee()
{
return $this->belongsTo(Employee::class, 'employee_id');
}
}
With these relationships defined you can then access the relevant models by calling the appropriate methods like so:
$dependents = Employee::first()->dependents; // Returns an eloquent collection
$employee = Dependent::first()->employee; // Returns a model of type Employee
Note that in this example using the first() method to grab a model, you can can do this with any object of the correct type.
In my database, i have two tables notification and alertFrequency. The notification has field id and website_url and the alert frequency has id and notification_id. Both tables has models which is one to many. The notification can have one or many alertFrequency.
class Notification extends Model {
public function alertFrequencies() {
return $this - > belongsToMany('AlertFrequency::class');
}
}
namespace App;
use Illuminate\ Database\ Eloquent\ Model;
class AlertFrequency extends Model {
protected $table = 'alertFrequencies';
public function notification() {
return $this - > belongsTo(Notification::class);
}
}
in the notification model, i wrote a function called alert, that will give me the laastest alert associated with a specific websie.
public function alert(){
$alert_frequency = AlertFrequency::find('notification_id')->first();
$o_notification = $this->alertFrequencies()->where('notification_id',$alert_frequency->id)
->select('created_at')->orderBy('created_at')->first();
if($alert_frequency ==null){
return false;
}
return created_at;
}
Is this a right way to extract the data? i would appreciate any suggestions and helps?
Notification hasMany AlertFrequency
public function alertFrequencies(){
return $this->hasMany('App\AlertFrequency');
}
and,
$alert_frequency = AlertFrequency::with('notification')->orderBy('created_at','desc')->first();
loads the latest AlertFrequency along with it's notification.
See One to Many relationship and Eager loading in documentation.
to get laastest alert associated with a specific websie with url $website_url.
Notification::where('website_url', $website_url)->orderBy('created_at')->first();
hasMany relation :
public function alertFrequencies(){
return $this->hasMany('App\AlertFrequency','notification_id');
}
I created a Model Account with accountgroup_id which refer from Account_group Model. Then I call it from route like this
Route::get('test', function () {
return \App\Account::get()->account_group;
});
Account Model has belogsto Relationship with Account_group
class Account extends Model
{
protected $fillable = ['accountgroup_id', 'accountno', 'accountname','address','contactno'];
public function account_group()
{
return $this->belongsTo('App\Account_group');
}
}
Account_group Model has hasMany relationship with Account
class Account_group extends Model
{
protected $fillable =['name','under'];
public function account()
{
return $this->hasMany('App\Account','accountgroup_id');
}
}
But after calling the route; I got following error.
Undefined property:
Illuminate\Database\Eloquent\Collection::$account_group
First, the second class should be named AccountGroup.
And reading the error carefully will give you a clue as to what's up - \App\Account::get() returns a collection of Account objects, each of which will have an AccountGroup. So you need to choose which specific Account you want, then you'll be able to access the account_group property on it:
\App\Account::find(1)->account_group; // get Account with ID 1
\App\Account::first()->account_group; // get the first Account record
My issue solved by calling Account with account group
\App\Account::with('account_group')->get();