Tenant variables
Tenant variables are variables that can be referenced everywhere in the application.
Every tenant variable has at least 1 value that may optionally be edited by users.
An example variable might be countries
where each value is a name of a country.
Getting started
To use tenant variables, you will have to create one first.
Creating a variable
Qore provides a TenantVariableCreator
which you may use in a seeder:
class TenantVariablesSeeder extends Seeder
{
public function run()
{
/** @var TenantVariableCreator $creator */
$creator = app(TenantVariableCreator::class);
$country = $creator->create('countries', 'Countries', ['employees', 'organizations']);
$creator->createValue($country, 'Netherlands', null, true, true);
$creator->createValue($country, 'United Kingdom', null, false, false);
$creator->createValue($country, 'Germany', null, false, false);
}
}
Variable definitions
When creating a variable with the create
method, you will have to supply:
- A name
- A description
- (optional) Tags used for filtering
Value definitions
When creating a value with the createValue
method, you will have to supply:
- The variable
- Content
- Description
- (optional) Should the value be locked, meaning no editing or deleting?
- (optional) Should the value be the default value to be selected in dropdowns?
- (optional) Should the value content be encrypted?
- (optional) Should the value be visible in dropdowns?
- (optional) Should the description get translated by default?
- (optional) Color code for the display value
- (optional) Icon for the display value
- (optional) Display type (e.g.:
TenantVariableValueDisplayType::TEXT
,TenantVariableValueDisplayType::PILL
)
Adding a column
For this example we will add a country_id
to our employees
table:
$table->unsignedBigInteger('country_id');
$table->foreign('country_id')->references('id')->on('tenant_variable_values');
And the relation on the Employee model:
public function country(): BelongsTo
{
return $this->belongsTo(TenantVariableValue::class, 'country_id')->withTrashed();
}
Make sure to always add a foreign key reference to your column. This will be cross-referenced when a user decides to delete a value.
Usage
You are free to use variables in any way, however Qore provides a dropdown select field by default.
Adding a select field
For example, let's add a country select to the Employee resource:
use Qore\System\Fields\VariableValue;
VariableValue::make(__('Country'), 'country')
->forVariable(tenant_variable('countries'))
->rules('required', 'exists:tenant_variable_values,id')
Adding multi select field
You can also have a multi select for tenant variable values.
Let's assume the following table & relationship on the Material model:
// Migration
Schema::create('material_tag', function (Blueprint $table) {
$table->id();
$table->foreignId('material_id')->constrained()->onDelete('cascade');
$table->foreignId('tenant_variable_value_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
// Model
public function tags(): BelongsToMany
{
return $this->belongsToMany(TenantVariableValue::class, 'material_tag');
}
Then the field would look like:
BelongsToMany::make(__('Tags'), 'tags', TenantVariableValueResource::class)
->scopeUsing(fn (Builder $builder) => $builder
->where('tenant_variable_id', tenant_variable('material_tags')->id)
)
->withRelationalMeta(function (FormState $state) {
$state->setState('tenantVariable', tenant_variable('material_tags')->id);
$state->readonlyFields('tenantVariable');
})
->rules('nullable', 'exists:tenant_variable_values,id')
Helper methods
You can retrieve a variable and it's values with the following method:
// The variable:
tenant_variable('countries')
// And the values:
tenant_variable('countries')->values
Note on caching
Tenant variables & values are cached by default, meaning the cache will only be busted when a value gets updated
.
If you ever have a many-to-many relationship that stores tenant variables, you might come across some issues where it might look like relationships are not actually saved.
Until we have a better solution in Qore, you could execute the following code to flush the cache:
TenantVariableValue::flushQueryCache();
For example, in your resource class you can add:
public function saved(Model $model, ?Model $original = null)
{
TenantVariableValue::flushQueryCache();
parent::saved($model, $original);
}