How to achieve this on laravel 5 eloquent - laravel

How can i achieve something like this?
public function getInformation($model) {
$result = $model::with(['province', 'city']);
if($model == 'App\Models\Business') {
$result->with(['businessProvince', 'businessCity']);
}
$result->get();
}
// call the function
$information->getInformation(\App\Models\Business::class);
i'm getting error
Object of class Illuminate\Database\Eloquent\Builder could not be
converted to string
on the sample code above. Any suggestion is really appreciated.

After taking a fourth look $model should be a string, and $result is an Eloquent Builder instance and never an instance of the model class (since a query was started when with was called).
So the $model == 'App\Models\Business' I would change to $model === \App\Models\Business::class but that should not change the outcome.
Are you sure this error comes from this part of the application? Which line specifically?
Original wrong answer.
You are trying to compare the model instance with a string (since $model::with() created a instance of the model class you passed in the $model argument).
You can use the instanceof keyword for comparing an instance with a class name (http://php.net/manual/en/language.operators.type.php).
if($model instanceof \App\Models\Business) {
$result->with(['businessProvince', 'businessCity']);
}

This solved my problem, thank you guys.
public function getInformation($model) {
$result = $model::with(['province', 'city']);
if($model == 'App\Models\Business') {
// my mistake
//$result->with(['businessProvince', 'businessCity']);
$result = $result->with(['businessProvince', 'businessCity']);
}
$result->get();
}

Related

how can I pass parameter to laravel getAttribute when I am appending it

this is my laravel custom accessor which I am appending using
protected $appends = [leave_balances];
public function getLeaveBalancesAttribute() {
// some code
}
I want to pass a parameter when I am calling this accessor like this
public function getLeaveBalancesAttribute($parameter) {
// use $parameter here
}
$payslip = Payslip::find(1);
\Log::debug($payslip->leave_balances("PARAMETER"));
I have searched and found that it is not possible. please can some one provide any solution to this I need to pass this parameter.
you dont append attribute unless you want it to act as an attribute,
you can just create a method since you are calling it like a method
in you Payslip model
public function leaveBalances( $params ) {
return $params
}
then you can use it like
$payslip = Payslip::find(1);
$payslip->leaveBalances("PARAMETER") // which output PARAMETER
If you declare an Attribute, you can only use it like this (following your example:
protected $appends = ['leave_balances'];
public function getLeaveBalancesAttribute()
{
return 'Hi!';
}
$payslip = Payslip::find(1);
$value = $payslip->leave_balances;
dd($value); // This will output string(Hi!)
What you (I think) want is setLeaveBalancesAttribute, so you can pass a value and do whatever you want with it:
public function setLeaveBalancesAttribute($parameter)
{
return $parameter.' Yes!';
}
$payslip = Payslip::find(1);
$payslip->leave_balances = 'It works!';
dd($payslip->leave_balances); // This will output string(It works! Yes!)
But, if you are using Laravel 9+, please do use the new way of defining attributes, it is better.
You can set the attribute $appends in the model where you have the accessor. Something like this:
protected $appends = ['the name of accessor'];
However, it will be in the most, I think in all, the responses or query you do with the model you declare it.
Another options is creating a single instance of the model using the ::find method. For example:
$model_instance = Model::find($id);
$attribute = $model_instance->attribute;
Here is the documentation reference: https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor

Adding methods to Eloquent Model in Laravel

I'm a bit confused how I am to add methods to Eloquent models. Here is the code in my controller:
public function show($id)
{
$limit = Input::get('limit', false);
try {
if ($this->isExpand('posts')) {
$user = User::with(['posts' => function($query) {
$query->active()->ordered();
}])->findByIdOrUsernameOrFail($id);
} else {
$user = User::findByIdOrUsernameOrFail($id);
}
$userTransformed = $this->userTransformer->transform($user);
} catch (ModelNotFoundException $e) {
return $this->respondNotFound('User does not exist');
}
return $this->respond([
'item' => $userTransformed
]);
}
And the code in the User model:
public static function findByIdOrUsernameOrFail($id, $columns = array('*')) {
if (is_int($id)) return static::findOrFail($id, $columns);
if ( ! is_null($user = static::whereUsername($id)->first($columns))) {
return $user;
}
throw new ModelNotFoundException;
}
So essentially I'm trying to allow the user to be retrieved by either user_id or username. I want to preserve the power of findOrFail() by creating my own method which checks the $id for an int or string.
When I am retrieving the User alone, it works with no problem. When I expand the posts then I get the error:
Call to undefined method
Illuminate\Database\Query\Builder::findByIdOrUsernameOrFail()
I'm not sure how I would go about approaching this problem.
You are trying to call your method in a static and a non-static context, which won't work. To accomplish what you want without duplicating code, you can make use of Query Scopes.
public function scopeFindByIdOrUsernameOrFail($query, $id, $columns = array('*')) {
if (is_int($id)) return $query->findOrFail($id, $columns);
if ( ! is_null($user = $query->whereUsername($id)->first($columns))) {
return $user;
}
throw new ModelNotFoundException;
}
You can use it exactly in the way you are trying to now.
Also, you can use firstOrFail:
public function scopeFindByIdOrUsernameOrFail($query, $id, $columns = array('*')) {
if (is_int($id)) return $query->findOrFail($id, $columns);
return $query->whereUsername($id)->firstOrFail($columns);
}
Your method is fine, but you're trying to use it in two conflicting ways. The one that works as you intended is the one in the else clause, like you realised.
The reason the first mention doesn't work is because of two things:
You wrote the method as a static method, meaning that you don't call it on an instantiated object. In other words: User::someStaticMethod() works, but $user->someStaticMethod() doesn't.
The code User::with(...) returns an Eloquent query Builder object. This object can't call your static method.
Unfortunately, you'll either have to duplicate the functionality or circumvent it someway. Personally, I'd probably create a user repository with a non-static method to chain from. Another option is to create a static method on the User model that starts the chaining and calls the static method from there.
Edit: Lukas's suggestion of using a scope is of course by far the best option. I did not consider that it would work in this situation.

Laravel Eloquent belongsTo: "Trying to get property of non-object" when using without echo/die/var_dump

I've just started with Laravel and Eloquent.
In my "Receipt"-model, I try to get information about a relationship.
As long as I'm using var_dump, I get my information.
As soon as I'm just returning the value to use it in a blade view, I get my "Trying to get property of non-object".
<?php
class Receipt extends Eloquent {
public function businesspartner() {
return $this->belongsTo('Businesspartner', 'f_businesspartner_id');
}
public function brand() {
return $this->belongsTo('Brand', 'f_brand_id');
}
public function invoice() {
return $this->belongsTo('Invoice', 'f_invoice_id');
}
public function name() {
$name = '';
$bp = $this->businesspartner()->first();
$name = $bp->salutation; // line 21
$name .= ' ';
$name .= $bp->lastname_company;
return $name;
}
}
The error occurs in line 21.
When I now put a
var_dump($name);die();
before returning, it prints me my name.
What's going wrong here? :(
Regards,
Timo
SOLUTION
As #Jarek Tkaczyk wrote, I was calling the name() method in a loop.
When doing my debug outputs, I got data from my first row.
When getting the error, the code was already processing the second row, where the foreign key was null.
Wrapping the problematic part in if(count($this->businesspartner)) helped.
For more information about that, Jarek linked that post: https://stackoverflow.com/a/23911985/784588

eloquent morphmany relationship - update and/or save

I have seen the similar Q asked here but did not find any suitable answer and hence asking again. If you know any thread please guide me to it,
I have
Model User and Model Property and both have Address
class Address {
protected $fillable = ['address','city','state','zip'];
public function addressable(){
return $this->morphTo();
}
}//Address
class User extends Eloquent {
protected $fillable = ['first_name','last_name', 'title'];
public function address(){
return $this->morphMany('Address', 'addressable');
}
}//User
class Property extends Eloquent {
protected $fillable = ['name','code'];
public function address(){
return $this->morphMany('Address', 'addressable');
}
}//Property
Is there any way to UpdateIfNotCreate type method for address to update as well associate with User/Property?
Taylor Otwell's official answer,
$account = Account::find(99);
User::find(1)->account()->associate($account)->save();
is NOT working as I am getting an exception
message: "Call to undefined method Illuminate\Database\Query\Builder::associate()"
type: "BadMethodCallException"
The way I have solved the issue is as follows:
$data = Input::all();
if($data['id'] > 0){
$address_id = $data['id']; unset($data['id']);
$address = Address::find($address_id)->update($data);
}//existing
else{
$address = new Address($data);
User::find($user_id)->address()->save($address);
}//add new
I could use the different Routes ( PUT to /update{id} and POST to / )
but in my case both new and existing records are coming to same route ( /update )
Can you guys please recommend the better way to go about this?
Thx,
It's pretty straightforward:
// get only applicable fields
$input = Input::only('address','city','state','zip');
// get existing or instantiate new address
$address = Address::firstOrNew($input);
// associate the address with the user
// btw I would rather call this relation addresses if it's morhpmany
User::find($userId)->addresses()->save($address);
Not sure where you got Taylor's answer, but I don't think it was supposed for this case. It couldn't work anyway.

Problems updating using Eloquent

Right now I'm working on my first update function using Eloquent ORM. Trying to follow the docs, I have this in my model:
public function updateAvailability()
{
$this->active = Input::get('available');
$this->activeDetails = Input::get('availableStatus');
$this->save();
}
which returns:
Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
and all of this is being called to in my controller as:
public function updateProfile($id)
{
if(Input::get('type')=='availability'){
$availability = User::find($id)->updateAvailability;
}
$name = str_replace(' ', '', Input::get('name'));
return Redirect::to('people/'.$name);
}
Are there some gaps in my understanding of updating in Eloquent? (I'm sure there are). I would love to use ajax to handle it, but I can't seem to find the right resources to get that working.
SOLVED: $availability = User::find($id)->updateAvailability; needed to be changed to $availability = User::find($id)->updateAvailability();. That's all.

Resources