从自定义目录加载供应商资产 - cakephp 3

时间:2016-04-03 21:45:03

标签: cakephp composer-php cakephp-3.x

我想在cakephp 3中创建供应商包。它应该依赖于另一个包,包含php文件和一些静态资产:如js,css,img等。设置php文件自动加载我能够处理。但是要加载来自其他供应商的静态文件,例如

echo $this->Html->css('AnotherPackage.styles');

cake希望它们应该在供应商的webroot目录中,而不是

# another package's files
/vendor/author/another-package/php
/vendor/author/another-package/css_files
/vendor/author/another-package/js_files
/vendor/author/another-package/images

我发现的类似问题只有copying files to webroot,这是我不想做的事情。

如何告诉蛋糕从其确切的文件夹而不是webroot加载供应商的文件?或者以更好的方式解决这个问题,而不必复制某些东西。我正在使用作曲家。

由于

2 个答案:

答案 0 :(得分:0)

您是否正在Linux机器上执行此操作?如果是这样,您可以只创建一个符号链接,以使webroot目录指向软件包的根目录。

答案 1 :(得分:0)

您在使用作曲家吗? 您正在处理的项目是否取决于composer.json文件中供应商的软件包? 如果是这样,您可以在项目中创建一个Controller(类似于ExternalAssets),该Controller可以读取这些供应商文件,并将它们传递给Response对象。

<?php
/**
 * ExternalAssetsController
 */

namespace App\Controller;

use App\Controller\Controller\AppController;
use Cake\Core\App;
use Cake\Http\Exception\BadRequestException;
use Cake\Http\Exception\ForbiddenException;
use Cake\Routing\Router;

/**
 * ExternalAssets Controller
 *
 * Serves up external assets that aren't in the webroot folder.
 */
class ExternalAssetsController extends AppController
{
    /**
     * Initialize method.
     *
     * @return void
     */
    public function initialize()
    {
        parent::initialize();

        $this->loadComponent('RequestHandler');
        // see https://book.cakephp.org/3.0/en/development/routing.html#routing-file-extensions
        // or whatever extensions you need.
        Router::extensions(['css', 'js', 'png', 'jpg']);

        // if you're using the auth component in a restricted way.
        $authAllowedActions = ['asset'];
        $this->Auth->allow($authAllowedActions);
    }

    /**
     * Delivers an asset.
     *
     * @param string|null $folder The Folder's name.
     * @param string|null $file The File's name.
     * @return \Cake\Http\Response
     * @throws \Cake\Http\Exception\BadRequestException When $folder or $file isn't set.
     * @throws \Cake\Http\Exception\ForbiddenException When we can't read the file.
     */
    public function asset($folder = null, $file = null)
    {
        if (!$folder) {
            throw new BadRequestException(__('Folder was not defined'));
        }
        if (!$file) {
            throw new BadRequestException(__('File was not defined'));
        }
        $folder = str_replace('..', '', $folder);
        $file = str_replace('..', '', $file);

        $basepath = realpath(ROOT . DS . 'vendor' . DS . 'author' . DS . 'another-package');
        $path = realpath(ROOT . DS . 'vendor' . DS . 'author' . DS . 'another-package' . DS . $folder . DS . $file . '.' . $this->getRequest()->getParam('_ext'));

        if (strpos($path, $basepath) === false) {
            throw new ForbiddenException(__('Path out of bounds, possible hack attempt.'));
        }

        if (!is_readable($path)) {
            throw new ForbiddenException(__('Unable to read the file.'));
        }

        $this->setResponse($this->getResponse()->withFile($path, [
            'name' => $file . '.' . $this->getRequest()->getParam('_ext'),
            'download' => false
        ]));

        return $this->getResponse();
    }
}

然后使用Router::url()创建到控制器的编译路径。 像这样:

<link rel="stylesheet" href="<?=Router::url([
    'prefix' => false,
    'plugin' => false, // unless the controller in in a plugin
    'controller' => 'ExternalAssets'
    'action' => 'asset'
    0 => 'css_files',
    1 => 'css_file_name',
    '_ext' => 'css'
]) ?>">