귀하는 로그인되어 있지 않습니다. 이대로 편집하면 귀하의 IP 주소가 편집 기록에 남게 됩니다.스팸 방지 검사입니다. 이것을 입력하지 마세요!{{틀:상위문서|라이믹스/매뉴얼}} == 개요 == '''템플릿 문법 v2'''는 [[라이믹스/릴리즈 노트/2.1.8|라이믹스 2.1.8]]부터 프리뷰 형식으로 제공되고, '''라이믹스 2.2부터 정식 지원'''할 템플릿 문법이다.<ref name="v2">[https://rhymix.org/manual/theme/template_v2 템플릿 문법 v2 - 라이믹스 매뉴얼]</ref> Laravel Blade 문법을 기반으로 하되, 라이믹스의 구조와 기능에 맞게 여러 지시자(directive)가 추가되었다. 기존 v1 문법 중 안정성과 편리함이 검증된 요소도 상당수 그대로 유지되어 두 문법을 섞어 쓸 수 있다.<ref name="v2" /> 다만 '''Laravel Blade를 그대로 가져다 쓰는 것이 아니다.''' PHP 지원 범위, 서로 다른 출처의 모듈과 스킨을 조합하는 라이믹스의 특성, <code>Context</code> 변수 참조 방식, v1 문법 유지 등의 이유로 Laravel의 코드를 그대로 쓰기 어려워, "Blade 스타일"의 문법만 차용하고 컴파일러는 자체 구현하였다. 따라서 세부 해석 방식에 차이가 있을 수 있다.<ref name="v2" /> 이 문서에서는 공식 매뉴얼의 표현을 따라 Blade 스타일 문법을 '''v2 정규 문법''', v1과 호환되는 문법을 '''v1 호환 문법'''으로 부른다. 두 문법은 충돌하지 않지만, 가능하면 v2 정규 문법만 쓰는 것이 권장된다.<ref name="v2" /> == 버전 표기 == 확장자가 <code>.blade.php</code>인 파일은 모두 v2로 인식한다. VSCode, PHPStorm, IntelliJ 등 대부분의 편집기에서 Blade 플러그인을 설치하면 문법 강조와 자동 완성을 쓸 수 있다.<ref name="v2" /> 확장자가 <code>.html</code>인 파일에서 v2 문법을 쓰려면 최상단에 버전을 표기해야 한다. <syntaxhighlight lang="html"> @version(2) </syntaxhighlight> <syntaxhighlight lang="html"> <config version="2" /> </syntaxhighlight> == v1과의 차이 == === 문법 비교 === v1의 조건문·루프문에서 좌우의 주석을 지우면 Blade 지시자와 거의 같은 형태가 된다. 라이믹스가 차기 템플릿 문법으로 Blade를 채택한 이유 중 하나다.<ref name="v2" /> <syntaxhighlight lang="html"> @if ($condition) <div class="comment">{{ $comment }}</div> @endif </syntaxhighlight> <syntaxhighlight lang="html"> <!--@if($condition)--> <div class="comment">{$comment}</div> <!--@end--> </syntaxhighlight> === 문맥에 맞는 자동 이스케이프 === 템플릿에서 출력하는 '''모든 데이터는 자동으로 escape되며, 이를 일괄 해제하는 옵션은 제공하지 않는다.''' 필요한 곳에서만 <code>noescape</code> 필터나 <code>{!! $var !!}</code> 문법으로 개별 해제한다. 이미 escape된 데이터를 이중 인코딩하지는 않는다.<ref name="v2" /> <code><nowiki><script></nowiki></code> 태그 안에서는 문맥을 자동으로 인식하여 HTML이 아닌 JS 문법에 맞게 escape한다. 예를 들어 <code><</code>는 HTML 문맥에서 <code>&lt;</code>, JS 문맥에서 <code><</code>로 변환된다.<ref name="v2" /> === 일관성 있는 Context 참조 === v1에서는 <code><nowiki><?php ?></nowiki></code>로 PHP 코드를 직접 쓰면 <code>Context</code>를 참조하지 않는 로컬 변수가 생겨 <code>{@ ...}</code> 문법의 변수와 연동되지 않는 불편이 있었다. v2에서는 템플릿에서 쓰는 모든 변수가 항상 일관되게 <code>Context</code>를 참조한다.<ref name="v2" /> === 제거된 문법 === XE 1.4.4 이후 수많은 템플릿 해석 오류의 원인이 되어 온 <code><nowiki><block></nowiki></code> 가상 태그, <code>loop</code> 속성, <code>cond</code> 속성을 '''지원하지 않는다.''' 사용하면 출력물에 소스가 그대로 남거나 오류가 발생할 수 있다.<ref name="v2" /> <code><nowiki><include></nowiki></code>의 <code>cond</code> 속성과 <code>|cond=""</code> 문법은 계속 지원하지만, <code>@class</code>, <code>@style</code>, <code>@selected</code> 등으로 바꾸는 것이 권장된다. == 데이터 출력 == 표준은 중괄호 두 쌍이다. v1처럼 한 쌍만 써도 되지만, 중괄호 바로 안쪽에 공백이 있으면 안 된다. <syntaxhighlight lang="html"> {{ $var }} {{ $oDocument->getNickName() }} </syntaxhighlight> 한 쌍만 쓰면 클로저처럼 중괄호가 포함된 코드를 쓸 수 없고, 중괄호 안에서 줄바꿈을 할 수 없다. === 단일 중괄호가 금지되는 위치 === v1 호환 문법은 일반적인 CSS·JS 문법과 충돌하는 경우가 많아, '''라이믹스 2.1.22부터 CSS·JS 문맥에서는 허용하지 않는다.''' 아래 위치에서는 반드시 중괄호 두 쌍을 써야 한다.<ref name="v2" /> * <code><nowiki><script></nowiki></code> 태그 안 * <code><nowiki><style></nowiki></code> 태그 안 * <code>onclick</code> 등 이벤트 핸들러 속성 안 * <code>pattern</code> 속성 안 (2.1.25~) * <code><nowiki><a href="javascript:..."></nowiki></code> 등 JS를 쓰는 속성 안 * 모든 태그의 <code>style</code> 속성 안 === 변수의 유효 범위 === 템플릿의 변수는 모두 <code>Context</code>와 연동된다. 모듈이나 위젯에서 <code>Context::set('foo', $value)</code>로 설정했거나 <code>$_GET['foo']</code>로 들어온 값을 템플릿에서 <code>$foo</code>로 참조할 수 있고, 반대로 템플릿에서 <code>$foo</code>를 조작하면 다른 자료에서 <code>Context::get('foo')</code>로 바뀐 값을 읽을 수 있다. 즉 <code>Context</code>를 공용 상태 저장소로 쓴다.<ref name="v2" /> 다음은 <code>Context</code>와 연동되지 않는다. * 변수와 함께 인클루드한 템플릿 안의 변수 * <code>$_SERVER</code>, <code>$_SESSION</code>, <code>$GLOBALS</code> 등 초전역변수 * <code>Template</code> 인스턴스를 가리키는 <code>$this</code> * 변수 앞에 <code>\</code>를 붙인 <code>\$foo</code> — 로컬 변수가 된다. 클로저를 선언할 때도 이 방법을 써야 한다 <syntaxhighlight lang="html"> {{ implode(', ', array_map(function(\$i) { return \$i * 1000; }, $list)) }} </syntaxhighlight> :※ 템플릿 컴파일러가 내부적으로 쓰는 로컬 변수는 <code>$__tmp</code>처럼 '''언더바 두 개로 시작'''하는 것이 많다. 충돌을 피하려면 그런 이름은 쓰지 말자.<ref name="v2" /> === 출력 필터 === v1과 같은 출력 필터를 지원하며, <code>|</code> 좌우에 공백을 허용하는 점이 다르다. 필터명과 옵션은 <code>:</code>로 구분한다. <syntaxhighlight lang="html"> {{ $var|lower|escape }} {{ $timestamp|date:'n/j H:i' }} </syntaxhighlight> {| class="wikitable" ! 필터 !! 기능 !! 옵션 |- | autoescape || 자동 escape (이중 인코딩 안 함) || |- | autolang || 자동 escape하되 언어코드는 escape하지 않음 || |- | escape || 강제 escape (이중 인코딩) || |- | escapejs || JS 문자열에 넣을 수 있는 형태로 escape || |- | noescape || escape하지 않음 || |- | json || JSON으로 인코딩 (<code>@json</code> 권장) || |- | strip / strip_tags || <code>strip_tags()</code> || |- | trim || <code>trim()</code> || |- | urlencode || <code>rawurlencode()</code> || |- | lower / upper || 대소문자 변환 || |- | nl2br || 개행을 <code><nowiki><br></nowiki></code>로 변환 || |- | join || 배열을 문자열로 합침 || 구분자 (기본 <code>,</code>) |- | date || 타임스탬프 포맷 || 포맷 (기본 <code>Y-m-d H:i:s</code>) |- | format / number_format || 천 단위 쉼표 || 소수점 자릿수 (기본 0) |- | shorten / number_shorten || <code>123.4K</code> 형태로 표시 || 소수점 자릿수 (기본 2) |- | link || 문자열을 링크로 표시 || 링크 텍스트 |} <code>|</code>를 필터가 아닌 뜻으로 쓸 때는 <code>||</code> 연산자, 문자열 안의 <code>'|'</code>, <code>\|</code> 이스케이프 세 가지만 허용된다.<ref name="v2" /> == 조건문과 루프문 == PHP의 대체 문법(alternative syntax)에 <code>@</code>를 붙인 형태가 원칙이다. <code>@if</code>와 괄호 사이를 띄어도 되고, <code>@endif</code>를 <code>@end</code>로 줄여도 된다. <syntaxhighlight lang="html"> @if ($condition1) <div class="foo"></div> @elseif ($condition2) <div class="bar"></div> @else <div class="baz"></div> @endif </syntaxhighlight> {{인용문|괄호를 쓰는 Blade 스타일 지시자는 모두 정규식(PCRE)으로 해석된다. 복잡한 자료 구조를 즉석에서 선언하거나 문자열 안에 괄호를 넣어 해석을 방해하면 v1의 <code>loop</code>, <code>cond</code> 속성처럼 오작동할 수 있다. 복잡한 자료 구조는 따로 선언한 뒤 변수만 넘기자.}} === forelse === if문과 foreach문을 결합한 형태로, 배열이 비었을 때 표시할 내용을 쉽게 지정한다. 중간 지시자가 <code>@else</code>가 아니라 '''<code>@empty</code>'''임에 유의해야 한다. <syntaxhighlight lang="html"> @forelse ($array as $key => $val) <div class="item">{{ $val->name }}</div> @empty <div class="noitem">항목이 없습니다.</div> @endforelse </syntaxhighlight> === 루프 변수 === <code>@foreach</code>, <code>@forelse</code>에서 <code>$loop</code> 변수를 쓸 수 있다. {| class="wikitable" ! 속성 !! 타입 !! 의미 |- | <code>$loop->index</code> || int || 현재 인덱스 (0부터) |- | <code>$loop->iteration</code> || int || 현재 반복 횟수 (1부터) |- | <code>$loop->remaining</code> || int || 남은 횟수 |- | <code>$loop->count</code> || int || 총 반복 횟수 |- | <code>$loop->first</code> || bool || 첫 번째 항목인가 |- | <code>$loop->last</code> || bool || 마지막 항목인가 |- | <code>$loop->even</code> / <code>odd</code> || bool || 짝수·홀수번째인가 |- | <code>$loop->depth</code> || int || 중첩 루프의 깊이 (1부터) |- | <code>$loop->parent</code> || object 또는 null || 상위 루프 변수 |} <code>@for</code>, <code>@while</code>, <code>@switch</code>도 지원하며 <code>@continue</code>, <code>@break</code>, <code>@default</code>를 쓸 수 있다. === 라이믹스 전용 조건문 === Blade 10.x의 조건문은 <code>@hasSection</code>을 제외하고 모두 지원하며, <code>@auth</code>와 <code>@can</code> 등은 라이믹스의 권한 체계에 맞게 재해석되었다. 마치는 지시자는 모두 <code>@end</code>로 줄일 수 있다.<ref name="v2" /> {| class="wikitable" ! 지시자 !! 조건 |- | <code>@admin</code> || 최고관리자 |- | <code>@auth</code> || 로그인한 회원 |- | <code>@auth('admin')</code> || 최고관리자 |- | <code>@auth('manager')</code> || 게시판 관리자 |- | <code>@guest</code> || 로그인하지 않음 |- | <code>@can('view')</code> || <code>$grant->view</code> 권한 있음 |- | <code>@cannot('view')</code> || 해당 권한 없음 |- | <code>@canany(['view', 'write_comment'])</code> || 나열한 권한 중 하나 이상 있음 |- | <code>@desktop</code> || PC |- | <code>@mobile</code> || 모바일 |- | <code>@isset($foo)</code> / <code>@unset($foo)</code> / <code>@empty($foo)</code> || Context 변수의 존재 여부 |- | <code>@env('foo')</code> || 환경변수 존재 |} :※ <code>@mobile</code>의 판정 기준이 바뀌었다. '''2.1.21 이전'''은 모바일 뷰 설정과 <code>m</code> 파라미터의 영향을 받았지만, '''2.1.22 이후'''는 접속한 User-Agent와 "태블릿도 모바일 취급" 설정만 따른다.<ref name="v2" /> == 템플릿 인클루드 == 경로는 현재 파일 기준 상대경로이다. 여러 디렉터리를 거슬러 올라가야 한다면 <code>^</code>로 라이믹스 설치 디렉터리 기준 경로를 쓸 수 있다. 리소스 로딩에서도 마찬가지다. <syntaxhighlight lang="html"> @include ('dir/filename') @include ('^/common/tpl/default_layout') </syntaxhighlight> === 조건부 인클루드 === * <code>@includeIf</code> — 파일이 있을 때만 인클루드하고, 없어도 오류를 내지 않는다 * <code>@includeWhen</code> — 조건이 참일 때만 * <code>@includeUnless</code> — 조건이 거짓일 때만 === 변수 전달과 컴포넌트 === 인클루드할 때 연관배열이나 오브젝트를 함께 넘기면, '''인클루드된 템플릿은 <code>Context</code>를 참조하지 않고 전달받은 데이터만 쓴다.''' 없는 키를 참조하면 경고가 발생한다. 이를 이용해 외부 변수에 영향받지 않는 독립적인 컴포넌트를 만들 수 있다.<ref name="v2" /> <syntaxhighlight lang="html"> @include ('B', ['title' => '제목', 'content' => '내용']) </syntaxhighlight> 자식 템플릿은 부모의 변수를 상속받으며, 직접 전달받은 변수가 우선한다. 다만 인클루드된 템플릿이 <code>Context::get()</code>으로 외부 데이터에 접근하는 것을 막지는 않는다. 그런 시도가 눈에 잘 띄게 될 뿐이다.<ref name="v2" /> == 리소스 로딩 == <code><nowiki><script></nowiki></code>나 <code><nowiki><link></nowiki></code>로 직접 불러올 수도 있지만, <code>@load</code>로 코어에 맡기면 CSS·JS 압축 및 합치기와 자동 연동되고, SCSS·LESS가 자동 컴파일되며, 로딩 순서 조절과 언로딩이 가능하다.<ref name="v2" /> <syntaxhighlight lang="html"> @load ('styles.css') @load ('styles.css', 'print', 20) @load ('css/styles.scss', $vars) </syntaxhighlight> 파라미터 순서는 파일명, media, 로딩 순서, 변수이다. media와 로딩 순서는 생략할 수 있으나 각각 문자열과 정수여야 하며 변수를 쓸 수 없다. JS도 같은 문법이되 <code>media</code> 대신 <code>type</code>을 넘기며, 변수 전달 기능은 없다. <code>head</code>(기본값)는 본문 로딩 전, <code>body</code>는 본문 로딩 후 실행된다. v1 호환 문법은 각 파라미터의 역할이 더 분명하게 드러나므로 굳이 피할 필요는 없다.<ref name="v2" /> <syntaxhighlight lang="html"> <load src="^/modules/foo/bar/styles.scss" media="screen" vars="$vars" /> <load target="../../../styles.css" index="-3" /> </syntaxhighlight> == HTML 속성 도우미 == === @class와 @style === 배열을 넘기면 단순 값은 그대로, 키/값 형태는 값이 참일 때만 출력된다. <syntaxhighlight lang="html"> <div @class([ 'project-item', 'project-complete' => $is_complete, 'featured' => $is_featured, ])></div> </syntaxhighlight> <code>@style</code>도 같은 방식이지만, 꼭 필요한 경우가 아니면 스타일은 별도 CSS·SCSS 파일에 쓰는 것이 권장된다.<ref name="v2" /> === 불리언 속성 === <code>@checked</code>, <code>@selected</code>, <code>@disabled</code>, <code>@readonly</code>, <code>@required</code>를 쓸 수 있다. <syntaxhighlight lang="html"> <input type="checkbox" @checked($is_checked)> <option value="1" @selected($val == 1)>ONE</option> </syntaxhighlight> 지원하지 않는 속성에 조건을 걸어야 한다면 v1의 <code>|cond=""</code> 문법이나 if문을 쓴다. == PHP 코드와 주석 == <syntaxhighlight lang="html"> @php Hello::world(); $foo = 'bar'; @endphp </syntaxhighlight> v1의 <code>{@ ... }</code> 문법도 쓸 수 있으나 중괄호가 포함된 코드는 작성할 수 없다. 일반 HTML 주석은 결과물에 그대로 출력된다. 출력되지 않는 주석은 다음과 같이 쓴다. <syntaxhighlight lang="html"> {{-- 이 주석은 출력되지 않습니다 --}} <!--// 이 주석은 출력되지 않습니다 --> </syntaxhighlight> == 그 밖의 지시자 == {| class="wikitable" ! 지시자 !! 기능 |- | <code>@use</code> || 긴 클래스명을 alias로 줄여 쓴다 |- | <code>@csrf</code> || 폼에 CSRF 토큰 필드를 자동 주입한다 |- | <code>@json</code> || JSON으로 출력한다 |- | <code>@lang('msg_file_not_found')</code> || 번역문을 불러온다. <code>@lang('file.msg_...')</code>처럼 모듈을 지정할 수도 있다 |- | <code>@url('act', 'dispMemberInfo')</code> || URL을 생성한다. 배열로 넘길 수도 있다 |- | <code>@widget('content', $args)</code> || 위젯을 삽입한다 |- | <code>@dump</code> / <code>@dd</code> || 변수를 출력한다. <code>@dd</code>는 출력 후 중단한다 |- | <code>@once ... @endonce</code> || 한 번만 실행한다 |- | <code>@error ... @enderror</code> || 오류 처리 |- | <code>@verbatim ... @endverbatim</code> || 안쪽의 지시자를 해석하지 않고 그대로 출력한다 |- | <code>@push</code> / <code>@prepend</code> / <code>@stack</code> || 여러 곳에서 모은 내용을 한 지점에 출력한다 |- | <code>@fragment ... @endfragment</code> || 템플릿의 일부만 잘라내어 렌더링한다 |} == 미지원 기능 == Blade 10.x의 기능 중 '''템플릿 상속과 컴포넌트화 관련 지시자는 적용되지 않았다.''' <code>@extends</code>, <code>@yield</code>, <code>@section</code>, <code>@show</code>, <code>@inject</code>, <code>@slot</code> 등이 여기에 해당한다.<ref name="v2" /> 공식 문서가 밝힌 이유는 이렇다. 하나의 개발팀이 하나의 코드베이스를 관리한다고 가정하는 대다수 웹 프레임워크와 달리, 라이믹스는 각 모듈과 스킨을 독립적으로 개발하고 배포할 수 있어야 한다. 전문 개발자가 아닌 사용자와 자료 제작자가 많은데, 스킨에서 쓸 컴포넌트 하나를 만들려고 별도 <code>.php</code> 파일에서 클래스를 선언하거나 터미널에서 명령을 실행해야 하는 개발 방식은 받아들이기 곤란하다는 것이다.<ref name="v2" /> 따라서 Laravel Blade의 컴포넌트 설계는 라이믹스와 맞지 않다고 판단하여, 적절한 대안이 마련될 때까지 적용을 보류하였다. 대신 [[#변수 전달과 컴포넌트|인클루드시 변수 전달]] 기능으로 상당히 독립적인 컴포넌트를 구현할 수 있으며, 복잡한 기능이 필요하다면 위젯을 활용하는 것이 권장된다.<ref name="v2" /> == 같이 보기 == * [[라이믹스/매뉴얼]] * [[라이믹스/릴리즈 노트/2.1.8]] * [[라이믹스/매뉴얼/라이믹스 프레임워크]] — Template 클래스 * [[라이믹스/버전]] == 출처 == 이 문서는 라이믹스 공식 매뉴얼의 [https://rhymix.org/manual/theme/template_v2 템플릿 문법 v2] 문서를 바탕으로 작성되었다. 공식 매뉴얼은 CC BY-SA 4.0 라이선스로 배포된다.<ref name="docs-license">[https://github.com/rhymix/rhymix-docs rhymix-docs 저장소] README에 "이 매뉴얼은 CC-BY-SA 4.0 라이선스에 따라 배포됩니다"라고 명시되어 있다.</ref> 전체 지시자 목록과 상세한 예제는 공식 매뉴얼을 참고하자. == 각주 == <references /> <!-- 분류 --> [[분류:라이믹스]] [[분류:라이믹스/매뉴얼]] 편집 요약 가온 위키에서의 모든 기여는 크리에이티브 커먼즈 저작자표시-동일조건변경허락 라이선스로 배포된다는 점을 유의해 주세요(자세한 내용에 대해서는 가온 위키:저작권 문서를 읽어주세요). 만약 여기에 동의하지 않는다면 문서를 저장하지 말아 주세요. 또한, 직접 작성했거나 퍼블릭 도메인과 같은 자유 문서에서 가져왔다는 것을 보증해야 합니다. 저작권이 있는 내용을 허가 없이 저장하지 마세요! 취소 편집 도움말 (새 창에서 열림) 이 문서에서 사용한 틀: 틀:상위문서 (편집) 틀:상위문서/styles.css (편집) 틀:인용문 (편집)