class ModelRuleHelper

Share how the model rules read models, including the model a call on a model, builder or relation queries.

Unlike upstream, the queried model comes from the named Builder or Relation template, so custom builders with other type parameters, and non-generic builders whose ancestor fixes the model, resolve too.

Constants

private QUERY_METHODS

The model methods that build its queries.

Methods

__construct(ReflectionProvider $reflectionProvider, BuilderHelper $builderHelper, ModelPropertyHelper $modelPropertyHelper, ModelCastHelper $modelCastHelper)

Create a new model rule helper instance.

Type
callerType(MethodCall|StaticCall $node, Scope $scope)

Return the type the method is called on, with a class-string receiver as its object type.

array|null
exactCalledClasses(StaticCall $call, Scope $scope)

Get the exact classes a static call runs on, or null when a subclass could be called instead.

Type|null
queriedModel(ClassReflection $callerClass, Type $callerType)

Return the model a builder, relation or model queries.

bool
buildsPlainQueries(ClassReflection $modelClass)

Determine whether a concrete model builds its queries as the base Model does: through Model's query methods and the base builder, without any global scope.

bool
usesModelMethods(ClassReflection $modelClass, array $methods)

Determine whether the model runs Model's own implementation of each method, which a subclass or trait may override.

bool
isComputedProperty(ClassReflection $modelClass, string $name)

Determine whether reading the property runs a get accessor or a class cast, which can compute it from other attributes, as HasAttributes::transformModelValue() and mutateAttributeForArray() read it.

Expr|null
declaredPropertyDefault(ClassLike $class, string $name)

Get the default a class declares for one of its own properties, from its source.

bool
declaresInheritedMethod(ClassReflection $modelClass, string $methodName)

Determine whether a parent class or interface declares the method, whose name and visibility the model keeps.

bool
isLegacyScopeMethod(ExtendedMethodReflection $method)

Determine whether a model method is a legacy scope: Model::hasNamedScope() finds it by its name, and its first parameter takes the builder, unlike a helper whose name only starts with "scope", such as scopeExistsIn().

string|null
attributedScopeName(ClassReflection $modelClass, ExtendedMethodReflection $method)

Return the name of the attributed scope that can replace a legacy scope method.

void
trackModelSources(ClassReflection $modelClass, Scope $scope)

Track the files a model's property defaults and method bodies come from, for a rule checking the model's class.

Details

at line 75
__construct(ReflectionProvider $reflectionProvider, BuilderHelper $builderHelper, ModelPropertyHelper $modelPropertyHelper, ModelCastHelper $modelCastHelper)

Create a new model rule helper instance.

Parameters

ReflectionProvider $reflectionProvider
BuilderHelper $builderHelper
ModelPropertyHelper $modelPropertyHelper
ModelCastHelper $modelCastHelper

at line 86
Type callerType(MethodCall|StaticCall $node, Scope $scope)

Return the type the method is called on, with a class-string receiver as its object type.

Parameters

MethodCall|StaticCall $node
Scope $scope

Return Value

Type

at line 100
array|null exactCalledClasses(StaticCall $call, Scope $scope)

Get the exact classes a static call runs on, or null when a subclass could be called instead.

Parameters

StaticCall $call
Scope $scope

Return Value

array|null

at line 144
Type|null queriedModel(ClassReflection $callerClass, Type $callerType)

Return the model a builder, relation or model queries.

Parameters

ClassReflection $callerClass
Type $callerType

Return Value

Type|null

at line 162
bool buildsPlainQueries(ClassReflection $modelClass)

Determine whether a concrete model builds its queries as the base Model does: through Model's query methods and the base builder, without any global scope.

Global scopes may add any clause, and boot code can register them, so a model with boot or initialize hooks below Model (found as bootTraits() finds them), #[ScopedBy], a scope in the booted registry or a boot listener is not plain.

Parameters

ClassReflection $modelClass

Return Value

bool

at line 226
bool usesModelMethods(ClassReflection $modelClass, array $methods)

Determine whether the model runs Model's own implementation of each method, which a subclass or trait may override.

Parameters

ClassReflection $modelClass
array $methods

Return Value

bool

at line 238
bool isComputedProperty(ClassReflection $modelClass, string $name)

Determine whether reading the property runs a get accessor or a class cast, which can compute it from other attributes, as HasAttributes::transformModelValue() and mutateAttributeForArray() read it.

Parameters

ClassReflection $modelClass
string $name

Return Value

bool

at line 267
Expr|null declaredPropertyDefault(ClassLike $class, string $name)

Get the default a class declares for one of its own properties, from its source.

Reflection reparses defaults without their positions, and one declaration can hold several properties.

Parameters

ClassLike $class
string $name

Return Value

Expr|null

at line 281
bool declaresInheritedMethod(ClassReflection $modelClass, string $methodName)

Determine whether a parent class or interface declares the method, whose name and visibility the model keeps.

Parameters

ClassReflection $modelClass
string $methodName

Return Value

bool

at line 296
bool isLegacyScopeMethod(ExtendedMethodReflection $method)

Determine whether a model method is a legacy scope: Model::hasNamedScope() finds it by its name, and its first parameter takes the builder, unlike a helper whose name only starts with "scope", such as scopeExistsIn().

Parameters

ExtendedMethodReflection $method

Return Value

bool

at line 311
string|null attributedScopeName(ClassReflection $modelClass, ExtendedMethodReflection $method)

Return the name of the attributed scope that can replace a legacy scope method.

A model method already using that name keeps the legacy scope, which is then the only way to keep the scope's name, as DatabaseNotification's scopeRead() sits beside read().

Parameters

ClassReflection $modelClass
ExtendedMethodReflection $method

Return Value

string|null

at line 329
void trackModelSources(ClassReflection $modelClass, Scope $scope)

Track the files a model's property defaults and method bodies come from, for a rule checking the model's class.

They are not declarations, whose changes alone reanalyze the model's file.

Parameters

ClassReflection $modelClass
Scope $scope

Return Value

void