I know its bit late, but I have been visiting this question multiple times so thought to share my observations to help those who visits this question in future.
Here is the method i used to extract the relationships from an eloquent model class.
/**
*
* Returns all the relationship methods defined
* in the provided model class with related
* model class and relation function name
*
* @param string $modelClass exampe: App\Models\Post
* @return array $relattions array containing information about relationships
*/
protected function getModelRelationshipMethods(string $modelClass)
{
//can define this at class level
$relationshipMethods = [
'hasMany',
'hasOne',
'belongsTo',
'belongsToMany',
];
$reflector = new ReflectionClass($modelClass);
$path = $reflector->getFileName();
//lines of the file
$lines = file($path);
$methods = $reflector->getMethods();
$relations = [];
foreach ($methods as $method) {
//if its a concrete class method
if ($method->class == $modelClass) {
$start = $method->getStartLine();
$end = $method->getEndLine();
//loop through lines of the method
for($i = $start-1; $i<=$end-1; $i++) {
// look for text between -> and ( assuming that its on one line
preg_match('~\->(.*?)\(~', $lines[$i], $matches);
// if there is a match
if (count($matches)) {
//loop to check if the found text is in relationshipMethods list
foreach ($matches as $match) {
// if so add it to the output array
if (in_array($match, $relationshipMethods)) {
$relations[] = [
//function name of the relation definition
'method_name' => $method->name,
//type of relation
'relation' => $match,
//related Class name
'related' => (preg_match('/'.$match.'\((.*?),/', $lines[$i], $related) == 1) ? $related[1] : null,
];
}
}
}
}
}
}
return $relations;
}
If you dd() or dump() the returned $relations for the App/Post model, The output will be something like this
^ array:3 [
0 => array:3 [
"method_name" => "user"
"relation" => "belongsTo"
"related" => "User::class"
]
1 => array:3 [
"method_name" => "tag"
"relation" => "belongsToMany"
"related" => "Tag::class"
]
2 => array:3 [
"method_name" => "comments"
"relation" => "hasMany"
"related" => "Comment::class"
]
]
$relations
, as you pointed out. – Cheryle