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

Linter Laravel Package

memio/linter

Memio Linter provides a set of Memio Validator constraints to lint Memio models for syntax and structural issues. Use it standalone or as part of the Memio code generator to validate arguments, methods, contracts, objects, files, and collections.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel Integration (If Using Memio)

  1. Install Dependencies:
    composer require memio/linter memio/validator memio/model
    
  2. Basic Linter Usage (via Memio’s Build class):
    use Memio\Build;
    
    $models = Build::models()->fromDirectory(app_path('Models'));
    $validator = Build::linter()->validate($models);
    
    if ($validator->hasErrors()) {
        foreach ($validator->errors() as $error) {
            echo "Error: {$error->message()}\n";
        }
        exit(1);
    }
    
  3. First Use Case:
    • Run the linter locally on a subset of models to verify constraints (e.g., php artisan memio:linter if a custom command exists).
    • Integrate into CI/CD (e.g., GitHub Actions) to block PRs with syntax errors.

Laravel-Specific Quickstart (Non-Memio)

If not using Memio, extract constraints manually:

use Memio\Validator\Constraint\MethodCannotBeAbstractAndHaveBody;
use Memio\Validator\ModelValidator\MethodValidator;

// Example: Validate a Laravel model class
$reflectionClass = new ReflectionClass(App\Models\User::class);
$methodValidator = new MethodValidator(
    new ArgumentValidator(),
    new CollectionValidator()
);
$methodValidator->add(new MethodCannotBeAbstractAndHaveBody());

$errors = $methodValidator->validate($reflectionClass);

Implementation Patterns

Core Workflows

  1. Constraint-Based Validation:

    • Pattern: Chain validators for different model aspects (e.g., methods, contracts, arguments).
    • Example:
      $validator = new Validator();
      $validator->add(new ObjectValidator(/* ... */));
      $validator->add(new ContractValidator(/* ... */));
      
    • Laravel Adaptation: Use traits to wrap Memio validators for Eloquent models:
      trait MemioLinterTrait {
          public function validateWithMemioLinter() {
              $validator = new Validator();
              // Add constraints...
              return $validator->validate(new ReflectionClass($this));
          }
      }
      
  2. CI/CD Integration:

    • Pattern: Run linter as a pre-commit hook or GitHub Actions step.
    • Example Workflow:
      - name: Memio Linter
        run: |
          php vendor/bin/memio linter --directory=app/Models --fail-on-error
      
    • Laravel Tip: Combine with phpstan for layered validation:
      - name: PHPStan + Memio Linter
        run: |
          vendor/bin/phpstan analyse --level=max
          vendor/bin/memio linter --fail-on-error
      
  3. Custom Constraints:

    • Pattern: Extend existing constraints for Laravel-specific rules.
    • Example: Add a constraint to validate Eloquent fillable fields:
      use Memio\Validator\Constraint\ConstraintInterface;
      
      class FillableFieldsCannotBePrivate implements ConstraintInterface {
          public function validate($value) {
              // Logic to check fillable fields in Eloquent models
          }
      }
      

Integration Tips

  • For Memio Users:
    • Use Build::linter() for zero-config validation of Memio-generated models.
    • Leverage Memio’s phpspec tests to document expected behavior.
  • For Laravel (Non-Memio):
    • Partial Integration: Use individual constraints (e.g., MethodCannotBeAbstractAndHaveBody) via reflection.
    • Hybrid Approach: Combine with Laravel’s make:model to validate new models:
      // In a service provider
      Model::creating(function ($model) {
          $validator = new Validator();
          $validator->add(new ObjectValidator(/* ... */));
          if ($validator->validate(new ReflectionClass($model))->hasErrors()) {
              throw new \RuntimeException("Model validation failed");
          }
      });
      

Gotchas and Tips

Pitfalls

  1. Memio Dependency Lock-In:

    • Gotcha: Constraints assume Memio’s model structure (e.g., contracts, collections). Using this with vanilla Laravel models will fail.
    • Fix: Abstract constraints into generic PHP validators (e.g., using ReflectionClass).
  2. False Positives in Laravel:

    • Gotcha: Constraints like CollectionCannotHaveNameDuplicates may flag Eloquent relationships incorrectly.
    • Fix: Whitelist known collections or override constraints:
      $validator->ignore(new CollectionCannotHaveNameDuplicates());
      
  3. Performance Overhead:

    • Gotcha: Running the full linter suite on large codebases can be slow.
    • Fix: Validate incrementally (e.g., only changed files in CI):
      vendor/bin/memio linter --directory=app/Models --changed-only
      
  4. CI/CD Flakiness:

    • Gotcha: Docker/phpspec dependencies may cause build failures unrelated to code.
    • Fix: Cache dependencies in GitHub Actions:
      - uses: actions/cache@v3
        with:
          path: vendor
          key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
      

Debugging

  • Constraint-Specific Errors:
    • Use phpspec to test constraints in isolation:
      make phpspec arg='--format pretty --filter="MethodCannotBeAbstractAndHaveBody"'
      
  • Reflection Issues:
    • If constraints fail silently, enable verbose output:
      $validator->setVerbose(true);
      

Extension Points

  1. Custom Validators:
    • Pattern: Create a LaravelConstraint class to bridge Memio and Laravel:
      class EloquentFillableConstraint implements ConstraintInterface {
          public function validate($model) {
              $reflection = new ReflectionClass($model);
              // Custom logic for Laravel fillable fields
          }
      }
      
  2. Dynamic Constraint Loading:
    • Pattern: Load constraints from a config file:
      $constraints = config('memio.linter.constraints');
      foreach ($constraints as $constraint) {
          $validator->add(new $constraint());
      }
      
  3. Integration with Laravel Events:
    • Pattern: Trigger linter on ModelCreated events:
      Model::created(function ($model) {
          $validator = new Validator();
          $validator->add(new ObjectValidator(/* ... */));
          $validator->validate(new ReflectionClass($model));
      });
      

Configuration Quirks

  • Docker Requirement:
    • The package expects Dockerized development (per Makefile). For Laravel, consider:
      docker run --rm -v $(pwd):/app composer require memio/linter
      
  • PHP Version Mismatch:
    • Ensure php.ini settings (e.g., opcache.enable=0) match Memio’s requirements.

Pro Tips

  • Combine with PHPStan:
    • Use Memio’s linter for syntax rules and PHPStan for type safety:
      vendor/bin/phpstan analyse --level=max --no-progress
      vendor/bin/memio linter --fail-on-error
      
  • Document Constraints:
    • Add a CONSTRAINTS.md file to explain why each constraint exists (e.g., "No abstract methods with bodies to prevent runtime errors").
  • Gradual Adoption:
    • Start with critical constraints (e.g., MethodCannotBeAbstractAndHaveBody) before enabling all.
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor