Laravel Uygulamasında Özellikleri Etkinleştirme / Devre Dışı Bırakma


10

Çeşitli özelliklere sahip bir Laravel uygulaması geliştiriyorum. Belirli bir alanın gereksinimine bağlı olarak bunları etkinleştirmek veya devre dışı bırakmak istiyorum. Şu anda, benim yapılandırma gibi bir dizi bayrak var:

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

... ve bunun gibi.

Daha sonra denetleyicilerimde ve görünümlerimde, bir şey görüntüleyip görüntülememem, belirli eylemlere izin verme vb. Olup olmadığını görmek için bu yapılandırma değerlerini kontrol ediyorum.

Laravel uygulamasındaki özellikleri yönetmek için en iyi uygulama yöntemi var mı?


kontrolör yerine güzergahlar devre dışı bırakılsın mı? veya middleware kullanarak belki
Berto99

Özellik! == sayfa.
StackOverflowNewbie


Aslında bir çözüm olabilir. Yorumunuzu bir cevap haline getirmek ister misiniz?
StackOverflowNewbie

mh sorun değil, bir cevap değil, önemli size yardımcı olabilir
Berto99

Yanıtlar:


4

Buna teknik olarak özellik bayrakları denir - https://martinfowler.com/articles/feature-toggles.html

Gereksinimlerinize, yapılandırma / veritabanındaki bayraklar, sunum vb.

Ama temelde kod ve temiz olamaz.

Laravel paketleri:

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

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

Bazı hizmetler:

https://launchdarkly.com/

https://bullet-train.io/

https://configcat.com/

Ayrıca ön uç için https://marketingplatform.google.com/about/optimize/ adresine bakın.


1
Özellik işaretlemesi içeren örnek bir laravel projesi burada bulabilirsiniz: github.com/configcat/php-sdk/tree/master/samples/laravel
Peter

7

Birden fazla otel sağlayıcısı uygulamaya çalışırken aynı sorunla karşılaştım.

Yaptığım hizmet kabını kullanmaktı.

ilk önce her bir alan için kendi özellikleriyle sınıf oluşturacaksınız:

  • Doman1.php, Domain2.php gibi
  • sonra her birinin içine mantığını ekleyeceksin.

Sonra sen kullanımına sınıfla alanı bağlar uygulama servis sağlayıcısı bağlayıcı kullanmak vuracak.

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

Not sonra Sınıflarınızdaki genel sınıfını kullanan tüm alanlarla genel özellikleri tutan sınıfını gider kullanabilirsiniz

Sonunda oyun kumandanızda alan adınızı kontrol edebilir ve daha sonra kullanacağınız sınıfı kullanabilirsiniz

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

0

Belirli özellikleri etkinleştirmek veya devre dışı bırakmak için yapılandırma değerlerine dayalı sabit kodlama yaptığınızı düşünün. Yapılandırma değeri yerine adlandırılmış rotalara göre kontrol etmenizi öneririz.

  1. Tüm rotayı bir bütün olarak veya özellik bakımından gruplandırın.
  2. Tüm rotalar için ad tanımlayın
  3. Etkinleştirme / devre dışı bırakma etkinliğini rota adına göre denetleme ve veritabanına kaydetme
  4. Geçerli yol adını istek nesnesinden alıp veritabanıyla eşleştirerek belirli bir özelliğin etkinleştirilip etkinleştirilmediğini kontrol etmek için Laravel ara katman yazılımını kullanın.

böylece her yerde yinelenen aynı koşullara sahip olmayacaksınız ve kodunuzu şişireceksiniz .. İşte size tüm rotaları nasıl alacağınızı gösteren bir örnek kod ve durumunuzu eşleştirmek için daha fazla işlem yapmak için rota grubu adını eşleştirebilirsiniz.

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

ve burada belirli bir özelliğin etkin olup olmadığını kontrol edebileceğiniz örnek bir ara katman yazılımı işleyicisi.

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

1
Bu, özelliklerin sitedeki sayfalara eşit olduğunu varsayar, değil mi? Konu bu değil. Özellik, bir sayfadaki bazı snippet'ler (ör. Kenar çubuğunda bir Google Haritası görüntülenecektir) veya bir tür işlevsellik (ör. Kullanıcılar bazı verileri dışa aktarabilir) olabilir.
StackOverflowNewbie

