การเปิด / ปิดการใช้งานคุณสมบัติในแอพ Laravel


10

ฉันกำลังสร้างแอป Laravel ซึ่งมีคุณสมบัติหลายอย่าง ฉันต้องการที่จะเปิดใช้งานหรือปิดการใช้งานพวกเขาขึ้นอยู่กับความต้องการของโดเมนที่เฉพาะเจาะจง ขณะนี้ฉันมีชุดธงหลายรายการเช่น:

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

... และต่อไป

จากนั้นในตัวควบคุมและมุมมองของฉันฉันตรวจสอบค่ากำหนดเหล่านั้นเพื่อดูว่าฉันควรจะแสดงบางสิ่งบางอย่างหรือไม่อนุญาตให้ดำเนินการบางอย่าง ฯลฯ แอปของฉันเริ่มที่จะได้รับมลพิษด้วยการตรวจสอบเหล่านี้ทุกที่

มีวิธีปฏิบัติที่ดีที่สุดในการจัดการคุณสมบัติในแอป Laravel หรือไม่?


ปิดใช้งานเส้นทางแทนคอนโทรลเลอร์หรือไม่ หรือใช้มิดเดิลแวร์อาจ
Berto99

คุณสมบัติ! == หน้า
StackOverflow สมัคร

amybe นี้หรือไม่ github.com/francescomalatesta/laravel-feature
Berto99

จริง ๆ แล้วอาจเป็นทางออก ต้องการแสดงความคิดเห็นของคุณเป็นคำตอบหรือไม่?
StackOverflow สมัครใหม่

mh ไม่มีปัญหาไม่ใช่คำตอบสิ่งสำคัญคือมันอาจช่วยคุณได้
Berto99

คำตอบ:


4

เทคนิคนี้เรียกว่าการตั้งค่าสถานะคุณลักษณะ - https://martinfowler.com/articles/feature-toggles.html

ขึ้นอยู่กับความต้องการของคุณตั้งค่าสถานะในการกำหนดค่า / ฐานข้อมูลการเปิดตัว ฯลฯ ...

แต่โดยทั่วไปแล้วถ้าอยู่ในรหัสและไม่สามารถทำความสะอาดได้

แพ็คเกจ Laravel:

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

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

บริการบางอย่าง:

https://launchdarkly.com/

https://bullet-train.io/

https://configcat.com/

ดูที่https://marketingplatform.google.com/about/optimize/สำหรับส่วนหน้า


1
คุณสามารถหาตัวอย่างโครงการ laravel ที่มีการตั้งค่าสถานะคุณลักษณะได้ที่นี่: github.com/configcat/php-sdk/tree/master/samples/laravel
Peter

7

ฉันพบปัญหาเดียวกันเมื่อพยายามใช้ผู้ให้บริการโรงแรมหลายแห่ง

สิ่งที่ฉันทำคือใช้คอนเทนเนอร์เซอร์วิส

ก่อนอื่นคุณต้องสร้างคลาสสำหรับแต่ละโดเมนด้วยคุณสมบัติของเขา:

  • เช่น Doman1.php, Domain2.php
  • จากนั้นภายในแต่ละอันคุณจะเพิ่มตรรกะของคุณ

จากนั้นคุณจะใช้การรวมในผู้ให้บริการแอพเพื่อผูกโดเมนกับคลาสที่จะใช้

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

หมายเหตุคุณสามารถใช้คลาสทั่วไปที่เก็บคุณสมบัติไปกับโดเมนทั้งหมดจากนั้นใช้คลาสทั่วไปในคลาสของคุณ

สุดท้ายในคอนโทรลเลอร์คุณสามารถตรวจสอบโดเมนของคุณจากนั้นใช้คลาสที่คุณจะใช้

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

0

ดูเหมือนว่าคุณกำลังเขียนโค้ดอย่างหนักตามค่ากำหนดเพื่อเปิดใช้งานหรือปิดใช้งานคุณสมบัติบางอย่าง ฉันแนะนำให้คุณควบคุมสิ่งต่าง ๆ ตามเส้นทางที่ตั้งชื่อแทนที่จะเป็นค่ากำหนด

  1. จัดกลุ่มเส้นทางทั้งหมดโดยรวมหรือตามคุณสมบัติที่ชาญฉลาด
  2. กำหนดชื่อสำหรับเส้นทางทั้งหมด
  3. ควบคุมกิจกรรมเปิด / ปิดโดยใช้ชื่อเส้นทางและบันทึกในฐานข้อมูล
  4. ใช้ Laravel middleware เพื่อตรวจสอบว่ามีการเปิดใช้งานหรือปิดใช้งานคุณลักษณะเฉพาะโดยรับชื่อเส้นทางปัจจุบันจากวัตถุที่ร้องขอและจับคู่กับฐานข้อมูล ..

ดังนั้นคุณจะไม่มีเงื่อนไขเดียวกันซ้ำทุกที่และขยายรหัสของคุณ .. นี่คือตัวอย่างรหัสแสดงวิธีดึงข้อมูลเส้นทางทั้งหมดและคุณสามารถจับคู่ชื่อกลุ่มเส้นทางเพื่อดำเนินการต่อเพื่อให้ตรงกับสถานการณ์ของคุณ

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

และนี่คือตัวจัดการมิดเดิลแวร์ตัวอย่างที่คุณสามารถตรวจสอบว่าคุณลักษณะเฉพาะทำงานอยู่หรือไม่โดยการจับคู่กับสิ่งที่คุณเก็บไว้ในฐานข้อมูลแล้ว

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

1
ซึ่งถือว่าเป็นคุณลักษณะที่เท่ากับหน้าเว็บในไซต์ใช่ไหม นั่นไม่ใช่กรณี คุณลักษณะอาจเป็นข้อมูลโค้ดบางส่วนภายในหน้า (เช่น Google แผนที่จะแสดงในแถบด้านข้าง) หรือฟังก์ชั่นบางอย่าง (เช่นผู้ใช้สามารถส่งออกข้อมูลบางส่วน)
StackOverflow สมัคร

คุณถูกต้อง แต่คุณหมายถึงบางส่วนของบล็อกที่แสดงในหน้าอื่น ๆ หรือไม่? คุณมีข้อ จำกัด อะไรในการแสดง หน้าเฉพาะที่ชาญฉลาดหรือในทุกหน้าที่คุณแสดง
Akram Wahid

คุณสมบัติสามารถเป็นได้ทั้งหน้าหรือเพียงบางส่วนของหน้าหรือเพียงแค่การใช้งานบางอย่าง
StackOverflow สมัคร

0

สมมติว่าฟีเจอร์เหล่านั้นจำเป็นสำหรับการร้องขอ HTTP เท่านั้น

ฉันจะสร้างFeaturesคลาสพื้นฐานเริ่มต้นด้วยค่าสถานะเริ่มต้นทั้งหมด:

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

จากนั้นฉันจะขยายคลาสนั้นสำหรับแต่ละโดเมนและตั้งค่าการแทนที่ที่จำเป็นสำหรับโดเมนนั้น:

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

จากนั้นสร้าง Middleware เพื่อเชื่อมโยงฟีเจอร์คลาสเข้ากับคอนเทนเนอร์:

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

อย่าลืมแนบมิดเดิลแวร์นี้กับเส้นทางของคุณ: ไปยังกลุ่มหรือสำหรับแต่ละเส้นทาง

หลังจากนี้คุณสามารถพิมพ์คำแนะนำระดับคุณลักษณะของคุณในตัวควบคุมของคุณ:

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

0

Laravel ยอดเยี่ยมด้วยสิ่งนี้คุณยังสามารถจัดเก็บคุณสมบัติของคุณใน db และสร้างความสัมพันธ์ระหว่างโดเมน

