jeudi 25 octobre 2018

What is the most efficient way to get the relationship method names on an Laravel Eloquent object?

A lot of time, I've had reasons to get the names of the relationships defined on an Eloquent object. Since Laravel currently provides no way/helper to do this, I came up with the below:

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;
    }

And the helper class getDirectClassMethods is below (courtesy of 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);
    }

Now this whole code listing looks so cumbersome and verbose to me, at least when the desired task is such a simple one. Is there a better/faster/more efficient way of achieving this without all these verbosity?



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire