dongzha5934 2014-04-05 15:25
浏览 42
已采纳

在Lithium应用程序上设置多个webroot环境的最佳做法是什么?

I'm interested in having a unified backend environment for multiple users and having multiple frontend environments for users. All should run from a single application instance, which will be the equivalent of the app folder. I've gone back and forth on several configurations but keep running into inconsistencies once I get deeper into the app. Imagine something like the enterprise WordPress app: users need a unique webroot for their account for accessing their templates and digital assets, but one application instance runs the backend environment for all users. This is proving tricky on Lithium.

Right now, I set a basic environment parameter in the /[user]/webroot/index.php file, like so:

<?php

$env = ['webroot' => __DIR__, 'id' => 'generic_account'];

require dirname(dirname(__DIR__)) . '/app/config/bootstrap.php';

use lithium\action\Dispatcher;
use lithium\action\Request;

echo Dispatcher::run(new Request(compact('env')));

?>

Then, in the Dispatcher, I have an extension class map the account:

Dispatcher::applyFilter('run', function($self, $params, $chain) use (&$i) {
    Environment::set($params['request']);

    //Map $env['id'] value to stored database connection
    if (isset($params['request']->id)) {
        Accounts::load($params['request']);
    }

    foreach (array_reverse(Libraries::get()) as $name => $config) {
        if ($name === 'lithium') {
            continue;
        }
        $file = $config['path'] . '/config/routes.php';
        file_exists($file) ? call_user_func(function() use ($file) { include $file; }) : null;
    }
    return $chain->next($self, $params, $chain);
});

Finally, in the Accounts::load() method, I pull connection settings from a master database and set those as the default Connection configuration:

<?php

namespace app\extensions\core;

use app\models\Routes;
use lithium
et\http\Router;

class Accounts {

    public static function load(&$request) {
        if (!is_object($request)) {
            return false;
        }
        $class = [
            'accounts'      => 'app\models\Accounts',
            'plugins'       => 'app\extensions\core\Plugins',
            'prefs'         => 'app\extensions\core\Preferences',
            'connections'   => 'lithium\data\Connections',
            'inflector'     => 'lithium\util\Inflector',
            'exception'     => 'lithium
et\http\RoutingException'
        ];
        $class['accounts']::meta('connection', 'master');
        $bind = $class['prefs']::read('bind_account');
        $key = $bind == 'domain' || $bind == 'subdomain' ? 'HTTP_HOST' : 'id';
        $find = $class['accounts'] . '::' . $class['inflector']::camelize('find_by_' . $bind, false);
        $account = call_user_func($find, $request->env($key));

        if ($account == null) {
            throw new $class['exception']('Account `' . $request->env($key) . '` doesn\'t exist.');
        }
        $class['connections']::add('default', json_decode($account->database, true));
        $request->activeAccount = $account;
        $request->params['webroot'] = $request->env('webroot');
        $plugins = $class['plugins']::load();
        return true;
    }

    /**
     * Allows users to store customized route definitions in `routes` table,
     * hence the use of `app\models\Routes`.
     */
    public static function routes() {
        $routes = Routes::all();
        foreach ($routes as $route) {
            Router::connect($route->match, [
                'controller' => 'pages',
                'action' => 'view',
                'template' => $route->template,
                'layout' => $route->layout
            ]);
        }
    }
}

?>

All this seems to work well for routing URLs and allowing for multiple front-end webroots. Here's the trick: when creating a webroot for admin interfaces, it's turning into a convoluted mess for keeping the asset paths straight. I've used Media::assets() to try to overcome this, but I have a feeling there's a more elegant solution out there. I've struggled to find any other examples or documentation that specifically addresses this kind of setup concern.

  • 写回答

2条回答 默认 最新

  • duanbei7035 2014-04-06 15:25
    关注

    It's pretty straightforward, you're almost there. All you really need is a unique webroot/ directory per user, in addition to the normal bootstrap include and request-dispatching, you can include any other user-specific configuration, and register the main application, like so:

    Libraries::add('yourApp', [ 'path' => '/path/to/codebase', 'webroot' => __DIR__ ]);

    This gives you the centralized codebase, but also allows for a custom webroot per user.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大