Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Type Info Laravel Package

symfony/type-info

Symfony TypeInfo extracts and models PHP type information from reflections and type strings. Resolve scalars, objects, enums, generics, lists, and nullable types via TypeResolver, inspect identifiers and constraints, and stringify types like Collection.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require symfony/type-info phpstan/phpdoc-parser
    
    • phpstan/phpdoc-parser is required for resolving raw string types (e.g., @var docblocks).
  2. First Use Case: Resolve a property type from a class:

    use Symfony\Component\TypeInfo\TypeResolver;
    
    $resolver = TypeResolver::create();
    $type = $resolver->resolve(new \ReflectionProperty(MyClass::class, 'propertyName'));
    echo (string) $type; // Outputs: e.g., "int|null"
    
  3. Key Entry Points:

    • TypeResolver: Resolves types from Reflection* objects or strings.
    • Type factories: Build types programmatically (e.g., Type::nullable(Type::int())).
    • TypeIdentifier: Check type compatibility (e.g., TypeIdentifier::OBJECT).

Implementation Patterns

1. Resolving Types from Reflection

Use TypeResolver to extract types from PHP reflection objects:

$resolver = TypeResolver::create();
$propertyType = $resolver->resolve(new \ReflectionProperty(User::class, 'email'));
// Returns: Type instance for `string|null` (if nullable).

Common Reflection Sources:

  • Properties (ReflectionProperty)
  • Methods (ReflectionMethod)
  • Parameters (ReflectionParameter)
  • Classes (ReflectionClass)

Example: Method Return Type

$method = new \ReflectionMethod(User::class, 'getFullName');
$returnType = $resolver->resolve($method->getReturnType());

2. Building Types Programmatically

Construct complex types using static factories:

// Nullable int
$type = Type::nullable(Type::int());

// Generic collection (e.g., `Collection<int>`)
$type = Type::generic(Type::object(Collection::class), Type::int());

// Array shape (e.g., `array{string: int}`)
$type = Type::arrayShape([
    'name' => Type::string(),
    'age'  => Type::int(),
]);

Use Case: Define expected types for validation or API contracts.


3. Type Validation with isSatisfiedBy

Check if a type meets custom conditions:

$type->isSatisfiedBy(fn (Type $t) =>
    $t->isIdentifiedBy(TypeIdentifier::STRING) &&
    !$t->isNullable()
);

Example: Ensure a property is a non-nullable string:

$resolver->resolve(new \ReflectionProperty(User::class, 'username'))
    ->isSatisfiedBy(fn (Type $t) => $t->isIdentifiedBy(TypeIdentifier::STRING) && !$t->isNullable());

4. Integration with DocBlocks

Resolve types from PHPDoc annotations:

$resolver = TypeResolver::create();
$type = $resolver->resolve('@var string|null'); // From docblock

Use Case: Validate runtime types against docblock declarations.


5. Caching for Performance

Use TypeContextFactory with caching for repeated resolutions:

$factory = new \Symfony\Component\TypeInfo\TypeContextFactory();
$context = $factory->createFromReflectionClass(new \ReflectionClass(User::class));
$cachedResolver = new \Symfony\Component\TypeInfo\TypeResolver($context);

When to Use: In performance-critical paths (e.g., request validation).


6. Handling Generics and Collections

Resolve generic types (e.g., ArrayObject<string>):

$type = Type::generic(
    Type::object(ArrayObject::class),
    Type::string()
);

Use Case: Type-checking collections in frameworks like Symfony’s Collection.


7. String Conversion for Debugging

Cast types to strings for logging/debugging:

echo (string) Type::list(Type::int()); // Outputs: "int[]"

Use Case: Displaying types in error messages or API responses.


Gotchas and Tips

1. Nullable Types

  • Gotcha: Type::nullable(Type::nullable(Type::int())) is redundant—Type::nullable() is idempotent.
  • Fix: Use Type::nullable(Type::int()) directly.

2. Reflection Class Loading

  • Gotcha: Resolving types for classes in other namespaces may fail if autoloading is misconfigured.
  • Fix: Ensure composer dump-autoload is run or use ClassLoader::addPsr4().

3. DocBlock Parsing

  • Gotcha: Complex docblocks (e.g., @template-extends) may not resolve correctly.
  • Fix: Use phpstan/phpdoc-parser and ensure docblocks are properly formatted.

4. Performance with Caching

  • Tip: Cache TypeContext for classes/methods to avoid repeated parsing:
    $context = $factory->createFromReflectionClass(new \ReflectionClass(User::class));
    $resolver = new TypeResolver($context);
    
  • When: Useful in loops or high-traffic endpoints.

5. Type Aliases

  • Gotcha: Custom type aliases (e.g., @template-extends) require phpstan/phpdoc-parser.
  • Fix: Install the parser and ensure aliases are defined in docblocks.

6. Backed Enums

  • Gotcha: Interfaces extending BackedEnum may be misclassified as enums.
  • Fix: Use Type::enum() explicitly or update to Symfony 7.3.3+.

7. Array vs. List Types

  • Gotcha: Type::list() and Type::array() behave differently:
    • list: Homogeneous (e.g., int[]).
    • array: Heterogeneous (e.g., array{string, int}).
  • Fix: Use Type::arrayShape() for strict key-value pairs.

8. Debugging Type Resolutions

  • Tip: Log resolved types to debug issues:
    $type = $resolver->resolve($property);
    \Log::debug('Resolved type:', ['type' => (string) $type]);
    

9. Extension Points

  • Custom Resolvers: Extend TypeResolver to support custom type sources (e.g., database schemas).
  • Type Identifiers: Add custom identifiers via TypeIdentifier::class.

10. PHP 8.4+ Features

  • Tip: Leverage PHP 8.4’s array{...} syntax for stricter type hints:
    function process(array{string $name, int $age} $user) { ... }
    
  • Resolution: TypeInfo automatically resolves these to ArrayShapeType.

11. Common Pitfalls

Issue Solution
TypeResolver returns null Ensure phpstan/phpdoc-parser is installed.
Generic types not resolved Verify class names are fully qualified.
Docblock parsing fails Simplify docblocks or update dependencies.
Performance issues Cache TypeContext instances.

12. Testing

  • Tip: Mock TypeResolver in unit tests:
    $mockResolver = $this->createMock(TypeResolver::class);
    $mockResolver->method('resolve')->willReturn(Type::string());
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata