Skip to main content
Version: 3.x

Pseudojoin

Version
3.x
Updated
View markdown

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:

SettingMeaning
modelClassThe model exposing the option list
modelMethodThe method returning it — e.g. getProductTemplates, getPspConnectors
propNameKeyThe key field in each option, usually value
propNameDisplayThe label field, usually title
defaultlabelPlaceholder
$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 idjoin
  • Options come from a method, value is a string keypseudojoin

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