Как отобразить теги Laravel внутри html, хранящегося в s3 - PullRequest
1 голос
/ 11 июля 2020

Добрый день всем.

Как сказано в заголовке вопроса, у меня есть код шаблона HTML, хранящийся в s3 с тегами Laravel, скажем:

<html>
<head>
    <title>{{ $landing->title }}</title>
</head>
<body>
@foreach($landing->products as $product)
    <p>{{ $product->title }}</p>
@endforeach
</body>
</html>

Затем я хотел бы отобразить это как обработанное после обработки html с замененными тегами Laravel, как если бы это был обычный шаблон лезвия.

В моем контроллере у меня есть это:

print_r( view('render', compact('template', 'landing'))->render() );

(не хочу показывать в нем браузер, просто получите код html)

А в render.blade.php у меня:

{!! html_entity_decode($template->html()) !!}

Но это покажет мне код с тегами Laravel без надлежащей замены.

Есть ли на этом индикаторы? Любая помощь будет оценена по достоинству.

1 Ответ

1 голос
/ 11 июля 2020

Я вижу два возможных решения этой проблемы.

  1. Скомпилируйте лезвие самостоятельно (не оптимально IMO)

Вы можете создать вспомогательную функцию, которая будет компилировать лезвие для вы, учитывая строку. ( исходный код )

помощники. php (Или где бы вы ни хотели найти функцию)

function compile_blade($markup, $data = []) {
    $fs = new \Illuminate\Filesystem\Filesystem;
    $b = new \Illuminate\View\Compilers\BladeCompiler($fs, __DIR__);
    $src = $b->compileString($markup);

    $isPhp = false;
    if (substr( $src, 0, 5 ) === "<?php")
    {
        $isPhp = true;
        $src = substr($src, 5);
    }
    
    $tempFileName = tempnam("/tmp", "blade-compile");
    file_put_contents($tempFileName, $src);

    ob_start();

    extract($data);

    include $tempFileName;
    $out = ob_get_clean();
    if ($isPhp)
    {
        $out = '<?php'.$out;
    }
    
    return $out;
}

Затем в вашем контроллере вы должны предварительно обработать s3 blade для использования в вашем файле render.blade. php, например:

    return view('render', [
        'template' => compile_blade($template, $landing),
        'landing' => $landing,
    ));

Я не думаю, что это оптимальное решение, поскольку вы все равно создаете файлы.

Создайте новое пространство имен для blade-сервера / html из s3.

Сначала вам нужно создать в своем проекте папку, например ./storage/local/blade. Затем вам нужно добавить пространство имен для представлений в этой папке, например:

AppServiceProvider. php

public function boot()
{
    ...

    view()->addNamespace('s3', storage_path('/local/views');
    ...
}

Теперь, чтобы обработать получение разметки из s3 (в вашем контроллере или в другом месте ) вы бы сделали что-то вроде:

    // Lets say the file on s3 is markup.blade.php
    $contents = Storage::disk('s3')->get('path/to/markup.blade.php')
    Storage::disk('local')->put(storage_path('local/views/markup.blade.php'), $contents);

Теперь, если ваш render.blade. php используется исключительно для рендеринга разметки на s3, вы должны просто использовать вместо этого новое представление с пространством имен. Вы можете использовать это в своем контроллере, например:

    return view('s3::markup', compact('landing'));

Это становится немного сложнее, если вы хотите использовать разметку s3 в одном из других ваших файлов лезвий. Но это можно сделать, расширив лезвие, как в этом сообщении .

Blade::extend(function($view, $compiler)
{
    $pattern = $compiler->createMatcher('includeNamespaced');

    $viewPath = realpath($compiler->getPath());
    $parts = explode(DIRECTORY_SEPARATOR, $viewPath);
    $viewsDirectoryIndex = array_search('views', $parts);
    $namespace = $parts[$viewsDirectoryIndex + 1];

    $php = '$1<?php ';
    $php .= 'if($__env->exists(\''.$namespace.'.\'.$2)){';
    $php .= 'echo $__env->make(\''.$namespace.'.\'.$2)->render();';
    $php .= '}';
    $php .= 'else {';
    $php .= 'echo $__env->make($2)->render();';
    $php .= '}';
    $php .= '?>';

    return preg_replace($pattern, $php, $view);
});

Теперь вы можете @include представление с пространством имен в ваших файлах лезвия, например:

    @includeNamespaced('s3/markup')

Другая причина, по которой я предпочитаю решение 2, заключается в том, что вы можете получить некоторый эффект "кеширования", если посмотрите, существует ли уже файл в local / views, перед загрузкой из s3. Затем вы можете создать запланированное задание, которое удаляет файлы в хранилище / local / views старше некоторого ограничения по времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...