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

Attributes Laravel Package

laravel-lang/attributes

Laravel Lang: Attributes adds PHP attribute helpers for Laravel Lang packages, simplifying localization-related metadata and tooling. Includes documentation, tests, and easy Composer installation for Laravel projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require laravel-lang/attributes --dev
    

    Add the service provider to config/app.php:

    LaravelLang\Attributes\AttributesServiceProvider::class,
    
  2. First Use Case: Define a translation attribute on a model or DTO:

    use LaravelLang\Attributes\Label;
    
    class UserRequest extends FormRequest {
        #[Label('First Name')]
        public string $first_name;
    }
    

    Access the translated label in Blade:

    <x-input label="{{ $request->first_name->label }}" />
    

    Or in validation messages:

    $this->validate([
        'first_name' => 'required|string',
    ], [
        'first_name.required' => 'The :attribute is required.', // Automatically replaced with "First Name"
    ]);
    
  3. Translation Files: Ensure translations exist in resources/lang/{locale}/attributes.php:

    return [
        'first_name' => 'First Name',
    ];
    

Where to Look First

  • Documentation: Covers installation, attribute usage, and Blade integration.
  • config/attributes.php: Default configuration (e.g., fallback locales, attribute classes).
  • vendor/laravel-lang/attributes/src/: Source code for custom attribute extensions.

Implementation Patterns

Core Workflows

1. Model/Request Attributes

Use attributes on Laravel models, FormRequests, or DTOs to define translations:

use LaravelLang\Attributes\{Label, Placeholder};

class ProfileRequest extends FormRequest {
    #[Label('Full Name')]
    #[Placeholder('John Doe')]
    public string $name;

    #[Label('Date of Birth')]
    public string $dob;
}

Access in Blade:

<input
    type="text"
    name="name"
    placeholder="{{ $request->name->placeholder }}"
    aria-label="{{ $request->name->label }}"
>

2. Validation Integration

Leverage attributes in validation messages:

$this->validate([
    'name' => 'required|string|max:255',
    'dob' => 'required|date',
], [
    'name.required' => 'The :attribute is required.', // Uses "Full Name"
    'dob.date' => 'The :attribute must be a valid date.', // Uses "Date of Birth"
]);

3. Dynamic Forms

For dynamic fields (e.g., API-generated forms), resolve attributes at runtime:

use LaravelLang\Attributes\AttributeResolver;

$resolver = new AttributeResolver();
$label = $resolver->resolveLabel($request, 'email'); // Returns translated label

4. Custom Attributes

Extend the package with new attributes (e.g., [Tooltip]):

namespace App\Attributes;

use LaravelLang\Attributes\Attribute;

#[Attribute('tooltip')]
class Tooltip extends \LaravelLang\Attributes\Attribute {
    public function __construct(public string $text) {}
}

Register the custom attribute in config/attributes.php:

'attributes' => [
    \App\Attributes\Tooltip::class,
],

5. Fallback Logic

Configure fallbacks in config/attributes.php:

'fallback_locale' => 'en',
'fallback_to_attribute_name' => true, // Show "first_name" if translation missing

Integration Tips

  • Blade Components: Create reusable components for form fields:

    <x-form.input :field="$request->first_name" />
    
    // In a Blade component
    public function render() {
        return <<<'blade'
            <input
                type="text"
                name="{{\$field->name}}"
                placeholder="{{\$field->placeholder}}"
                aria-label="{{\$field->label}}"
            >
        blade;
    }
    
  • API Responses: Use attributes in API validation error responses:

    $this->validate([...]);
    return response()->json([
        'errors' => $this->errors()->messages(),
    ], 422);
    

    The :attribute placeholder will auto-resolve to translated labels.

  • Testing: Mock attributes in PHPUnit:

    $request = new ProfileRequest();
    $request->shouldReceive('getAttributeLabels')
        ->andReturn(['name' => 'Full Name']);
    
  • Localization Workflow:

    1. Add new attributes to models/requests.
    2. Run php artisan lang:publish to copy translation files.
    3. Update resources/lang/{locale}/attributes.php.
    4. Test with php artisan lang:test.

Gotchas and Tips

Pitfalls

  1. Attribute Reflection Overhead:

    • Issue: Reflection to read attributes adds ~1-2ms per request in high-traffic apps.
    • Fix: Cache resolved attributes in the request object:
      public function getAttributeLabels(): array {
          return $this->attributeLabels ??= (new AttributeResolver())->resolveAll($this);
      }
      
  2. Translation Key Conflicts:

    • Issue: Attribute keys (e.g., first_name) may clash with existing __('first_name') calls.
    • Fix: Use namespaced keys in attributes.php:
      return [
          'user.first_name' => 'First Name',
      ];
      
      Then reference in attributes:
      #[Label('user.first_name')]
      
  3. Blade Caching:

    • Issue: Dynamic attributes may break Blade cache if not handled carefully.
    • Fix: Use @once directives or disable caching for dynamic forms:
      @once
          <x-form.input :field="$dynamicField" />
      @endonce
      
  4. Fallback Locale Mismatch:

    • Issue: Fallback locale may not match user expectations (e.g., en instead of en_US).
    • Fix: Configure app.locale and attributes.fallback_locale consistently.
  5. Custom Attribute Registration:

    • Issue: Custom attributes may not load if not registered in config/attributes.php.
    • Fix: Verify the attributes array includes your custom class:
      'attributes' => [
          \LaravelLang\Attributes\Label::class,
          \App\Attributes\Tooltip::class,
      ],
      

Debugging Tips

  • Check Resolved Attributes:
    dd((new \LaravelLang\Attributes\AttributeResolver())->resolveAll($request));
    
  • Validate Translation Files: Run php artisan lang:test to ensure all attribute keys are translated.
  • Log Missing Translations: Enable debug mode in config/attributes.php:
    'debug' => true, // Logs missing translations to Laravel log
    

Extension Points

  1. Custom Attribute Resolvers: Override the default resolver for complex logic:

    use LaravelLang\Attributes\AttributeResolverInterface;
    
    class CustomResolver implements AttributeResolverInterface {
        public function resolveLabel(object $object, string $property): string {
            // Custom logic here
        }
    }
    

    Register in config/attributes.php:

    'resolver' => \App\Services\CustomResolver::class,
    
  2. Dynamic Attribute Loading: Load attributes from a database or API:

    #[Attribute('dynamic_label', [
        'source' => 'database',
        'table' => 'form_fields',
        'column' => 'label'
    ])]
    class DynamicLabel extends \LaravelLang\Attributes\Attribute {
        // ...
    }
    
  3. Translation Providers: Extend the package’s translation provider to support custom sources (e.g., JSON files):

    use LaravelLang\Attributes\TranslationProvider;
    
    class CustomTranslationProvider extends TranslationProvider {
        public function loadTranslations(): array {
            return array_merge(
                parent::loadTranslations(),
                json_decode(file_get_contents('custom/attributes.json'), true)
            );
        }
    }
    

    Bind in a service provider:

    $this->app->bind(
        \LaravelLang\Attributes\TranslationProvider::class,
        \App\Providers\CustomTranslationProvider::class
    );
    

Pro Tips

  • Use in API Resources: Attach translated labels to API responses:

    public function toArray($request) {
        return [
            'data' => [
                'name' => $this->name,
                'label' => $this->getAttributeLabel('name'),
            ],
        ];
    }
    
  • Combine with Laravel Breeze/Jetstream: Override default form components to use attributes:

    <x-jet-input
        type="text
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
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