很多时候,我都有理由获得在Eloquent对象上定义的关系的名称。由于Laravel目前不提供任何方法/帮助程序,因此我提出了以下建议:
public static function getRelationshipsForEloquentlModel($eloquentObject) {
$methods = self::getDirectClassMethods($eloquentObject);
$relations = [];
foreach ($methods as $method) {
try {
$reflection = new \ReflectionMethod($eloquentObject, $method);
//filter out non-eloquent relationship methods that expect parameters in
//their signature (else they blow up when they get called below without pars)
$pars = $reflection->getNumberOfParameters();
if ($pars == 0) {
$possibleRelationship = $eloquentObject->$method();
//one of the things we can use to distinctively identify an eloquent
//relationship method (BelongsTo, HasMany...etc) is to check for
//one of the public methods defined in Illuminate/Database/Eloquent/Relations/Relation.php
//(and hope that it is not discontinued/removed in future versions of Laravel :))
if (method_exists($possibleRelationship, "getEager")) {
$relationshipType = get_class($possibleRelationship);
//remove namespace
if ($pos = strrpos($relationshipType, '\\')) {
$relationshipType = substr($relationshipType, $pos + 1);
}
$relations[$method] = $relationshipType;
}
}
} catch (\Exception $ex) {
//Eloquent's save() method will throw some
//sql error because $eloquentObject may be
//an empty object like new App\User (so some NOT NULL db fields may blow up)
}
}
return $relations;
}
辅助类getDirectClassMethods
在下面(由onesimus on official PHP docs comment提供):
public static function getDirectClassMethods($class) {
$array1 = get_class_methods($class);
if ($parent_class = get_parent_class($class)) {
$array2 = get_class_methods($parent_class);
$array3 = array_diff($array1, $array2);
} else {
$array3 = $array1;
}
return ($array3);
}
现在,整个代码清单对我来说是如此繁琐和冗长,至少在所需任务如此简单的情况下如此。没有所有这些冗长的词,是否有更好/更快/更有效的方法来实现这一目标?
答案 0 :(得分:1)
此特征应有帮助
namespace App;
use ErrorException;
use Illuminate\Database\Eloquent\Relations\Relation;
use ReflectionClass;
use ReflectionMethod;
trait RelationshipsTrait
{
public function relationships() {
$model = new static;
$relationships = [];
foreach((new ReflectionClass($model))->getMethods(ReflectionMethod::IS_PUBLIC) as $method)
{
if ($method->class != get_class($model) ||
!empty($method->getParameters()) ||
$method->getName() == __FUNCTION__) {
continue;
}
try {
$return = $method->invoke($model);
if ($return instanceof Relation) {
$relationships[$method->getName()] = [
'type' => (new ReflectionClass($return))->getShortName(),
'model' => (new ReflectionClass($return->getRelated()))->getName()
];
}
} catch(ErrorException $e) {}
}
return $relationships;
}
}
您应该获得一个数组数组,只需将特征添加到任何模型中即可。
class Article extends Model
{
use RelationshipsTrait;
...
}
$article = new Article;
dd($article->relationships());
应该输出
"example" => array:2 [▼
"type" => "BelongsTo"
"model" => "App\Example"
],
"gallery" => array:2 [▼
"type" => "MorphMany"
"model" => "App\Gallery"
]