ฉันขอแนะนำให้ใช้เกตส์และนโยบายซึ่งจะช่วยให้คุณสามารถควบคุมตัวควบคุมและแม่แบบเบลดได้ดีขึ้น ซึ่งหมายความว่าคุณลงทะเบียนประตูจากฐานข้อมูลหรือรหัสยาก

ตัวอย่างเช่นหากคุณมีคุณสมบัติส่งออกผลิตภัณฑ์ที่มีปุ่มในระบบของคุณและคุณต้องการให้ผู้ใช้บางรายสามารถใช้คุณลักษณะดังกล่าวได้คุณสามารถลงทะเบียนประตูด้วยตรรกะทางธุรกิจ

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

จากนั้นคุณสามารถทำสิ่งต่อไปนี้ในตัวควบคุม

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

นี่คือตัวอย่างสำหรับแม่แบบใบมีดของคุณ:

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

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

ข้อมูลเพิ่มเติมสามารถดูได้ที่https://laravel.com/docs/5.8/authorization


0

กรณีที่น่าสนใจคุณมีที่นี่ อาจเป็นเรื่องที่น่าสนใจที่จะดูFeatureอินเทอร์เฟซหรือคลาสนามธรรมที่มีวิธีการบางอย่างที่คุณต้องการโดยทั่วไป

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

    ...
}

คุณยังสามารถแบ่งเหล่านี้ลงและExecutableFeatureRenderableFeature

นอกจากนี้ในบางระดับของโรงงานอาจทำให้ชีวิตง่ายขึ้น

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

สิ่งที่ฉันทำในกรณีของฉันคือการสร้างตารางใหม่ในฐานข้อมูลคุณสามารถเรียกมันได้Domainsเช่น

เพิ่มคุณสมบัติเฉพาะทั้งหมดซึ่งสามารถแสดงในบางโดเมนได้ แต่ไม่ใช่ส่วนที่เหลือเป็นคอลัมน์สำหรับตารางนั้นเป็นบิตสำหรับค่าบูลีน เช่นเดียวกับในกรณีของฉันallow_multiple_bookings, use_company_card... สิ่งที่

จากนั้นให้พิจารณาสร้างคลาสDomainและพื้นที่เก็บข้อมูลตามลำดับและขอค่าเหล่านี้ในรหัสของคุณพยายามที่จะผลักดันตรรกะนั้นในโดเมนของคุณ (โมเดลบริการแอปพลิเคชันบริการ ฯลฯ ) ให้มากที่สุด

ตัวอย่างเช่นฉันจะไม่ตรวจสอบวิธีการควบคุมRequestBookingหากโดเมนที่ขอจองสามารถขอเพียงหนึ่งหรือมากกว่า

แต่ฉันจะทำในสิ่งRequestBookingValidatorServiceที่สามารถตรวจสอบว่าเวลาการจองผ่านหรือไม่ผู้ใช้มีบัตรเครดิตที่เปิดใช้งาน ... หรือโดเมนที่การกระทำนี้มาจากได้รับอนุญาตให้ร้องขอมากกว่าหนึ่งการจอง (และถ้ามันมีอยู่แล้ว ใด ๆ )

สิ่งนี้จะเพิ่มความสะดวกในการอ่านเนื่องจากคุณได้ผลักดันการตัดสินใจนี้ไปยังบริการแอปพลิเคชันของคุณ นอกจากนี้ฉันพบว่าเมื่อใดก็ตามที่ฉันต้องการคุณสมบัติใหม่ที่ฉันสามารถใช้การย้าย Laravel (หรือ Symfony) เพื่อเพิ่มคุณสมบัตินั้นบนตารางและฉันยังสามารถอัปเดตแถว (โดเมนของคุณ) ด้วยค่าที่ฉันต้องการในรหัสเดียวกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.