How to get reference table data in Laravel 5.1 - php

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

Related

Laravel hasOne relation with where clause

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

Eloquent relationship in Laravel 6. Can't modify/overwrite relationship attribute

I built a one to one relationship between two Eloquent models and I want to replace an relationship attribute called profile_picture inside my User Eloquent model but I don't know how to do it.
This is a summary of my User model.
class User extends Authenticatable implements JWTSubject{
use Notifiable;
public function profile_picture(){
return $this->hasOne(UserProfilePicture::class);
}
}
And this is a summary of my UserProfilePicture model.
class UserProfilePicture extends Model{
public function user(){
return $this->belongsTo(User::class);
}
}
This is how I pretent to do it in my UserController file.
public function publicUserData($username){
$user = User::where("username", $username)->with("profile_picture")->first();
if($user){
if(!$user->profile_picture){
$user->profile_picture = UserProfilePicture::$defaultUserProfilePicture;
}
return response()->json($user);
}
return response()->json(false);
}
This is $defaultUserProfilePicture static array.
public static $defaultUserProfilePicture = [
"url" => "public/avatars/defaultUserPhoto.jpg",
"size" => 5229
];
I tried to use mutators but looks like it isn't work on relationships attributes.
I found this but doesn't work for me.
Thanks in advance.
You can provides the relation default model with attributes, you may pass an array or Closure to the withDefault method
public function profile_picture(){
return $this->hasOne(UserProfilePicture::class)->withDefault(UserProfilePicture::$defaultUserProfilePicture);
}
Reference: https://laravel.com/docs/7.x/eloquent-relationships#default-models
I solved it, first I put the static array UserProfilePicture::$defaultUserProfilePicture into my database then I do:
$user->setRelation("profile_picture", UserProfilePicture::find(1));
That take one more database request but is the one solution to I have for now.

Eloquent: How to access related model within a withDefault() closure?

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

laravel 5.1 BelongsTo Reverse call

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.

Laravel 5 Eager Loading not working

I look at many search results with this trouble but i can`t get it to work.
The User Model:
<?php namespace Module\Core\Models;
class User extends Model {
(...)
protected function Person() {
return $this->belongsTo( 'Module\Core\Models\Person', 'person_id' );
}
(...)
And the Person Model:
<?php namespace Module\Core\Models;
class Person extends Model {
(...)
protected function User(){
return $this->hasOne('Module\Core\Models\User', 'person_id');
}
(...)
Now, if i use User::find(1)->Person->first_name its work. I can get the Persons relations from the User Model.
But.. User::with('Person')->get() fails with a Call to undefined method Illuminate\Database\Query\Builder::Person()
What im doing wrong? i need a collection of all the users with their Person information.
You have to declare the relationship methods as public.
Why is that? Let's take a look at the with() method:
public static function with($relations)
{
if (is_string($relations)) $relations = func_get_args();
$instance = new static;
return $instance->newQuery()->with($relations);
}
Since the method is called from a static context it can't just call $this->Person(). Instead it creates a new instance of the model and creates a query builder instance and calls with on that and so on. In the end the relationship method has to be accessible from outside the model. That's why the visibility needs to be public.

Categories