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条)

报告相同问题?

悬赏问题

  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?