Pseudojoin
- Version
- 3.x
- Updated
A picker whose options come from a model method rather than a table, storing the option's own string key: a template folder name, a PSP connector name, a language tag.
Storage kind: column · Column: varchar(100)
Use it when the thing being chosen is not a database row — templates on disk, installed connectors,
registered providers. If the options are rows and the value is their id, you want
join; if the set is a short fixed list known in code, you want
dropdown.
Settings
Declared like a join, because it is one — the class extends KenedoPropertyJoin:
| Setting | Meaning |
|---|---|
modelClass | The model exposing the option list |
modelMethod | The method returning it — e.g. getProductTemplates, getPspConnectors |
propNameKey | The key field in each option, usually value |
propNameDisplay | The label field, usually title |
defaultlabel | Placeholder |
$propDefs['template'] = array(
'name' => 'template',
'type' => 'pseudojoin',
'modelClass' => 'ConfigboxModelTemplates',
'modelMethod' => 'getProductTemplates',
'propNameKey' => 'value',
'propNameDisplay' => 'title',
);
Because there is no table, there is no SQL join and no <name>_display_value from one: the label
comes from the option list itself, re-fetched when the form renders.
Why it exists
These were declared as 'type' => 'join', 'isPseudoJoin' => true. That worked — KenedoPropertyJoin
checks the flag and skips the SQL join — but everything describing the property saw "join" and
inferred an int unsigned foreign key, when the column really holds a short string. The generated
schemas, the type descriptions and the schema-drift check were all wrong in the same way.
The class extends KenedoPropertyJoin and forces isPseudoJoin in its constructor, before the
parent sees the definition — getPropertyDefinition() is final, so there is no other interception
point. Query building is therefore unchanged; what changes is that the type now states what it is,
and getDefaultDataType() can answer varchar(100).
varchar(100) comfortably holds a template folder or connector name — the longest in use is seven
characters — while staying narrow enough to index. A picker whose keys are genuinely longer carries
an explicit dataType.
Choosing between this and join
- Options come from a table, value is an integer id →
join - Options come from a method, value is a string key →
pseudojoin
isPseudoJoin on a join is still honoured, so customization code declaring the old shape keeps
working. It is also still correct for its other use: a genuine integer FK suppressing the join to
avoid an alias collision between two joins onto the same parent model.
Notes
It has its own template (tmpl/pseudojoin.php) that delegates to the join template. That file
has to exist: templates resolve by type name, and without one the field renders as nothing — the
form shows no control, nothing is submitted, and the insert fails on a NOT NULL column far from the
cause. That is exactly how this type's first version broke product-list saves.
The same trap applies to any type you add: see §6 of the overview.
@see join.md @see dropdown.md