ショコラ
Laravel Bladeのディレクティブを定義するには?
ディレクティブに渡せるパラメーターは1つ。複数渡すときは配列で渡す。
ディレクティブを定義したら、./artisan view:clear コマンド を実行する。
もっさん先輩
./artisan view:clear
手順
Blade のディレクティブを定義する手順
- 独自ディレクティブを AppServiceProvider.php の bootメソッド で定義します。
因みに、現在の app/Providers/AppServiceProvider.php です。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Blade::directive('exists' ,fn($var) => "<?php if (isset($var) && !in_array($var,[null,false,0,'',[]],true)): ?>");
Blade::directive('set' ,fn($var) => "<?php $var ?>");
Blade::directive('unset' ,fn($var) => "<?php unset($var) ?>");
Blade::directive('extract' ,fn($var) => "<?php extract($var) ?>");
Blade::directive('for_extract',fn($var) => "<?php \$__LOCALS ??= []; \$__LOCALS[\$loop->depth ?? 0] = get_defined_vars(); \$__currentLoopData = array($var)[0]; \$__env->addLoop(\$__currentLoopData); foreach(\$__currentLoopData as \$__): \$__env->incrementLoopIndices(); \$loop = \$__env->getLastLoop(); extract(\$__,isset(array($var)[1])?EXTR_PREFIX_ALL:EXTR_OVERWRITE,array($var)[1] ?? ''); ?>");
Blade::directive('endfor_extract',fn() => "<?php endforeach; \$__env->popLoop(); \$loop = \$__env->getLastLoop(); extract(\$__LOCALS[\$loop->depth ?? 0]); ?>");
Blade::directive('div' ,fn($times) => "<?php \$times = $times; if (0 == \$loop->index % $times): ?>");
Blade::directive('div_close' ,fn() => "<?php if (((0 != \$loop->index) && (0 == (\$loop->index + 1) % \$times)) || \$loop->last): ?>");
Blade::directive('enddiv' ,fn() => "<?php endif ?>");
Blade::directive('checked' ,fn($var) => "<?php if ($var) echo 'checked' ?>");
Blade::directive('selected' ,fn($var) => "<?php if ($var) echo 'selected' ?>");
Blade::directive('last' ,fn($var) => "<?php if (\$loop->last) echo $var ?>");
Blade::directive('script' ,fn() => "<?php \$__env->startPush('scripts') ?>");
Blade::directive('endscript' ,fn() => "<?php \$__env->stopPush() ?>");
Blade::directive('dialog' ,fn() => "<?php \$__env->startPush('dialogs') ?>");
Blade::directive('enddialog' ,fn() => "<?php \$__env->stopPush() ?>");
Blade::directive('parent' ,fn() => "window.livewire.all().find(i => -1 != i.__instance.childIds.indexOf('{{ \$_instance->id }}'))");
Blade::directive('config' ,fn($var) => "<?= _config($var) ?>");
Blade::directive('url' ,fn($var) => "<?= _url($var) ?>");
Blade::directive('action' ,fn() => "<?= _url(\Route::currentRouteName()) ?>");
Blade::directive('hidden' ,fn($vars) => "<?php foreach ([$vars] as \$var): ?><input type=\"hidden\" name=\"{{ \$var }}\" value=\"{{ \$\$var }}\"><?php endforeach ?>");
}
}
配置先:app/Libs/functions.php
@config、@urlディレクティブ を使うには、以下の _config、_url関数が必要です。
<?php
function numf($val):string
{
return is_numeric($val) ? number_format((float)$val) : '';
}
function formatDate($expr,$format):string
{
return date($format,strtotime($expr));
}
function headline($str,$width = 20)
{
$headline = $str;
if (mb_ereg("(.+?)(。|\n)",$str,$m)) {
$headline = $m[1];
}
return mb_strimwidth($headline,0,$width);
}
function flash($key, $message = null)
{
if (!is_null($message))
session()->flash($key,$message);
return session($key);
}
function render_blade(string $blade)
{
$tmpl = uniqid();
$file = resource_path('views/dynamic/'.$tmpl.'.blade.php');
try {
file_put_contents($file,$blade);
return view('dynamic.'.$tmpl)->render();
}
finally {
unlink($file);
}
}
function _config(string $key, $default = null)
{
return config($key) ?: env($key) ?: $default;
}
function _url(string $route = '', string $param = '')
{
if (str_starts_with($route,'/'))
[$route,$param] = ['',$route.$param];
static $cache = [];
if (!isset($cache[$route]))
if (\Route::has($route))
$cache[$route] = route($route);
elseif ('' == $route)
$cache[$route] = _config('APP_URL','//'.$_SERVER['HTTP_HOST']);
elseif ('' != ($cache[$route] = _config($route)))
;
else {
[$route,$param] = ['','/'.$route.$param];
$cache[$route] = _url($route);
}
return $cache[$route].$param;
}
過去に @phpディレクティブ で変数に0を入れていた処理がありましたので、今回 @setディレクティブ を作成してみました。
@set ( $i = 0 )
本来なら↓のように書きます。@php には @endphp が必要で、少し重い感じがします。
@php $i = 0 @endphp
- AppServiceProvider.php にディレクティブを定義したら、view:clearコマンド を実行します。
./artisan view:clear
Bladeディレクティブ を更新したら、毎回↑上のコマンドを実行する必要があります。
- たったこれだけで、ブレードで独自ディレクティブが使えるようになります。
@set、@unset、@exists の使用例です。
@set ( $i = 0 )
@set ( $i++ )
{{ $i }}
@set ( $j = 100 )
@set ( $j++ )
{{ $i }},{{ $j }}
@set ( $i = 100; $j = 200 )
{{ $i }},{{ $j }}
@exists ($i)
値があります。
@endif
@unset ($i)
@empty ($i)
値はありません。
@endif
@div,@div_close,@divend の使用例です。
<table>
@foreach ([0,1,2,3,4,5,6,7,8,9] as $i)
@div (3)
{{-- $loop->index が3で割り切れた時に入ります。 --}}
<tr>
@enddiv
<td>{{ $i }} </td>
@div_close
{{-- $loop->index + 1 が3で割り切れた時に入ります。 --}}
</tr>
@enddiv
@endforeach
</table>
@config,@url の使用例です。
<a href="@url">@config('APP_NAME')</a>
<a href="@url('register')">会員登録(ルートで指定)</a>
<a href="@url('/aaa/bbb/ccc','?a=123')">パスとクエリで指定</a>
以上