Kích hoạt / vô hiệu hóa các tính năng trong ứng dụng Laravel


10

Tôi đang xây dựng một ứng dụng Laravel, có một số tính năng khác nhau. Tôi muốn có thể bật hoặc tắt chúng tùy thuộc vào yêu cầu của một tên miền cụ thể. Hiện tại, trong cấu hình của tôi có một loạt các cờ như:

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

... và như thế.

Sau đó, trong bộ điều khiển và chế độ xem của mình, tôi kiểm tra các giá trị cấu hình đó để xem liệu tôi có nên hiển thị thứ gì đó hay không, cho phép một số hành động nhất định, v.v. Ứng dụng của tôi bắt đầu bị ô nhiễm với các loại kiểm tra này ở mọi nơi.

Có phương pháp thực hành tốt nhất để quản lý các tính năng trong ứng dụng Laravel không?


vô hiệu hóa tuyến đường thay vì bộ điều khiển? hoặc có thể sử dụng phần mềm trung gian
Berto99

Tính năng! == trang.
StackOverflowNewbie


Có thể thực sự là một giải pháp. Bạn muốn làm cho nhận xét của bạn thành một câu trả lời?
StackOverflowNewbie

Không có vấn đề gì, không phải là một câu trả lời, điều quan trọng là nó có thể giúp bạn
Berto99

Câu trả lời:


4

Đây được gọi là cờ tính năng về mặt kỹ thuật - https://martinfowler.com/articles/feature-tlass.html

phụ thuộc vào yêu cầu của bạn, cờ trong cấu hình / cơ sở dữ liệu, triển khai, v.v ...

Nhưng về cơ bản là nếu trong mã và không thể sạch.

Gói Laravel:

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

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

Một số dịch vụ:

https://launchdarkly.com/

https://bONS-train.io/

https://configcat.com/

Ngoài ra, hãy xem https: // marketingpl platform.google.com/about/optizes/ cho lối vào.


1
Bạn có thể tìm thấy một dự án laravel mẫu với tính năng gắn cờ ở đây: github.com/configcat/php-sdk/tree/master/samples/laravel
Peter

7

Tôi đã gặp phải vấn đề tương tự khi tôi cố gắng thực hiện nhiều nhà cung cấp khách sạn.

Những gì tôi đã làm là sử dụng dịch vụ container.

Đầu tiên bạn sẽ tạo lớp cho mỗi miền Với các tính năng của anh ấy:

  • như Doman1.php, Domain2.php
  • sau đó bên trong mỗi một trong những bạn sẽ thêm logic của bạn.

sau đó bạn sẽ sử dụng ràng buộc trong nhà cung cấp dịch vụ ứng dụng của mình để liên kết tên miền với lớp để sử dụng.

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

Ghi chú rằng bạn có thể sử dụng lớp chung chứa các tính năng đi với tất cả các miền sau đó sử dụng lớp chung đó trong các lớp của bạn

Cuối cùng, trong bộ điều khiển của bạn, bạn có thể kiểm tra tên miền của mình sau đó để sử dụng lớp bạn sẽ sử dụng

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

0

Có vẻ như bạn là những thứ mã hóa cứng dựa trên các giá trị cấu hình để bật hoặc tắt các tính năng nhất định. Tôi khuyên bạn nên kiểm soát mọi thứ dựa trên các tuyến đường được đặt tên thay vì giá trị cấu hình.

  1. Nhóm tất cả các tuyến đường như một toàn bộ hoặc theo tính năng khôn ngoan.
  2. Xác định tên cho tất cả các tuyến
  3. Kiểm soát hoạt động bật / tắt theo tên tuyến và bản ghi trong cơ sở dữ liệu
  4. Sử dụng phần mềm trung gian của Laravel để kiểm tra xem một tính năng cụ thể được bật hay tắt bằng cách lấy tên tuyến hiện tại từ đối tượng yêu cầu và khớp với cơ sở dữ liệu ..

do đó, bạn sẽ không có cùng điều kiện lặp lại mọi nơi và làm phồng mã của bạn .. đây là mã mẫu cho bạn biết cách truy xuất tất cả các tuyến và bạn có thể khớp tên nhóm tuyến để xử lý thêm để phù hợp với tình huống của bạn.

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

và đây là một trình xử lý phần mềm trung gian mẫu, nơi bạn có thể kiểm tra xem một tính năng cụ thể có hoạt động hay không bằng cách khớp với những gì bạn đã lưu trữ trong cơ sở dữ liệu của mình ..

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

1
Điều này giả định rằng các tính năng tương đương với các trang trên trang web, phải không? Đó không phải là trường hợp. Một tính năng có thể là một số đoạn trong một trang (ví dụ: Google Map sẽ hiển thị trong thanh bên) hoặc một số loại chức năng (ví dụ: người dùng có thể xuất một số dữ liệu).
StackOverflowNewbie

bạn đúng, tuy nhiên, ý bạn là một số khối được hiển thị trên các trang khác nhau? những hạn chế của bạn để hiển thị nó là gì? trang cụ thể khôn ngoan hoặc trên tất cả các trang bạn hiển thị nó
Akram Wahid

Các tính năng có thể là toàn bộ trang hoặc chỉ là một phần của trang hoặc chỉ là một số chức năng.
StackOverflowNewbie

0

Giả sử rằng các tính năng đó chỉ cần thiết cho các yêu cầu HTTP.

Tôi sẽ tạo một Featureslớp cơ sở mặc định với tất cả các cờ mặc định:

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

Sau đó, tôi sẽ mở rộng lớp đó cho mỗi Tên miền và đặt các phần ghi đè cần thiết cho tên miền đó:

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

Sau đó tạo Middleware để liên kết Lớp tính năng với vùng chứa:

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

Đừng quên đính kèm phần mềm trung gian này vào các tuyến đường của bạn: cho một nhóm hoặc cho từng tuyến.

Sau này, bạn có thể Gõ lớp Tính năng của mình trong bộ điều khiển:

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

0

Laravel rất tuyệt với điều này, bạn thậm chí có thể lưu trữ các tính năng của mình trong db và tạo mối quan hệ giữa tên miền.

Tôi khuyên bạn nên sử dụng Gates và Chính sách, điều này sẽ giúp bạn kiểm soát tốt hơn trong các bộ điều khiển và mẫu lưỡi cắt của mình. Điều này có nghĩa là bạn đăng ký các cổng từ db của bạn hoặc mã cứng chúng.

Ví dụ: nếu bạn có tính năng xuất sản phẩm bằng một nút trong hệ thống của mình và bạn muốn cung cấp tính năng đó cho một số người dùng, bạn có thể đăng ký cổng với logic nghiệp vụ.

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

Sau đó, bạn có thể làm như sau trong bộ điều khiển

<?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
    }
}

Dưới đây là một ví dụ cho các mẫu lưỡi của bạn:

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

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

thêm thông tin có sẵn tại https://laravel.com/docs/5.8/authorization


0

Trường hợp thú vị bạn có ở đây. Thật thú vị khi xem xét một Featuregiao diện hoặc lớp trừu tượng có chứa một vài phương thức mà bạn thường cần.

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(...);

    ...
}

Bạn thậm chí có thể chia những thứ này vào ExecutableFeatureRenderableFeature.

Hơn nữa về một số loại nhà máy có thể được thực hiện để làm cho cuộc sống dễ dàng hơn.

// 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

Những gì tôi đã làm trong trường hợp của tôi là tạo một bảng mới trên cơ sở dữ liệu, bạn có thể gọi nó là Domainsví dụ.

Thêm tất cả các tính năng cụ thể, những tính năng có thể được hiển thị trên một số tên miền nhưng không có trong phần còn lại, dưới dạng cột cho bảng đó dưới dạng bit cho các giá trị boolean. Giống như, trong trường hợp của tôi , allow_multiple_bookings.use_company_card ... bất cứ điều gì.

Sau đó, hãy xem xét việc tạo một lớp Domainvà kho lưu trữ tương ứng của nó và chỉ cần hỏi các giá trị này trên mã của bạn, cố gắng đẩy logic đó càng nhiều càng tốt vào miền của bạn (mô hình, dịch vụ ứng dụng, v.v.).

Chẳng hạn, tôi sẽ không kiểm tra phương thức điều khiển RequestBookingnếu tên miền đang yêu cầu đặt chỗ chỉ có thể yêu cầu một hoặc nhiều.

Thay vào đó, tôi làm điều RequestBookingValidatorServiceđó để có thể kiểm tra xem thời gian đặt phòng đã qua chưa, người dùng có thẻ tín dụng được kích hoạt hay không, hoặc Tên miền mà hành động này xuất phát được phép yêu cầu nhiều hơn một lần đặt phòng (và sau đó nếu nó đã có bất kì).

Điều này thêm sự tiện lợi của khả năng đọc, vì bạn đã đẩy quyết định này đến các dịch vụ ứng dụng của mình. Ngoài ra, tôi thấy rằng bất cứ khi nào tôi cần một tính năng mới, tôi có thể sử dụng di chuyển Laravel (hoặc Symfony) để thêm tính năng đó trên bảng và tôi thậm chí có thể cập nhật các hàng của nó (tên miền của bạn) với các giá trị tôi muốn trên cùng một cam kết mà tôi đã mã hóa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.