swayok / laravel-site-loader

将单个项目(例如:后台和前端)的几个不同部分(站点)分离的类

dev-master 2019-04-16 12:32 UTC

This package is auto-updated.

Last update: 2024-09-16 23:27:49 UTC


README

例如:你有一个项目,其中包含几个非常不同的站点。比如说 - 这是前端、后台和超级管理员站点。所有这些站点都有不同的资源(视图、CSS、JS、图像等),但使用共同的DB模型、类等。分离它们将是一个糟糕的想法,可能会浪费很多时间。

那么如果我们使用服务提供者呢?

这可以在简单情况下完成。但是,如果您有一些 register() 和 provides() 方法,您将需要手动检测是否需要加载它们,您还需要为 boot() 方法执行相同的验证。当您有对相同 '\Class\Name' 的 '$this->app->singleton('\Class\Name', callback)' 调用,但具有不同的 'callback' 时,不使用条件留下这些方法可能是危险的。我遇到了很多问题,最终制作了这些类,以尽可能简单地解决这些问题。

如何使用它

1. 创建站点加载器

为您的项目中的每个站点创建一个扩展 \LaravelSiteLoader\AppSiteLoader 的加载器类。(或者您可以使用 \LaravelSiteLoader\AppSiteLoaderInterface 来创建自己的 \LaravelSiteLoader\AppSiteLoader 版本)

前端

namespace App\Frontend;

use LaravelSiteLoader\AppSiteLoader;

class FrontendSiteLoader extends AppSiteLoader {

    static public function canBeUsed() {
        return (
            $_SERVER['REQUEST_URI'] === '/'
            || empty($_SERVER['REQUEST_URI'])
            || starts_with($_SERVER['REQUEST_URI'], static::getBaseUrl())
        );
    }

    static public function getBaseUrl() {
        return '/account';
    }
    
    public function boot() {
        static::setLocale();
        // your code here
    }
    
    static public function getDefaultLocale() {
        return 'en';
    }
    
    public function register() {
        // your registrations here
    }

    public function provides() {
        // your privides list here
        return [];
    }
}

后台

namespace PeskyCMF\CMS\CmsAdmin;

use LaravelSiteLoader\AppSiteLoader;

class AdminSiteLoader extends AppSiteLoader {

    static public function getBaseUrl() {
        return '/admin';
    }
    
    public function boot() {
        static::setLocale();
        // your code here
    }
    
    static public function getDefaultLocale() {
        return 'en';
    }
    
    public function register() {
        // your registrations here
    }

    public function provides() {
        // your privides list here
        return [];
    }
}

\LaravelSiteLoader\AppSiteLoader 中有一些预定义字段

/** @var AppSitesServiceProvider */
protected $provider;
/** @var Application */
protected $app;

和函数

static public function canBeUsed() {
    return (
        $_SERVER['REQUEST_URI'] === '/'
        || empty($_SERVER['REQUEST_URI'])
        || starts_with($_SERVER['REQUEST_URI'], static::getBaseUrl())
    );
}

/**
 * @return ParameterBag
 */
protected function getAppConfig() {
    return config();
}

/**
 * Sets the locale if it exists in the session and also exists in the locales option
 *
 * @return void
 */
static public function setLocale() {
    $locale = session()->get(get_called_class() . '_locale');
    \App::setLocale($locale ?: static::getDefaultLocale());
}

/**
 * Configure session for current site
 * @param string $connection - connection name
 * @param int $lifetime - session lifetime in minutes
 */
public function configureSession($connection, $lifetime = 720) {
    $config = $this->getAppConfig()->get('session', ['table' => 'sessions', 'cookie' => 'session']);
    $this->getAppConfig()->set('session', array_merge($config, [
        'table' => $config['table'] . '_' . $connection,
        'cookie' => $config['cookie'] . '_' . $connection,
        'lifetime' => $lifetime,
        'connection' => $connection,
        'path' => static::getBaseUrl()
    ]));
}

如果需要特定内容,请覆盖它们。

2. 创建和配置特殊服务提供者

创建一个扩展 \LaravelSiteLoader\Providers\AppSitesServiceProvider 的单一服务提供者,并包含一些特定配置: protected $defaultSectionLoaderClassprotected $sectionLoaderClasses。我个人使用 AppServiceProvider 来做这个

namespace App\Providers;

use LaravelSiteLoader\Providers\AppSitesServiceProvider;
use App\Frontend\FrontendSiteLoader;
use App\CmsAdmin\AdminSiteLoader;

class AppServiceProvider extends AppSitesServiceProvider {
    protected $defaultSectionLoaderClass = FrontendSiteLoader::class;

    protected $sectionLoaderClasses = [
        AdminSiteLoader::class,
    ];
}

在这里

  • protected $defaultSectionLoaderClass 在无法使用 protected $sectionLoaderClasses 中的加载器时使用
  • protected $sectionLoaderClasses 是除默认加载器之外的所有站点加载器的列表

为了检测正确的加载器,\LaravelSiteLoader\Providers\AppSitesServiceProvider$this->sectionLoaderClasses 列表中的所有加载器类调用 AdminSiteLoader::canBeUsed() 方法。第一个返回 true 的加载器将被分配给 $this->siteLoader 属性。如果没有匹配的加载器,则将 $this->defaultSectionLoaderClass 加载器分配给 $this->siteLoader 属性,而不调用 canBeUsed() 方法

3. 将您的服务提供者添加到 config/app.php

注意

  • 在您的服务提供者中,您可以通过 $this->siteLoader 访问匹配的加载器

  • 如果您在服务提供者中覆盖了 boot()register()provides() 方法,请确保在您的方法中调用 parent::boot()parent::register()parent::provides() 方法,以保存加载器的功能。如果您的服务提供者中重载了 provides() 方法,此代码可能很有用

    public function provides() { return array_unique(array_merge( parent::provides(), [ \App\Http\Request::class, DbModel::class ] )); }

  • \LaravelSiteLoader\Providers\AppSitesServiceProvider 中,我重新声明了一些方法为公共

    public function loadTranslationsFrom($path, $namespace) public function loadViewsFrom($path, $namespace) public function publishes(array $paths, $group = null)

因此您可以在加载器中使用它们,通过 $this->provider->loadTranslationsFrom('/path', 'namespace')