Skip to content

Instantly share code, notes, and snippets.

@xxzefgh
Created December 20, 2016 07:45
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save xxzefgh/3022fee8afa53e45a6b89da3f16b3815 to your computer and use it in GitHub Desktop.
Save xxzefgh/3022fee8afa53e45a6b89da3f16b3815 to your computer and use it in GitHub Desktop.
<?php
namespace App;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class BelongsToMorph extends BelongsTo
{
/**
* The name of the polymorphic relation.
*
* @var string
*/
protected $morphName;
/**
* The type of the polymorphic relation.
*
* @var string
*/
protected $morphType;
public function __construct(Builder $query, Model $parent, $name, $type, $id, $otherKey, $relation)
{
$this->morphName = $name;
$this->morphType = $type;
parent::__construct($query, $parent, $id, $otherKey, $relation);
}
/**
* Add the constraints for a relationship query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Builder $parent
* @param array|mixed $columns
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*'])
{
$table = $this->getParent()->getTable();
$query = parent::getRelationQuery($query, $parent, $columns);
return $query->where("{$table}.{$this->morphType}", '=', $this->morphName);
}
/**
* Get the results of the relationship.
*
* @return mixed
*/
public function getResults()
{
if ($this->getParent()->{$this->morphType} === $this->morphName) {
return $this->query->first();
}
return null;
}
/**
* Get the polymorphic relationship columns.
*
* @param string $name
* @param string $type
* @param string $id
* @return array
*/
protected static function getMorphs($name, $type, $id)
{
$type = $type ?: $name.'_type';
$id = $id ?: $name.'_id';
return [$type, $id];
}
/**
* Define an inverse morph relationship.
*
* @param Model $parent
* @param string $related
* @param string $name
* @param string $type
* @param string $id
* @param string $otherKey
* @param string $relation
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public static function build(Model $parent, $related, $name, $type = null, $id = null, $otherKey = null, $relation = null)
{
// If no relation name was given, we will use this debug backtrace to extract
// the calling method's name and use that as the relationship name as most
// of the time this will be what we desire to use for the relationships.
if (is_null($relation)) {
list($current, $caller) = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$relation = $caller['function'];
}
$morphName = Arr::get(array_flip(Relation::morphMap()), $related, $related);
list($type, $id) = self::getMorphs(Str::snake($name), $type, $id);
$instance = new $related;
// Once we have the foreign key names, we'll just create a new Eloquent query
// for the related models and returns the relationship instance which will
// actually be responsible for retrieving and hydrating every relations.
$query = $instance->newQuery();
$otherKey = $otherKey ?: $instance->getKeyName();
return new BelongsToMorph($query, $parent, $morphName, $type, $id, $otherKey, $relation);
}
}
@kristianharmer
Copy link

@ibi001 where do I put this file and do I need to add any references anywhere?

Thanks in advance,
K...

@kevin1193
Copy link

This is cool. I've used it.

@dwihujianto
Copy link

Thank for this magic brother 👍

@bocanhcam
Copy link

Hi, Thank you for your solution. But i have a problem working with it. I have 4 relations BelongsToMorph and when i use has or whereHas some of them return another relations.
`public function salaryAdvance()
{
return BelongsToMorph::build($this, SalaryAdvance::class, 'mainledgerable');
}

public function tuition()
{
    return BelongsToMorph::build($this, CollectTuitionFee::class, 'mainledgerable');
}

public function fiOther()
{
    return BelongsToMorph::build($this, FiOther::class, 'mainledgerable');
}

public function payrollSlip()
{
    return BelongsToMorph::build($this, PayrollSlip::class, 'mainledgerable');
}`

MainLedger::has('tuition','>=',1)->get();
$rows = MainLedger::where(function($query) use ($request){ $type = $request->type; if ($type){ $query->whereHas('tuition', function($query) use ($type) { $query->where('type',$type); }, '>=', 1); } }) ->orderBy('id','desc');

This code return object of another relations like payrollSlip or salaryAdvance

@manhtlu
Copy link

manhtlu commented Jan 23, 2019

thank you very much !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment