Skip to content

Commit 1935c52

Browse files
committed
wip
1 parent b54e401 commit 1935c52

File tree

4 files changed

+230
-13
lines changed

4 files changed

+230
-13
lines changed

INSTALLATION.md

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ This guide provides detailed instructions for installing and configuring the Lar
1616

1717
### System Requirements
1818

19-
- **PHP**: 8.1 or higher
20-
- **Laravel**: 9.0 or higher
21-
- **Database**: MySQL 5.7+, PostgreSQL 12+, or SQLite 3.35+
19+
- **PHP**: 8.3 or higher
20+
- **Laravel**: 11.0 or higher
21+
- **Database**: MySQL 8.1+, PostgreSQL 12+, or SQLite 3.35+
2222

2323
### PHP Extensions
2424

@@ -565,9 +565,48 @@ rm -rf database/migrations/*_create_entity_properties_table.php
565565

566566
After successful installation:
567567

568+
> **⚠️ IMPORTANT**: Before using dynamic properties, you must create property definitions first!
569+
570+
### Quick Start
571+
572+
1. **Create your first properties**:
573+
```bash
574+
# Interactive property creation
575+
php artisan properties:create
576+
```
577+
578+
Or programmatically:
579+
```php
580+
use SolutionForest\LaravelDynamicProperties\Models\Property;
581+
582+
Property::create([
583+
'name' => 'phone',
584+
'label' => 'Phone Number',
585+
'type' => 'text'
586+
]);
587+
```
588+
589+
2. **Add the trait to your models**:
590+
```php
591+
use SolutionForest\LaravelDynamicProperties\Traits\HasProperties;
592+
593+
class User extends Model
594+
{
595+
use HasProperties;
596+
}
597+
```
598+
599+
3. **Start using properties**:
600+
```php
601+
$user = User::find(1);
602+
$user->setDynamicProperty('phone', '+1234567890'); // ✅ Works
603+
```
604+
605+
### Additional Resources
606+
568607
1. **Read the [Usage Examples](docs/EXAMPLES.md)** for common use cases
569-
2. **Review the [API Documentation](docs/API.md)** for detailed method references
608+
2. **Review the [API Documentation](docs/API.md)** for detailed method references
570609
3. **Check the [Performance Guide](docs/PERFORMANCE.md)** for optimization strategies
571610
4. **Set up monitoring** for production environments
572611

573-
The package is now ready to use! Start by adding the `HasProperties` trait to your models and creating your first properties.
612+
> **💡 Remember**: Always create Property definitions before setting values to avoid `PropertyNotFoundException`!

README.md

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ php artisan vendor:publish --provider="SolutionForest\LaravelDynamicProperties\D
6565

6666
## Quick Start
6767

68+
> **⚠️ IMPORTANT**: You must create Property definitions before setting property values. Attempting to set a property that doesn't have a definition will throw a `PropertyNotFoundException`.
69+
6870
### 1. Add the Trait to Your Models
6971

7072
```php
@@ -85,8 +87,10 @@ class User extends Model
8587

8688
### 2. Create Properties
8789

90+
**⚠️ REQUIRED STEP**: Before setting any property values, you must first create the property definitions. This ensures type safety, validation, and optimal performance.
91+
8892
```php
89-
use YourVendor\DynamicProperties\Models\Property;
93+
use SolutionForest\LaravelDynamicProperties\Models\Property;
9094

9195
// Create a text property
9296
Property::create([
@@ -118,14 +122,19 @@ Property::create([
118122

119123
### 3. Set and Get Properties
120124

125+
**✅ Only after creating property definitions can you set values:**
126+
121127
```php
122128
$user = User::find(1);
123129

124-
// Set properties
130+
// ✅ This works - property 'phone' was defined above
125131
$user->setDynamicProperty('phone', '+1234567890');
126132
$user->setDynamicProperty('age', 25);
127133
$user->setDynamicProperty('status', 'active');
128134

135+
// ❌ This will throw PropertyNotFoundException
136+
$user->setDynamicProperty('undefined_property', 'value');
137+
129138
// Or use magic methods
130139
$user->prop_phone = '+1234567890';
131140
$user->prop_age = 25;
@@ -143,20 +152,80 @@ $user->setProperties([
143152
]);
144153
```
145154

155+
> **💡 Pro Tip**: Use the Artisan command to create properties interactively:
156+
> ```bash
157+
> php artisan properties:create
158+
> ```
159+
146160
### 4. Search by Properties
147161
162+
**🔍 Search works with or without property definitions, but defining properties first is strongly recommended for type safety:**
163+
148164
```php
149-
// Find users by single property
165+
// ✅ RECOMMENDED: Search with defined properties (uses correct column types)
150166
$activeUsers = User::whereProperty('status', 'active')->get();
151167
$youngUsers = User::whereProperty('age', '<', 30)->get();
152168
169+
// ⚠️ FALLBACK: Search undefined properties (uses value-based type detection)
170+
$results = User::whereProperty('undefined_prop', 'some_value')->get();
171+
153172
// Find users by multiple properties
154173
$users = User::whereProperties([
155174
'status' => 'active',
156175
'age' => 25
157176
])->get();
158177
```
159178
179+
## ⚠️ Common Pitfalls and Warnings
180+
181+
### 1. Property Definition Required for Setting Values
182+
```php
183+
// ❌ WRONG - Will throw PropertyNotFoundException
184+
$user->setDynamicProperty('new_field', 'value'); // Property 'new_field' doesn't exist
185+
186+
// ✅ CORRECT - Create property definition first
187+
Property::create([
188+
'name' => 'new_field',
189+
'label' => 'New Field',
190+
'type' => 'text'
191+
]);
192+
$user->setDynamicProperty('new_field', 'value'); // Now it works
193+
```
194+
195+
### 2. Type Safety Depends on Property Definitions
196+
```php
197+
// ✅ With property definition - Type safe
198+
Property::create(['name' => 'score', 'type' => 'number']);
199+
$users = User::whereProperty('score', '>', 80); // Uses number_value column correctly
200+
201+
// ⚠️ Without property definition - Fallback behavior
202+
$users = User::whereProperty('undefined_score', '>', 80); // Uses value-based type detection
203+
```
204+
205+
### 3. Validation Only Works with Property Definitions
206+
```php
207+
// ✅ With validation rules
208+
Property::create([
209+
'name' => 'email',
210+
'type' => 'text',
211+
'validation' => ['email', 'required']
212+
]);
213+
$user->setDynamicProperty('email', 'invalid-email'); // Throws PropertyValidationException
214+
215+
// ❌ Without property definition - No validation possible
216+
// (Would throw PropertyNotFoundException before validation could occur)
217+
```
218+
219+
### 4. Performance Impact
220+
```php
221+
// ✅ FAST - Uses correct column and indexes
222+
Property::create(['name' => 'department', 'type' => 'text']);
223+
$users = User::whereProperty('department', 'engineering'); // Optimized query
224+
225+
// ⚠️ SLOWER - Uses fallback type detection
226+
$users = User::whereProperty('undefined_dept', 'engineering'); // Less optimal
227+
```
228+
160229
## Advanced Usage
161230
162231
### Property Types and Validation
@@ -449,6 +518,45 @@ return [
449518
];
450519
```
451520
521+
## Troubleshooting
522+
523+
### Common Errors and Solutions
524+
525+
#### `PropertyNotFoundException`
526+
```php
527+
// Error: "Property 'phone' not found"
528+
$user->setDynamicProperty('phone', '+1234567890');
529+
```
530+
**Solution**: Create the property definition first:
531+
```php
532+
Property::create(['name' => 'phone', 'type' => 'text']);
533+
$user->setDynamicProperty('phone', '+1234567890'); // Now works
534+
```
535+
536+
#### `PropertyValidationException`
537+
```php
538+
// Error: "Validation failed for property 'age'"
539+
$user->setDynamicProperty('age', -5);
540+
```
541+
**Solution**: Check property validation rules:
542+
```php
543+
$property = Property::where('name', 'age')->first();
544+
var_dump($property->validation); // See what rules are defined
545+
$user->setDynamicProperty('age', 25); // Use valid value
546+
```
547+
548+
#### Inconsistent Search Results
549+
```php
550+
// Getting different results for the same logical query
551+
$users1 = User::whereProperty('level', '>', 5)->get(); // 10 results
552+
$users2 = User::whereProperty('level', '>', '5')->get(); // 3 results
553+
```
554+
**Solution**: This happens when property definition is missing. Create it:
555+
```php
556+
Property::create(['name' => 'level', 'type' => 'number']);
557+
// Now both queries will return the same results
558+
```
559+
452560
## Testing
453561
454562
The package includes comprehensive tests. Run them with:

docs/API.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# API Documentation
22

3+
> **⚠️ IMPORTANT**: Property definitions must be created before setting property values. All `setDynamicProperty` methods will throw `PropertyNotFoundException` if the property doesn't exist. Search methods (`whereProperty`) will work but fall back to less optimal type detection without property definitions.
4+
35
## Table of Contents
46

57
- [Models](#models)
@@ -14,6 +16,37 @@
1416
- [Facades](#facades)
1517
- [Artisan Commands](#artisan-commands)
1618

19+
## Getting Started
20+
21+
### Property Definition Requirement
22+
23+
**All dynamic property operations require property definitions to exist first.** Here's what happens in each scenario:
24+
25+
| Operation | With Property Definition | Without Property Definition |
26+
|-----------|-------------------------|----------------------------|
27+
| `setDynamicProperty()` | ✅ Works with validation | ❌ Throws `PropertyNotFoundException` |
28+
| `setProperties()` | ✅ Works with validation | ❌ Throws `PropertyNotFoundException` |
29+
| `whereProperty()` | ✅ Optimal performance, type-safe | ⚠️ Works but uses fallback type detection |
30+
| `getDynamicProperty()` | ✅ Returns typed value | ✅ Returns value if exists |
31+
32+
### Quick Setup Checklist
33+
34+
1. **Create property definitions**:
35+
```php
36+
Property::create(['name' => 'phone', 'type' => 'text']);
37+
Property::create(['name' => 'age', 'type' => 'number']);
38+
```
39+
40+
2. **Add trait to your models**:
41+
```php
42+
class User extends Model { use HasProperties; }
43+
```
44+
45+
3. **Start using properties**:
46+
```php
47+
$user->setDynamicProperty('phone', '+1234567890');
48+
```
49+
1750
## Models
1851

1952
### Property Model
@@ -159,7 +192,13 @@ class User extends Model
159192

160193
Sets a single property value with validation.
161194

195+
> **⚠️ REQUIREMENT**: The property must exist in the `properties` table before calling this method.
196+
162197
```php
198+
// First create the property definition
199+
Property::create(['name' => 'phone', 'type' => 'text']);
200+
201+
// Then set the value
163202
$user->setDynamicProperty('phone', '+1234567890');
164203
```
165204

@@ -192,7 +231,15 @@ $phone = $user->getDynamicProperty('phone');
192231

193232
Sets multiple properties at once.
194233

234+
> **⚠️ REQUIREMENT**: All properties must exist in the `properties` table before calling this method.
235+
195236
```php
237+
// Ensure all properties are defined first
238+
Property::create(['name' => 'phone', 'type' => 'text']);
239+
Property::create(['name' => 'age', 'type' => 'number']);
240+
Property::create(['name' => 'active', 'type' => 'boolean']);
241+
242+
// Then set multiple values
196243
$user->setProperties([
197244
'phone' => '+1234567890',
198245
'age' => 25,
@@ -293,9 +340,18 @@ $entityProperties = $user->entityProperties;
293340

294341
Filter entities by a single property value.
295342

343+
> **💡 BEST PRACTICE**: While this method works without property definitions (using fallback type detection), defining properties first ensures optimal performance and type safety.
344+
296345
```php
346+
// ✅ RECOMMENDED: With property definition
347+
Property::create(['name' => 'active', 'type' => 'boolean']);
348+
Property::create(['name' => 'age', 'type' => 'number']);
349+
297350
$activeUsers = User::whereProperty('active', true)->get();
298351
$youngUsers = User::whereProperty('age', '<', 30)->get();
352+
353+
// ⚠️ WORKS BUT NOT OPTIMAL: Without property definition
354+
$results = User::whereProperty('undefined_prop', 'value')->get(); // Uses fallback logic
299355
```
300356

301357
**Parameters:**
@@ -372,8 +428,15 @@ Core service for managing dynamic properties.
372428

373429
Sets a property value for an entity.
374430

431+
> **⚠️ REQUIREMENT**: The property must exist in the `properties` table before calling this method.
432+
375433
```php
376434
$propertyService = app(PropertyService::class);
435+
436+
// First ensure property exists
437+
Property::create(['name' => 'phone', 'type' => 'text']);
438+
439+
// Then set the value
377440
$propertyService->setDynamicProperty($user, 'phone', '+1234567890');
378441
```
379442

0 commit comments

Comments
 (0)