Mengaktifkan / Menonaktifkan Fitur di Aplikasi Laravel


10

Saya sedang membangun aplikasi Laravel, yang memiliki sejumlah berbagai fitur. Saya ingin dapat mengaktifkan atau menonaktifkannya tergantung pada persyaratan domain tertentu. Saat ini, di config saya ada serangkaian flag seperti:

'is_feature_1_enabled' => true,
'is_feature_2_enabled' => false,

... dan seterusnya.

Kemudian pada pengendali dan pandangan saya, saya memeriksa nilai-nilai konfigurasi untuk melihat apakah saya harus menampilkan sesuatu atau tidak, memungkinkan tindakan tertentu, dll. Aplikasi saya mulai tercemar dengan jenis-jenis cek ini di mana-mana.

Apakah ada metode praktik terbaik dalam mengelola fitur di aplikasi Laravel?


nonaktifkan rute bukan pengontrol? atau menggunakan middleware mungkin
Berto99

Fitur! == halaman.
StackOverflowNewbie


Sebenarnya bisa jadi solusi. Ingin membuat komentar Anda menjadi jawaban?
StackOverflowNewbie

mh tidak masalah, bukan jawaban, yang penting itu mungkin bisa membantu Anda
Berto99

Jawaban:


4

Ini secara teknis disebut fitur flags - https://martinfowler.com/articles/feature-toggles.html

tergantung pada kebutuhan Anda, flag di config / database, rollout, dll ...

Tapi itu pada dasarnya kalau ada dalam kode dan tidak bisa bersih.

Paket Laravel:

https://github.com/alfred-nutile-inc/laravel-feature-flag

https://github.com/francescomalatesta/laravel-feature

Beberapa layanan:

https://launchdarkly.com/

https://bullet-train.io/

https://configcat.com/

Lihat juga https://marketingplatform.google.com/about/optimize/ untuk tampilan depan .


1
Anda dapat menemukan proyek sampel laravel dengan penandaan fitur di sini: github.com/configcat/php-sdk/tree/master/samples/laravel
Peter

7

Saya mengalami masalah yang sama ketika saya mencoba menerapkan beberapa penyedia hotel.

Apa yang saya lakukan adalah menggunakan wadah layanan.

pertama Anda akan membuat kelas untuk setiap domain Dengan fitur-fiturnya:

  • seperti Doman1.php, Domain2.php
  • kemudian di dalam masing-masing Anda akan menambahkan logika Anda.

maka Anda akan menggunakan pengikatan di penyedia layanan aplikasi Anda untuk mengikat domain dengan kelas yang akan digunakan.

$this->app->bind('Domain1',function (){
       return new Domain1();
    });
    $this->app->bind('Domain2',function (){
        return new Domain2();
    });

Catatan Anda dapat menggunakan kelas umum yang berisi fitur-fitur yang ada di semua domain lalu gunakan kelas umum itu di kelas Anda

Akhirnya di controller Anda, Anda dapat memeriksa domain Anda kemudian menggunakan kelas yang akan Anda gunakan

    app(url('/'))->methodName();

0

Sepertinya Anda mengkodekan hal-hal berdasarkan nilai konfigurasi untuk mengaktifkan atau menonaktifkan fitur tertentu. Saya sarankan Anda untuk mengontrol hal-hal berdasarkan rute yang ditentukan daripada nilai konfigurasi.

  1. Kelompokkan semua rute secara keseluruhan atau berdasarkan fitur.
  2. Tentukan nama untuk semua rute
  3. Kontrol aktivitas aktifkan / nonaktifkan dengan nama rute dan catat dalam basis data
  4. Gunakan Laravel middleware untuk memeriksa apakah fitur tertentu diaktifkan atau dinonaktifkan dengan mendapatkan nama rute saat ini dari objek permintaan dan mencocokkannya dengan database ..

jadi Anda tidak akan memiliki kondisi yang sama mengulangi setiap tempat dan mengasapi kode Anda .. di sini adalah kode sampel menunjukkan kepada Anda cara mengambil semua rute, dan Anda dapat mencocokkan nama grup rute untuk proses lebih lanjut agar sesuai dengan situasi Anda.

Route::get('routes', function() {
$routeCollection = Route::getRoutes();

echo "<table >";
    echo "<tr>";
        echo "<td width='10%'><h4>HTTP Method</h4></td>";
        echo "<td width='10%'><h4>Route</h4></td>";
        echo "<td width='80%'><h4>Corresponding Action</h4></td>";
    echo "</tr>";
    foreach ($routeCollection as $value) {
        echo "<tr>";
            echo "<td>" . $value->getMethods()[0] . "</td>";
            echo "<td>" . $value->getPath() . "</td>";
            echo "<td>" . $value->getName() . "</td>";
        echo "</tr>";
    }
echo "</table>";
});

dan di sini adalah contoh middleware handler di mana Anda dapat memeriksa apakah fitur tertentu aktif dengan mencocokkan dengan apa yang sudah Anda simpan di database Anda ..

public function handle($request, Closure $next)
    {
        if(Helper::isDisabled($request->route()->getName())){
             abort(403,'This feature is disabled.');
        }
        return $next($request);
    }

1
Ini mengasumsikan bahwa fitur sama dengan halaman di situs, kan? Bukan itu masalahnya. Fitur dapat berupa cuplikan dalam halaman (mis. Google Map akan ditampilkan di sidebar), atau semacam fungsionalitas (mis. Pengguna dapat mengekspor beberapa data).
StackOverflowNewbie

Anda benar, namun maksud Anda beberapa blok yang ditampilkan pada halaman yang berbeda? apa kendala Anda untuk menampilkannya? halaman khusus atau pada semua halaman yang Anda tampilkan
Akram Wahid

Fitur dapat berupa seluruh halaman, atau hanya sebagian dari halaman, atau hanya beberapa fungsi.
StackOverflowNewbie

0

Dengan asumsi bahwa fitur-fitur itu hanya diperlukan untuk permintaan HTTP.

Saya akan membuat Featureskelas dasar default dengan semua flag standar:

Class Features {
    // Defaults
    protected $feature1_enabled = true;
    protected $feature2_enabled = true;

    public function isFeature1Enabled(): bool
    {
        return $this->feature1_enabled;
    }

    public function isFeature2Enabled(): bool
    {
        return $this->feature2_enabled;
    }
}

Lalu saya akan memperluas kelas itu untuk setiap Domain dan mengatur penggantian yang diperlukan untuk domain itu:

Class Domain1 extends Features {
    // override
    protected $feature1_enabled = false;
}

Kemudian buat Middleware untuk mengikat Kelas Fitur ke wadah:

class AssignFeatureByDomain
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        switch ($_SERVER['HTTP_HOST']) {
            case 'domain1':
                app()->bind(Features::class, Domain1::class);
                break;
            default:
                abort(401, 'Domain rejected');
        }

        return $next($request);
    }
}

Jangan lupa untuk melampirkan middleware ini ke rute Anda: ke grup atau untuk setiap rute.

Setelah ini, Anda bisa mengetikkan kelas Fitur di pengontrol Anda:

public function index(Request $request, Features $features)
{
    if ($features->isFeature1Enabled()) {
        //
    }
}

0

Laravel hebat dengan ini, Anda bahkan dapat menyimpan fitur Anda di db, dan membuat hubungan antara domain.

Saya akan merekomendasikan untuk menggunakan Gates dan Kebijakan, yang akan memberi Anda kontrol yang lebih baik di controller dan template blade Anda. Ini berarti Anda mendaftarkan gerbang dari db atau kode keras Anda.

Misalnya jika Anda memiliki fitur produk ekspor dengan tombol di sistem Anda dan Anda ingin membuat fitur itu tersedia untuk beberapa pengguna, Anda dapat mendaftarkan gerbang dengan logika bisnis.

//Only admins can export products
Gate::define('export-products', function ($user) {
    return $user->isAdmin;
});

Kemudian Anda dapat melakukan hal berikut di pengontrol

<?php

namespace App\Http\Controllers;

use App\Product;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class ProductsController extends Controller
{
    /**
     * Export products
     *
     * @param  Request  $request
     * @param  Post  $post
     * @return Response
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function export(Request $request)
    {
        $this->authorize('export-products');

        // The current user can export products
    }
}

Berikut ini contoh template templat Anda:

@can('export-products', $post)
    <!-- The Current User Can export products -->
@endcan

@cannot('export-products')
    <!-- The Current User Can't export products -->
@endcannot

informasi lebih lanjut tersedia di https://laravel.com/docs/5.8/authorization


0

Kasus menarik yang Anda miliki di sini. Mungkin menarik untuk melihat Featureantarmuka atau kelas abstrak yang berisi beberapa metode yang biasanya Anda butuhkan.

interface Feature
{
    public function isEnabled(): bool;

    public function render(): string;

    // Not entirely sure if this would be a best practice but the idea is to be
    // able to call $feature->execute(...) on any feature.
    public function execute(...);

    ...
}

Anda bahkan dapat membagi ini menjadi ExecutableFeaturedan RenderableFeature.

Selanjutnya pada beberapa jenis kelas pabrik dapat dibuat untuk membuat hidup lebih mudah.

// Call class factory.
Feature::make('some_feature')->render();
...->isEnabled();

// Make helper method.
feature('some_feature')->render();

// Make a blade directives.
@feature('some_feature')
@featureEnabled('some_feature')

0

Apa yang saya lakukan dalam kasus saya adalah membuat tabel baru pada database, Anda bisa menyebutnya Domainssebagai contoh.

Tambahkan semua fitur spesifik, yang dapat ditampilkan pada beberapa domain tetapi tidak di sisanya, sebagai kolom untuk tabel itu sebagai bit untuk nilai boolean. Seperti, dalam kasusku allow_multiple_bookings,, use_company_card... terserahlah.

Kemudian, pertimbangkan untuk membuat kelas Domaindan repositori masing-masing, dan tanyakan saja nilai-nilai ini pada kode Anda, mencoba untuk mendorong sebanyak mungkin logika itu ke domain Anda (model Anda, layanan aplikasi, dll).

Misalnya, saya tidak akan melakukan pemeriksaan pada metode pengontrol karena RequestBookingjika domain yang meminta pemesanan hanya dapat meminta satu atau lebih.

Alih-alih, saya melakukannya pada suatu RequestBookingValidatorServiceyang dapat memeriksa apakah waktu pemesanan telah berlalu, pengguna memiliki kartu kredit yang diaktifkan, ... atau dari Domain tempat tindakan ini diizinkan untuk meminta lebih dari satu pemesanan (dan kemudian jika sudah memiliki apa saja).

Ini menambah kenyamanan keterbacaan, karena Anda telah mendorong keputusan ini ke layanan aplikasi Anda. Juga, saya menemukan bahwa setiap kali saya memerlukan fitur baru saya dapat menggunakan migrasi Laravel (atau Symfony) untuk menambahkan fitur itu di atas meja dan saya bahkan dapat memperbarui barisnya (domain Anda) dengan nilai-nilai yang saya inginkan pada komit yang sama dengan yang saya beri kode.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.