Skip to main content

Configuration

Products can have configurations that control performance parameters like memory or RAM. They subsequently allow delivering services based on this configuration.

Interface: App/Contracts/Store/ProductConfigInterface

Abstract Class: App/Abstracts/AbstractConfig

Creating the Class

The App/Contracts/Store/ProductConfigInterface interface defines the methods each configuration class must implement to manage product configuration. The main methods are:

  • validate(): Defines validation rules for the configuration.
  • render(): Returns the HTML form to display and modify the product configuration.
  • storeConfig(): Saves configurations to the database.
  • updateConfig(): Updates existing configurations in the database.
  • deleteConfig(): Deletes the configuration associated with a product.
  • getConfig(): Retrieves a product's configuration.
  • cloneConfig(): Clones a configuration from one product to another.
<?php
// addons/fund/src/CustomProductConfig.php
namespace App\Addons\Fund;

use App\Abstracts\AbstractConfig;
use App\Models\Store\Product;
use App\Models\Provisioning\Server;

class CustomProductConfig extends AbstractConfig
{
protected string $type = 'custom-product';
protected string $model = \App\Addons\Fund\Models\GameserverConfigModel::class;

/**
* Render the configuration form for a specific product
*/
public function render(Product $product)
{
$context = [
'servers' => $this->servers, // Available servers
'config' => $this->getConfig($product->id, new $this->model), // Existing configuration or new instance
];

return view('fund_admin::product-config', $context);
}

/**
* Validate configuration data
*/
public function validate(): array
{
return [
'memory' => 'required|numeric|min:512',
'cpu' => 'required|numeric|min:1',
'disk' => 'required|numeric|min:10',
'server_id' => 'required|exists:servers,id',
];
}

/**
* Save configuration for a product
*/
public function storeConfig(Product $product, array $parameters)
{
$this->model::create($parameters + ['product_id' => $product->id]);
}

/**
* Update configuration for a product
*/
public function updateConfig(Product $product, array $parameters)
{
$this->model::where('product_id', $product->id)->update($parameters);
}
}

Creating the Migration

Use the following artisan command to create a migration for the game server configuration table:

php artisan clientxcms:create-migration-extension

When the command asks for the migration name, enter:

CreateGameserverConfigTable

Then, in the generated migration file, define the table structure by adding a product_id field to link with products:

// database/migrations/2022_01_01_000000_create_gameserver_config_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateGameserverConfigTable extends Migration
{
public function up()
{
Schema::create('gameserver_configs', function (Blueprint $table) {
$table->id();
$table->foreignId('product_id')->constrained('products')->onDelete('cascade'); // Link to products table
$table->integer('memory');
$table->integer('cpu');
$table->integer('disk');
$table->foreignId('server_id')->constrained('servers')->onDelete('cascade'); // Link to servers table
$table->timestamps();
});
}

public function down()
{
Schema::dropIfExists('gameserver_configs');
}
}

Configuration Form View

You can create a view in the addons/fund/views/admin/product-config.blade.php folder to display the configuration form:

<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
@include("admin/shared/input", ['name' => 'memory', 'label' => __('provisioning.memory'), 'value' => $config->memory, 'help' => __('provisioning.in_gb'), 'type' => 'number','step' => '0.1', 'min' => 0])
</div>
<div>
@include("admin/shared/input", ['name' => 'disk', 'label' => __('provisioning.disk'), 'value' => $config->disk, 'help' => __('provisioning.in_gb'), 'type' => 'number', 'step' => '0.1', 'min' => 0])
</div>
<div>
@include("admin/shared/input", ['name' => 'cpu', 'label' => __('provisioning.cpu'), 'value' => $config->cpu, 'type' => 'number'])
</div>
</div>

Creating the Associated Model

Create a model to represent the game server configuration. We recommend naming this model GameserverConfigModel for clarity:

namespace App\Addons\Fund\Models;

use Illuminate\Database\Eloquent\Model;

class GameserverConfigModel extends Model
{
protected $table = 'gameserver_configs'; // Table name

protected $fillable = [
'product_id',
'memory',
'cpu',
'disk',
'server_id',
];

public function product()
{
return $this->belongsTo(\App\Models\Store\Product::class);
}

public function server()
{
return $this->belongsTo(\App\Models\Provisioning\Server::class);
}
}

Registering the Class in the Product

Once the configuration class and model are created, you must associate this configuration with the product by registering it in the config() method of the product class. Here's an example:

public function config(): ?\App\Contracts\Store\ProductConfigInterface
{
return new \App\Addons\Fund\GameserverConfig(); // Returns the configuration class for this product
}

This allows the CMS to use the configuration when managing products, displaying the configuration form and validating data when creating or modifying a product.