Загрузить ресурсы поставщика из пользовательского каталога - cakephp 3

Я хочу создать пакет поставщика в cakephp 3. Это должно зависеть от другого пакета, в котором есть как файлы php, так и некоторые статические ресурсы: например, js, css, img и т. Д. Настройка автозагрузки файлов php, с которой я могу справиться. Однако для загрузки статических файлов от другого поставщика, например

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

торт ожидает, что они должны быть внутри каталога 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

Единственная похожая проблема, которую я обнаружил, - это копирование файлов в корневой каталог , чего я не хочу делать.

Как я могу сказать, что торт загружает файлы поставщика из их точных папок, а не из веб-корневого каталога? Или как лучше решить эту проблему, не копируя что-то. Я использую композитор.

Спасибо


person dav    schedule 03.04.2016    source источник
comment
См. Мой новый ответ на вопрос, о котором вы говорите stackoverflow.com/questions/26736656/   -  person Yaroslav    schedule 14.08.2019


Ответы (2)


Вы делаете это на Linux? Если это так, вы можете просто создать символическую ссылку, чтобы корневой каталог webroot указывал прямо на корневой каталог пакета.

person user3268305    schedule 06.03.2019

Вы используете композитор? Зависит ли проект, над которым вы работаете, от пакета поставщика в вашем файле composer.json? Если это так, вы можете создать в своем проекте контроллер (что-то вроде ExternalAssets), который может читать файлы этих поставщиков и передавать их объекту 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'
]) ?>">
person Brian F    schedule 03.10.2019