__call 魔術方法使用
這個方法用來監視一個物件中的其它方法。如果你試著呼叫一個物件中不存在的方法,__call 方法將會被自動呼叫。
會省略部分程式碼,只挑取要講解的內容
Layout
- 佈局設定
/**
* Add a new column in layout.
*
* @param int $width
* @param \Closure $closure
*/
public function column($width, \Closure $closure)
{
if ($this->columns->isEmpty()) {
$column = $this->current;
$column->setWidth($width);
} else {
$column = new Column($width);
$this->current = $column;
}
$this->columns->push($column);
$closure($this->parent);
}
$content->row(function(Row $row) {
$row->column(4, 'foo');
$row->column(4, 'bar');
$row->column(4, 'baz');
});
----------------------------------
|foo |bar |baz |
| | | |
| | | |
| | | |
| | | |
| | | |
----------------------------------
Column
- row 獲取內容
- build 渲染輸出
/**
* Add a row for column.
*
* @param $content
*
* @return Column
*/
public function row($content)
{
if (!$content instanceof \Closure) {
$row = new Row($content);
} else {
$row = new Row();
call_user_func($content, $row);
}
ob_start();
$row->build();
$contents = ob_get_contents();
ob_end_clean();
return $this->append($contents);
}
/**
* Build column html.
*/
public function build()
{
$this->startColumn();
foreach ($this->contents as $content) {
if ($content instanceof Renderable || $content instanceof Grid) {
echo $content->render();
} else {
echo (string) $content;
}
}
$this->endColumn();
}
- 例子
ArticleController
protected function form()
{
$form = new Form(new Article());
$form->image('image', __('Image'));
return $form;
}
Form
- 欄位呼叫實現
- row 鏈式呼叫
class Form implements Renderable
{
use HasFields;
public function __call($method, $arguments)
{
if ($className = static::findFieldClass($method)) { // 查詢欄位是否有對應的類
$column = Arr::get($arguments, 0, ''); //[0];
$element = new $className($column, array_slice($arguments, 1)); // 例項化
$this->pushField($element);
return $element;
}
}
/**
* Add a row in form.
*
* @param Closure $callback
*
* @return $this
*/
public function row(Closure $callback): self
{
$this->rows[] = new Row($callback, $this);
return $this;
}
}
HasFields
- 定義欄位和類對應
/**
* 這裡的註釋IDE 會識別提示
*
* @method Field\Image image($column, $label = '')
*/
trait HasFields
{
/**
* Available fields.
*
* @var array
*/
public static $availableFields = [
'image' => Field\Image::class,
];
}
Image
- 前面設定的各種引數在這裡渲染
public function render()
{
return Admin::component($this->getView(), $this->variables());
}
HasAssets
- 渲染的具體實現
- 渲染結果
- 分析html
- 對 html dom 樹分析插入需要的程式碼
- 返回渲染後的字串
trait HasAssets
{
/**
* @param $component
*/
public static function component($component, $data = [])
{
$string = view($component, $data)->render();
$dom = new \DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML('<?xml encoding="utf-8" ?>'.$string);
libxml_use_internal_errors(false);
}
}
helpers
助手函式
- view 獲取例項,解析內容
- render 獲取內容
if (! function_exists('view')) {
/**
* Get the evaluated view contents for the given view.
*
* @param string|null $view
* @param \Illuminate\Contracts\Support\Arrayable|array $data
* @param array $mergeData
* @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
*/
function view($view = null, $data = [], $mergeData = [])
{
$factory = app(ViewFactory::class);
if (func_num_args() === 0) {
return $factory;
}
return $factory->make($view, $data, $mergeData);
}
}
form.blade.php
- row 呼叫渲染
- columns 呼叫渲染
<div class="box-body">
@if(!$tabObj->isEmpty())
@include('admin::form.tab', compact('tabObj'))
@else
<div class="fields-group">
@if($form->hasRows())
@foreach($form->getRows() as $row)
{!! $row->render() !!}
@endforeach
@else
@foreach($layout->columns() as $column)
<div class="col-md-{{ $column->width() }}">
@foreach($column->fields() as $field)
{!! $field->render() !!}
@endforeach
</div>
@endforeach
@endif
</div>
@endif
</div>
<!-- /.box-body -->
本作品採用《CC 協議》,轉載必須註明作者和本文連結