본문 바로가기
개발자, 코딩

[php]Codeigniter 4 Layout 사용하기 - 메뉴바, 푸터 공통 사용

by The Career 2022. 1. 7.
반응형

코드이그나이터 4를 활용해서 메뉴바, 푸터를 공통으로 사용할 수 있는 Layout 방법을 찾게되었습니다.

일반적으로 사용하는 menu와 footer를 별도의 파일로 설정하여 각 페이지마다 include 시키는 방식은 매우 번거롭고 불편합니다. 😵‍💫

JSP는 이런 Layout을 구성해주는 Tiles와 같은 프레임워크가 존재하지만, php는 따로 내용을 찾을 수 없었습니다. 검색을 하던 도중 Helper로 Layout을 구성하여 Controller에서 view를 리턴할 때 해당 Layout을 포함하여 전달 할 수 있는 방법을  찾게되었습니다.


❓ PHP에서 Layout을 편리하게 구성하기 위한 고민

위에서 언급했던 것처럼, Layout 페이지를 별도로 구성하여 각 페이지마다 include 시키는 방식은 관리가 번거롭습니다. 페이지를 개발할 때마다 추가해주어야하고, 파일 구성이 변경되면 각 페이지마다 또 수정을 해주어야하기 때문입니다.

따라서 render를 해주는 Helper를 구성하여 view 리턴 시 Layout을 포함할 수 있도록 해주어야합니다.

 


1️⃣ Layout 구성하기

우선, 전 페이지에 공통적으로 들어갈 Layout을 구성해야합니다. 저는 VIews/layout/layout.php 파일을 생성하여 Layout을 구성했습니다. Layout에는 기본 html 구조와 메뉴, 푸터가 들어가며 실제 view를 렌더링 후 포함시킬 content 영역을 분리했습니다.

 

 

Layout은 위 영역에서 메뉴와 푸터를 포함하고 있으며, 모든 view 호출시마다 문서를 위 구조로 메뉴와 푸터 영역을 포함하여 리턴하게 됩니다.

 

<html>
     <head>
          <meta charset="utf-8">
          <title>js 예제</title>
     </head>
     <style>
          ul {
               list-style: none;
          }

          a {
               text-decoration: none;
               outline: none;
          }

          .page {
               width: 1440px;
               margin: 0 auto;
          }

          header {
               width: 100%;
               height: 80px;
               display: flex;
               align-items: center;
               justify-content: space-between;
               border-bottom: solid 1px black;
          }

          header > h2 {
               margin-left:20px;
          }

          header > nav {
               width:600px;
               height:100%;
          }

          header ul {
               width:100%;
               height: 100%;
               display: flex;
               justify-content: space-between;
          }

          header ul > li {
               font-size:20px;
               height: 100%;
               display: flex;
               align-items: center;
          }

          footer {
               width: 100%;
               height: 90px;
               bottom: 0px;
               position: absolute;
               border-top: 1px solid #c4c4c4;
               padding-top: 15px;
               color: #808080;
               font-size: 11px;
          }

          footer a {
               display: inline-block;
               margin: 0 20px 10px 20px;
               color: #808080; font-size: 11px;
          }

          footer a:visited {
               color: #808080;
          }

          footer p {
               margin-top: 0; margin-bottom: 0;   
          }

          footer p span {
               display: inline-block;
               margin-left: 20px;
          }

          section{
               padding-bottom: 105px;
          }
          .wrap {
               min-height: 100vh;
               position: relative;
               width: 100%; 
          }
          .content{
               text-align: center;
               width: 100%;
          }
     </style>
     <body>
          <div class="wrap">
               <header id="header" class="header">
                    <nav>
                         <ul>
                              <li><a href="#">메뉴1</a></li>
                              <li><a href="">메뉴2</a></li>
                              <li><a href="">메뉴3</a></li>
                              <li><a href="">메뉴4</a></li>
                         </ul>
                    </nav>
               </header>
               <section>
                    <div class="content">
                         <?php echo $content; ?>
                    </div>
               </section>
               <footer id="footer" class="footer">
                    <nav>
                         <a href='https://cocoder.tistory.com' target='_blank'>Blog</a> |
                         <a href='https://github.com/cocoder16' target='_blank'>Github</a>
                    </nav>
                    <p>
                         <span>저자 : nick</span><br/>
                         <span>이메일 : nick901106@gmail.com</span><br/>
                         <span>Copyright 2022. All Rights Reserved.</span>
                    </p>
               </footer>
          </div>
     </body>
</html>

 

위 코드에서 

 

<section>
	<div class="content">
		<?php echo $content; ?>
	</div>
</section>

이 부분이 실제 view를 포함시킬 영역입니다. 메뉴를 제외한 컨텐츠 영역에 별도 css 작업이 필요한 경우 해당 영역에 css를 잡아주면 됩니다.

 


2️⃣ 렌더링 helper 만들기

이제 view 리턴시 Layout을 포함시켜줄 helper를 만들면 됩니다. helper는 root 디렉토리에 Helpers 폴더 하단에 만들어주면 됩니다. helper 파일명은 '이름_helper.php'로 작성합니다. 저는 render_helper.php로 작성했습니다.

 

<?php
    if ( ! function_exists('render'))
    {
        function render(string $name, array $data = [], array $options = [])
        {
            return view(
                'layout/layout',
                [
                    'content' => view($name, $data, $options),
                ],
                $options
            );
        }
    }
?>

함수 render 호출 시 view name, 전달 data, option을 받아 레이아웃을 포함하여 view를 리턴합니다.

'layout/layout' 부분에는 1번에서 만든 Views 하단의 layout의 경로를 전달하면 됩니다. 저는 content라는 이름으로 view를 전달했습니다.

 

이제 위에서 작성한 helper를 등록해주면 됩니다. app/config/Events.php 파일에 아래 내용을 복사하여 넣어줍니다.

Events::on('post_controller_constructor', function() {
	helper(['render']);
});

위에서 render는 위에서 작성한 helper 파일의 '_helper.php' 앞의 이름을 넣어주면 됩니다.

이는 CI에서 제공하는 Hook을 사용하여 controller 사용 직후, 해당 함수를 사용하겠다는 의미입니다.

 


3️⃣  Layout 호출하기

이제 위에서 만든 render 함수를 호출해주면 됩니다. controller에서 view를 리턴하는 대신, render 함수를 리턴해주면 됩니다.

//controller

public function dataTable()
{
	// return view('example/dataTable'); // 일반 view 호출
	return render('example/dataTable'); // layout을 포함한 view 호출
}

위 처럼 render(view 경로, 전달 data, options)로 호출하여 사용하면 됩니다.

render를 통해 호출된 view는 위에서 작성한 layout을 포함하여 표시합니다.

 

 

메뉴와 푸터가 포함된 화면을 볼 수 있습니다. 👍🏻

단순하지만, 페이지나 파일의 구성이 변경되어도 helper만 변경하면 되기때문에 관리 측면에서 훨씬 편리해보입니다!

 


❗️ 결론

helper를 사용하여 layout을 호출하는 방식으로 한번 작성해두면 render 함수를 호출만 하면 되기 때문에 사용이 굉장히 편리합니다!

개인적으로 몇 개의 layout을 구성하여 각 layout별 render 함수를 만들어서 필요에 따라 해당 render를 호출하면 더욱 더 편리하지 않을까 생각합니다.(유저 layout, 관리자 layout 등)


✅  참고자료

 


 

반응형