haklısın, ancak farklı sayfalarda görüntülenen bazı blokları mı kastediyorsun? görüntülemek için kısıtlamalarınız nelerdir? akıllıca veya görüntülediğiniz tüm sayfalarda
Akram Wahid

Özellikler bir sayfanın tamamı veya bir sayfanın yalnızca bir bölümü veya yalnızca bazı işlevler olabilir.
StackOverflowNewbie

0

Bu özelliklerin yalnızca HTTP istekleri için gerekli olduğu varsayılarak.

FeaturesTüm varsayılan bayrakları ile bir varsayılan temel sınıf oluşturmak istiyorum :

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

Sonra her etki alanı için bu sınıfı genişletmek ve bu etki alanı için gereken geçersiz kılmaları ayarlayın:

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

Ardından, özellikler sınıfını kapsayıcıya bağlamak için bir Middleware oluşturun:

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

Bu ara katmanı rotalarınıza eklemeyi unutmayın: bir gruba veya her rota için.

Bundan sonra, denetleyicilerinizde Özellikler sınıfınızı TypeHint yapabilirsiniz:

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

0

Laravel bununla harika, hatta db'de özelliklerinizi saklayabilir ve etki alanı arasında bir ilişki oluşturabilirsiniz.

Denetleyicilerinizde ve blade şablonlarınızda size daha iyi kontrol sağlayacak Gates ve Politikaları kullanmanızı öneririm. Bu sizin db veya sabit kod onları kapıları kayıt anlamına gelir.

Örneğin, sisteminizde bir düğmeyle dışa aktarma ürünleri özelliğiniz varsa ve bu özelliği bazı kullanıcılar için kullanılabilir yapmak istiyorsanız, kapıları iş mantığına kaydedebilirsiniz.

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

Daha sonra kontrol cihazlarında aşağıdakileri yapabilirsiniz

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

Blade şablonlarınıza bir örnek:

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

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

daha fazla bilgiyi https://laravel.com/docs/5.8/authorization adresinde bulabilirsiniz.


0

Burada ilginç bir durum var. Genel Featureolarak ihtiyacınız olan birkaç yöntemi içeren bir arayüze veya soyut sınıfa bakmak ilginç olabilir .

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

    ...
}

Bunları ExecutableFeatureve içine ayırabilirsiniz RenderableFeature.

Ayrıca hayatı kolaylaştırmak için bir çeşit fabrika sınıfı yapılabilir.

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

Benim durumumda yaptığım, veritabanında yeni bir tablo oluşturmaktı, Domainsörneğin diyebilirsiniz .

Bazı etki alanlarında gösterilebilecek ancak geri kalanında gösterilemeyen tüm belirli özellikleri, boole değerleri için bit olarak bu tablonun sütunları olarak ekleyin. Benim durumumda allow_multiple_bookings, use_company_card... ... her neyse.

Ardından, bir sınıf Domainve ilgili havuzu oluşturmayı düşünün ve kodunuzda bu değerleri isteyin, bu mantığı alanınıza (modeliniz, uygulama hizmetleriniz, vb.) Mümkün olduğunca zorlamaya çalışın.

Örneğin, RequestBookingrezervasyon isteyen etki alanının yalnızca bir veya daha fazlasını isteyebilmesi için denetleyici yöntemini denetlemezdim .

Bunun yerine RequestBookingValidatorService, rezervasyon tarihinin geçip geçmediğini, kullanıcının etkin bir kredi kartına sahip olup olmadığını veya ... hiç).

Bu kararı uygulama hizmetlerinize ilettiğiniz için okunabilirliğin rahatlığını artırır. Ayrıca, yeni bir özelliğe ihtiyaç duyduğumda, masaya bu özelliği eklemek için Laravel (veya Symfony) geçişlerini kullanabileceğimi ve hatta satırlarını (alanlarınızı) kodladığım aynı taahhütte istediğim değerlerle güncelleyebileceğimi görüyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.