Tetapan boleh dikonfigurasikan pengguna dalam aplikasi Symfony dengan jbtronics/settings-bundle (Bahagian Migrasi dan pembolehubah persekitaran

WBOY
Lepaskan: 2024-07-19 11:26:33
asal
422 orang telah melayarinya

User-configurable settings in Symfony applications with jbtronics/settings-bundle (Part  Migrations and environment variables

Dalam dua bahagian pertama siri ini, konsep asas himpunan tetapan telah diperkenalkan dan cara menggunakannya untuk mencipta tetapan boleh dikonfigurasikan pengguna yang bagus dalam aplikasi Symfony.
Dalam bahagian ini, anda akan belajar cara membuat versi tetapan anda dan berhijrah antara tetapan tersebut. Selain itu, anda akan belajar cara menggabungkan pembolehubah persekitaran dengan tetapan.

Versi dan penghijrahan

Lama kelamaan aplikasi anda akan berkembang dan begitu juga tetapan anda. Ini bermakna bahawa dari semasa ke semasa parameter baharu akan ditambahkan pada tetapan, yang lama akan dialih keluar dan yang sedia ada akan ditukar. Untuk menangani perkara ini, himpunan tetapan menyediakan mekanisme versi dan migrasi, yang menguruskan kebanyakan kerja untuk anda.

Andaikan anda mempunyai kelas tetapan mudah seperti ini:

namespace App\Settings; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; #[Settings] class TestSettings { #[SettingsParameter] public string $email = 'test@invalid'; #[SettingsParameter] public int $baz = 42; }
Salin selepas log masuk

Tetapan ini telah digunakan untuk beberapa lama dalam aplikasi anda dan pengguna telah menyimpan penyesuaian mereka padanya. Jika anda hanya mahu menambah parameter baharu pada tetapan, anda boleh melakukan ini dengan hanya menambahkan sifat baharu pada kelas dan ia akan berfungsi dengan baik. Parameter baharu akan dimulakan dengan nilai lalai dan pengguna boleh menukarnya sesuka hati:

#[Settings] class TestSettings { #[SettingsParameter] public string $email = 'test@invalid'; #[SettingsParameter] public int $baz = 42; #[SettingsParameter] public bool $qux = true; }
Salin selepas log masuk

Mengalih keluar parameter berfungsi sama. Jika anda mengalih keluar harta daripada kelas, himpunan tetapan akan mengabaikan nilai sedia ada untuknya dan memadamkannya apabila tetapan disimpan seterusnya.

Namun, yang lebih rumit, adalah jika anda ingin menamakan semula medan atau, lebih rumit lagi, menukar jenisnya atau cara data disimpan dengan tepat. Untuk tidak kehilangan penyesuaian sedia ada pengguna, anda perlu menentukan cara menukar antara perwakilan tetapan yang berbeza. Himpunan tetapan boleh menyokong anda dengan ini dengan menyediakan rangka kerja untuk migrasi.

Anggap anda ingin menukar kelas tetapan anda dengan cara, yang kini anda boleh mempunyai berbilang alamat e-mel. Juga, anda ingin menukar pengindeksan parameter baz, supaya ia tidak bermula pada 0, tetapi pada 1, bermakna semua nilai sedia ada harus ditambah dengan 1. Pada akhirnya kelas tetapan anda akan kelihatan seperti ini:

namespace App\Settings; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; #[Settings(version: self::VERSION, migrationService: TestSettingsMigration::class)] class TestSettings { public const VERSION = 1; #[SettingsParameter(type: ArrayType::class, options: ['type' => StringType::class])] public array $email = ['test@invalid']; #[SettingsParameter] //Now with different indexing public int $baz = 43; }
Salin selepas log masuk

Kelas tetapan ujian kini mempunyai struktur baharu yang dimaksudkan dan boleh digunakan dalam aplikasi. Walau bagaimanapun, set-bundle tidak akan tahu cara menukar data sedia ada kepada struktur baharu. Di sinilah penghijrahan
ikut bermain.

Anda boleh melihat bahawa atribut tetapan kini mempunyai pilihan versi dan pilihan migrationService ditentukan:

Pilihan versi menentukan versi skema terbaharu tetapan dan hanyalah integer (lebih besar sifar), yang dinaikkan setiap kali anda menukar struktur kelas tetapan. Anda boleh bermula dengan 1 dan menambahnya setiap kali anda menukar struktur kelas tetapan. Anda boleh meletakkan nombor versi terus ke dalam atribut, atau anda boleh menentukan pemalar untuknya, seperti yang ditunjukkan dalam contoh, yang mempunyai kelebihan bahawa anda boleh mendapatkan semula versi semasa dengan mudah dari luar kelas.

Perkara baharu kedua ialah pilihan migrationService. Ini menentukan kelas perkhidmatan, yang sebenarnya melakukan pemindahan data. MigrationService mesti melaksanakan SettingsMigrationInterface, yang menentukan fungsi migrasi yang bertanggungjawab untuk melaksanakan migrasi antara dua versi data tertentu.

Dalam kebanyakan kes, anda ingin melakukan migrasi secara berperingkat antara versi (bermaksud anda memindahkan 1 -> 2, kemudian 2 -> 3 dan seterusnya, bukannya 1 -> 3 secara langsung untuk mengelakkan pertindihan kod). Dalam keadaan ini, lebih mudah untuk melanjutkan kelas SettingsMigration. Menggunakan kelas abstrak ini, perkhidmatan migrasi anda mungkin kelihatan seperti ini:

namespace App\Settings\Migrations; use Jbtronics\SettingsBundle\Migrations\SettingsMigration; class TestSettingsMigration extends SettingsMigration { /** * This method is called automatically by the migration class and handles * migration of version 0 (non versioned settings) to version 1. */ public function migrateToVersion1(array $data, SettingsMetadata $metadata): array { /* * $data contains the old settings data, in the normalized form (in the way it was saved in the database) * Each key is the parameter name (not necessarily the property name) * * In the end we must return the new data in the normalized form, which is later then passed to * the parameter type converters. */ //If the email parameter was set, convert it to an array if (isset($data['email'])) { $data['email'] = [$data['email']]; } //Increment the baz parameter, if it was set if (isset($data['baz'])) { $data['baz']++; } //Return the new data return $data; } /** * This method is called, to handle migration from version 1 to version 2. */ public function migrateToVersion2(array $data, SettingsMetadata $metadata): array { //Perform some more migrations... return $data; } }
Salin selepas log masuk

Perkhidmatan migrasi mengandungi pelbagai kaedah dalam bentuk migrateToVersionXX(), yang dipanggil secara automatik oleh kelas jika tetapan dipindahkan daripada versi XX-1 ke versi XX. Kaedah menerima data dalam bentuk normal dan metadata kelas tetapan dan mesti mengembalikan data dalam bentuk normal, yang kemudiannya dihantar kepada penukar jenis parameter. Jika anda ingin menyatakan secara eksplisit fungsi yang dipanggil untuk versi yang mana, anda boleh mengatasi kaedah resolveStepHandler, yang mengembalikan penutupan untuk digunakan untuk versi tertentu.

Memandangkan data sedia ada belum mempunyai versi lagi, ia diandaikan ia adalah versi 0. Oleh itu, apabila menemui tetapan data ini-himpunan akan memanggil pengendali migrateToVersion1 untuk berhijrah daripada 0 kepada versi 1 yang paling terkini.

The old data from the storage is passed to the migration method (as $data) and you have to convert it to the new form how it can be saved to storage and how the parameter type conversions can understand it. Each parameter is stored in the $data array with the parameter name as key. You can then modify the data as you like and return it in the end.

Please note that the $data array is in the normalized form, meaning that you only have simple datatypes like strings, integers, arrays and so on. If you want to like to work with the denormalized form (like objects, etc.) you might find the getAsPHPValue() and setAsPHPValue() methods available in the SettingsClass (or in the PHPValueConverterTrait) useful. Or you call the ParameterTypes you need directly.

The settings-bundle stores the version of the data in the storage provider, so that it is automatically known what version the data has and what migrations to perform. The migrations are automatically performed when trying to retrieve settings data (by getting the settings from the SettingsManager or calling a property of a lazy settings class). By default, the migrated data is written back to the storage after the migration, so that the migration only has to be performed once for each setting, even if the settings are not explicitly written back to the storage.

Environment variables

Environment variables are one of the classic possibilities to configure a Symfony application. They allow you for an easy configuration approach in automatic deployed applications, containers, etc. via a more or less unified interface. So they are pretty ideal for server administrators, who want to configure an application without touching the code. However, the big disadvantage of environment variables is, that they are not user-configurable, as users (even those intended as admin users) can not change them without direct access to the server.

To retain the advantages of environment variables, while also allowing users to configure the applications via the settings-bundle, the bundle can map environment variables to settings class parameters.

This is done via the envVar option on the SettingsParameter attribute:

#[Settings] class TestSettings { #[SettingsParameter(envVar: 'APP_EMAIL')] public string $email = 'test@invalid'; #[SettingsParameter(envVar: 'int:APP_BAZ', envVarMode: EnvVarMode::OVERWRITE)] public int $baz = 42; #[SettingsParameter(envVar: 'bool:APP_TEST_SETTINGS_QUX', envVarMode: EnvVarMode::OVERWRITE_PERSIST)] public bool $qux = true; }
Salin selepas log masuk

The envVar option specifies the environment variable to map to the parameter. If it does not exist, nothing happens. However, if it exists, the bundle will retrieve the value of the environment variable and set it as the value of the parameter. By default, the "raw" environment variable contains just a string. If you have another simple data type (like an integer or a boolean), you can use one of Symfony's env var processors to convert the string value of the env variable to the desired type (e.g. int:APP_BAZ, which converts the content of APP_BAZ to an int).

The environment variable handling happens transparently in the background, meaning that you can use the settings class as usual, and you (almost) do not have to care about the environment variables when using the settings.

Environment variable handling modes

The envVarMode option specifies how the environment variable should be handled. If no mode is specified, the mode EnvVarMode::INITIAL is used. In this mode the environment variable is only used to initialize the parameter. That means if the parameter is used the first time, instead of the default value in the code, the value of the environment variable is used. Users can change this value as they like, and the environment variable will not affect the parameter anymore. This mode allows a server administrator to set useful initial defaults via environment variables (e.g. while deploying the container), but users can change them completely later.

However, in some cases, you might want the server admin to enforce a certain value via environment variables and forbid users to change them via WebUI. For these cases, you can use the EnvVarMode::OVERWRITE and EnvVarMode::OVERWRITE_PERSIST mode. In this mode, the environment variable will always overwrite a parameter value, no matter what was set as a value before by users. This means that freshly retrieved settings will always have the value of the environment variable, even if the user changed it before. The OVERWRITE_PERSIST mode additionally writes the value back to the storage, so that the value is still set even after the env variable is removed (however users can then change the value again).

If a parameter is overwritten by an environment variable, its form field will be disabled in the default generated WebUI, so that users can see that the value is enforced by the environment variable and can not be changed via the WebUI.

A limitation of this system is that you can still change the value of a settings parameter in your code, even if it is overwritten by an environment variable. The changes will also be used in other parts of the application during the request. It is just that these changes do not get persisted, meaning that if you reload the settings from the storage, the value of the environment variable will be used again. If you try to change settings parameters via direct access in you code, you might want to check if the parameter is overwritten by an environment variable (by using the isEnvVarOverwritten method of the SettingsManager), and if so, you might want to disable the possibility to change the parameter in your code.

Environment variables mapper

For many constellations, the type conversion via the env var processor works fine. However, in some cases where you have more complex parameter types, you need a more complex conversion logic. For these cases, you can use the envVarMapper option of the SettingsParameter attribute. This option specifies a callable, which is called with the value of the environment variable and must return the value to set as the parameter value:

class TestSettings { #[SettingsParameter(envVar: 'string:ENV_VAR3', envVarMapper: [self::class, 'mapDateTimeEnv']) private ?\DateTime $dateTimeParam = null; public static function mapDateTimeEnv(?string $value): ?\DateTime { return $value ? new \DateTime($value) : null; } }
Salin selepas log masuk

The $value parameter passed, is the value retrieved from the environment variable, with env var processors applied, meaning that it not necessarily has to be a string.

Conclusion

You can see that jbtronics/settings-bundle can support you with handling changes in the schema of settings, and how to map environment variables to settings parameters. This allows you to have a flexible configuration system, which can be used by users and server administrators alike.

As always you can find more information in the bundle documentation.

Atas ialah kandungan terperinci Tetapan boleh dikonfigurasikan pengguna dalam aplikasi Symfony dengan jbtronics/settings-bundle (Bahagian Migrasi dan pembolehubah persekitaran. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!