Skip to content

Latest commit

 

History

History
192 lines (154 loc) · 4.93 KB

include.md

File metadata and controls

192 lines (154 loc) · 4.93 KB

include

@include指令的实现很容易理解,它相当于渲染一遍include进来的模板,然后把渲染后的内容填充到模板中。

//src/Illuminate/View/Compilers/Concerns/CompilesIncludes.php

/**
 * Compile the include statements into valid PHP.
 *
 * @param  string  $expression
 * @return string
 */
protected function compileInclude($expression)
{
    $expression = $this->stripParentheses($expression);

    return "<?php echo \$__env->make({$expression}, array_except(get_defined_vars(), array('__data', '__path')))->render(); ?>";
}

它还有几个变种的指令,@includeIf@includeWhen以及@includeFirst,对应的实现如下:

//src/Illuminate/View/Compilers/Concerns/CompilesIncludes.php

/**
 * Compile the include-if statements into valid PHP.
 *
 * @param  string  $expression
 * @return string
 */
protected function compileIncludeIf($expression)
{
    $expression = $this->stripParentheses($expression);

    return "<?php if (\$__env->exists({$expression})) echo \$__env->make({$expression}, array_except(get_defined_vars(), array('__data', '__path')))->render(); ?>";
}

/**
 * Compile the include-when statements into valid PHP.
 *
 * @param  string  $expression
 * @return string
 */
protected function compileIncludeWhen($expression)
{
    $expression = $this->stripParentheses($expression);

    return "<?php echo \$__env->renderWhen($expression, array_except(get_defined_vars(), array('__data', '__path'))); ?>";
}

/**
 * Compile the include-first statements into valid PHP.
 *
 * @param  string  $expression
 * @return string
 */
protected function compileIncludeFirst($expression)
{
    $expression = $this->stripParentheses($expression);

    return "<?php echo \$__env->first({$expression}, array_except(get_defined_vars(), array('__data', '__path')))->render(); ?>";
}

具体的逻辑都下放到$__env对象里了。

@includeIf是在@include的基础上,先判断模板文件是否存在,存在的情况下才渲染。

//src/Illuminate/View/Factory.php

/**
 * Determine if a given view exists.
 *
 * @param  string  $view
 * @return bool
 */
public function exists($view)
{
    try {
        $this->finder->find($view);
    } catch (InvalidArgumentException $e) {
        return false;
    }

    return true;
}

@includeWhen是在@include的基础上,先判断表达式的值是否为真。

//src/Illuminate/View/Factory.php

/**
 * Get the rendered content of the view based on a given condition.
 *
 * @param  bool  $condition
 * @param  string  $view
 * @param  array   $data
 * @param  array   $mergeData
 * @return string
 */
public function renderWhen($condition, $view, $data = [], $mergeData = [])
{
    if (! $condition) {
        return '';
    }

    return $this->make($view, $this->parseData($data), $mergeData)->render();
}

@includeFirst是在@include的基础上,渲染最先找到的那个模板文件。

//src/Illuminate/View/Factory.php

/**
 * Get the first view that actually exists from the given list.
 *
 * @param  array  $views
 * @param  array   $data
 * @param  array   $mergeData
 * @return \Illuminate\Contracts\View\View
 */
public function first(array $views, $data = [], $mergeData = [])
{
    $view = collect($views)->first(function ($view) {
        return $this->exists($view);
    });

    if (! $view) {
        throw new InvalidArgumentException('None of the views in the given array exist.');
    }

    return $this->make($view, $data, $mergeData);
}

Blade还支持一个结合了循环以及include的指令:@each,具体用法请参考文档。

它的实现如下:

//src/Illuminate/View/Factory.php

/**
 * Get the rendered contents of a partial from a loop.
 *
 * @param  string  $view
 * @param  array   $data
 * @param  string  $iterator
 * @param  string  $empty
 * @return string
 */
public function renderEach($view, $data, $iterator, $empty = 'raw|')
{
    $result = '';

    // If is actually data in the array, we will loop through the data and append
    // an instance of the partial view to the final result HTML passing in the
    // iterated value of this data array, allowing the views to access them.
    if (count($data) > 0) {
        foreach ($data as $key => $value) {
            $result .= $this->make(
                $view, ['key' => $key, $iterator => $value]
            )->render();
        }
    }

    // If there is no data in the array, we will render the contents of the empty
    // view. Alternatively, the "empty view" could be a raw string that begins
    // with "raw|" for convenience and to let this know that it is a string.
    else {
        $result = Str::startsWith($empty, 'raw|')
                    ? substr($empty, 4)
                    : $this->make($empty)->render();
    }

    return $result;
}

它依次使用$data中的元素去渲染$view,然后把渲染后的结果拼接在一起。如果$data为空,那么 就渲染默认模板或者输出一段字符串。