Skip to main content

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();
}
caution

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);
}