You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This roadmap turns the current improvement analysis into a concrete execution plan for `freshsauce/model`.
3
+
This roadmap tracks the improvement work for `freshsauce/model`.
4
4
5
-
The sequencing is intentional:
5
+
Current status:
6
+
7
+
1. Phase 1 is complete.
8
+
2. Phase 2 is complete.
9
+
3. Phase 3 is complete.
10
+
4. Phase 4 remains optional and has not been started.
11
+
12
+
The sequencing remains intentional:
6
13
7
14
1. Fix correctness issues before expanding the API.
8
15
2. Improve developer ergonomics without turning the library into a heavyweight ORM.
9
-
3. Add optional features only where they preserve the package's lightweight position.
16
+
3. Tighten quality and portability before considering broader feature growth.
17
+
4. Add optional features only where they preserve the package's lightweight position.
10
18
11
19
## Principles
12
20
@@ -17,257 +25,41 @@ The sequencing is intentional:
17
25
18
26
## Phase 1: Core correctness and safety
19
27
20
-
Goal: remove known edge-case bugs and make failure modes explicit.
21
-
22
-
Priority: high
23
-
24
-
### Milestone 1.1: Serialization works correctly
25
-
26
-
Problem:
27
-
`Model::__sleep()` returns table field names, but model state lives in `$data` and `$dirty`. Serializing a model currently emits warnings and drops state.
28
-
29
-
Tasks:
30
-
31
-
- Replace `__sleep()` with `__serialize()` and `__unserialize()`.
32
-
- Preserve hydrated values and dirty-state behavior after unserialization.
33
-
- Decide whether deserialized models should retain dirty flags or reset to clean.
34
-
- Add PHPUnit coverage for round-trip serialization of new and persisted models.
35
-
36
-
Acceptance criteria:
37
-
38
-
-`serialize($model)` produces no warnings.
39
-
-`unserialize(serialize($model))` preserves field values.
40
-
- Dirty-state behavior after round-trip is documented and tested.
41
-
42
-
### Milestone 1.2: Persisted-state detection is explicit
43
-
44
-
Problem:
45
-
`save()` uses truthiness on the primary key. A value like `0` is treated as "new" and triggers insert instead of update.
46
-
47
-
Tasks:
48
-
49
-
- Introduce a dedicated persisted-state check based on `null` rather than truthiness.
50
-
- Review insert/update/delete behavior for zero-like primary key values.
51
-
- Add tests for integer `0`, string `'0'`, and non-default primary key names.
52
-
53
-
Acceptance criteria:
54
-
55
-
-`save()` updates when a record has a zero-like primary key value.
56
-
- Insert behavior remains unchanged for `null` primary keys.
57
-
58
-
### Milestone 1.3: Dynamic finder failures are model-level errors
59
-
60
-
Problem:
61
-
Unknown dynamic fields fall through to raw SQL execution and surface as PDO errors instead of clear model exceptions.
62
-
63
-
Tasks:
64
-
65
-
- Make `resolveFieldName()` fail fast when a field does not map to a real column.
66
-
- Add a dedicated exception for unknown fields or invalid dynamic methods.
67
-
- Add tests for invalid `findBy...`, `findOneBy...`, and `countBy...` calls.
28
+
Status: completed
68
29
69
-
Acceptance criteria:
30
+
Summary:
70
31
71
-
- Invalid dynamic finders throw a predictable library exception before query execution.
72
-
- Error messages identify the requested field and model class.
73
-
74
-
### Milestone 1.4: Empty-array query behavior is defined
75
-
76
-
Problem:
77
-
Helpers that build `IN (...)` clauses do not define behavior for empty arrays.
78
-
79
-
Tasks:
80
-
81
-
- Define expected behavior for empty-array matches across:
82
-
-`findBy...`
83
-
-`findOneBy...`
84
-
-`firstBy...`
85
-
-`lastBy...`
86
-
-`countBy...`
87
-
-`fetchAllWhereMatchingSingleField()`
88
-
-`fetchOneWhereMatchingSingleField()`
89
-
- Implement that behavior without generating invalid SQL.
90
-
- Add regression tests for each public entry point.
91
-
92
-
Acceptance criteria:
93
-
94
-
- Empty arrays never produce invalid SQL.
95
-
- Collection methods return empty results.
96
-
- Singular methods return `null`.
97
-
- Count methods return `0`.
98
-
99
-
### Milestone 1.5: Replace generic exceptions with library exceptions
100
-
101
-
Problem:
102
-
The model currently throws generic `\Exception` in many places, which makes calling code and tests less precise.
103
-
104
-
Tasks:
105
-
106
-
- Introduce a small exception hierarchy under `Freshsauce\Model\Exception\`.
107
-
- Replace generic throws for:
108
-
- missing connection
109
-
- unknown field
110
-
- invalid dynamic method
111
-
- missing data access
112
-
- identifier quoting setup failures
113
-
- Keep exception names narrow and practical.
114
-
115
-
Acceptance criteria:
116
-
117
-
- Core failure modes throw specific exception classes.
118
-
- Existing messages remain readable.
119
-
- Public docs mention the main exception types users should expect.
32
+
- Fixed serialization, zero-like primary key handling, invalid dynamic finder failures, and empty-array query behavior.
33
+
- Replaced generic exceptions with a small library exception hierarchy.
34
+
- Added regression coverage for the above edge cases.
120
35
121
36
## Phase 2: API ergonomics and typing
122
37
123
-
Goal: make the library easier to use correctly while keeping the current lightweight style.
0 commit comments