코드이그나이터4는 디버그바라는것을 사용합니다.


왼쪽 하단의 조그마한 코드이그나이터 아이콘이 디버그바입니다.


본래 라라벨이었나? 그쪽에서 사용하던거를 코드이그나이터도 채용한건데요.


문제는 이게, Filters로 작용을 한다는거..


필자처럼 코드이그나이터 2, 3버전처럼 코딩하다가는 낭패를 봅니다.

(아니, HTML밖에 추가적인 코드가 있는게 딱히 불편하지 않은 사람은 상관없..)



필자가 기존 코드이그나이터3에서 사용하는 Hook 파일입니다.


이렇게 사용안하는 분들도 많고, 저처럼 사용하는 분들도 있을겁니다.

(실제로 컨트롤러에서 HTML이랑 다 씌우는 사람들 많이 봤.. 하나의 파일에 HTML 코드 전부가 없는것만으로도 다행이지.. 근데 코드이그나이터 쓰면서 뷰파일에 HTML이랑 다 씌우는 사람도 봤.. 예제가 그렇다면서;;)


실제 운영중인 사이트의 후커라 뭔가 잡다한게 많은데..


주요내용은 컨트롤러에서 $this->load->view(); 한 내용을 서버가 브라우저에게 던지기 직전에, 컨트롤러에서 작업한 뷰를 가져와서 그것에 테마에 맞는 레이아웃(BODY 안의 코드)을 입히고, 거기에 HTML 코드를 입히는 코드입니다.


코드이그나이터4도 이게 가능할거라 생각..


작업을 해봤습니다.


코드이그나이터4는 헬퍼가 없습니다.


정규버전은 있을거 같지도 않은게, 기존의 헬퍼 작업을 해주는게 Events 라는 이름으로 존재합니다.


도큐멘트를 보면 기존의 후커기능에서 + 사용자 이벤트를 추가 할 수 있습니다.


중요한건 그런게 아니니 여기서는 패스하고..


후커기능을 보면..


코드이그나이터4가 시작할때와 종료할때, 그리고 컨트롤러가 인스턴트화 직후 메소드 호출직전..


3가지 스테이터스밖에 존재하지 않습니다.


그러면 기존의 컨트롤러 작업 이후는..!?


일단 처음에는 Events로 작업을 해보려 했는데, 난관이 여러개 있습니다.


일단 Events를 호출할때 변수를 넣어주지 않으면 안되는데..


view(); 로 작업한 내용을 불러올 수 없습니다.

(현재는 그 방법을 알고있기는 한데, 추후 설명..)


게다가 가장 큰 문제점이, 사용자가 사용하는 영역내에서는 Events 에서 아무리 작업을 해도 디버그 툴바가 마지막에 실행되서 </html> 이후에 붇는 문제점이..


이거는 컨트롤러에서 작업을 해도 마찬가지입니다.



이게 그 잔해인데..


컨트롤러에서 return $this->layout('test'); 를하여 해당 함수를 불러도 디버그바가 하단에 작업됩니다.


그러면 디버그바가 대체 어느시점에서 어떤 시스템으로 불러오는지 확인할 필요가 있습니다.


그래서 디버그바가 어디서 작업하는지 계속 확인을 해봤는데..



Filters 시스템에서 디버그바 작업을 실행합니다.


정확히는 화면에 뿌려주는 작업을 Filters 에서 합니다.


그외에 디버그툴은 코드이그나이터4가 돌아가는동안 계속 호출되면서 작업합니다.


그러한 의도치않은 탄막들 때문에 분석에 시간이 오래걸렸네요;;

(오늘 하루종일 보고 있었던듯.. grep로 리눅스에서 불러오는곳도 다 뒤져보고..)


Filters 는 호출시점이 before와 after 두가지가 있습니다.



system/CodeIgniter.php 파일을 열어보시면 241, 267라인이 각기 Filters 를 작업하는 곳입니다.


즉, before는 컨트롤러를 불러오기 직전.


after는 컨트롤러의 리턴값이 랜더링까지 된 이후 시점입니다.


그러면 기존의 Hook에서 작업을 하려면 Filters after를 호출하면 됩니다.


application/Filters/Layout.php 파일을 생성합니다.



파일을 생성하신후에는 아래의 코드를 넣어주세요.


기본 코드입니다.


<?php namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
class Layout implements FilterInterface {
/**
* We don't need to do anything here.
*
* @param   RequestInterface|\CodeIgniter\HTTP\IncomingRequest  $request
*
* @return  mixed|void
*/
public function before (RequestInterface $request) {}
/**
* If the debug flag is set (CI_DEBUG) then collect performance
* and debug information and display it in a toolbar.
*
* @param   RequestInterface|\CodeIgniter\HTTP\IncomingRequest  $request
* @param   ResponseInterface|\CodeIgniter\HTTP\Response        $response
*
* @return  mixed|void
*/
public function after (RequestInterface $request, ResponseInterface $response) {}
}


보시면 컨트롤러에서도 봤던 코드들이 계속 따라다니는걸 볼 수 있습니다.


application/Config/Filters.php 로 돌아와서..



application/Filters/Layout.php 를 사용할거기 때문에 use App\Filters\Layout; 를 추가(5라인)해줍니다.


그리고 $aliases 변수에 'layout'  => Layout::class, 를 추가해줍니다.


상단에서 use를 사용했기 때문에 그냥 Layout::class라고 작성해도 문제 없습니다.

(PhpStorm에서는 코드이그나이터4 기본 코드가 문제라고 저렇게 물결로 뜹니다.)


이제 after 에서 불러올거기 때문에 $globals 변수에서 after에 'layout' 을 추가해줍니다.


여기서 layout은 $aliases 변수에서 설정한 key 값입니다.


설정이 종료되었으면 다시, application/Filters/Layout.php 으로 돌아옵니다.



이곳에서 기존에 하던 작업을 그대로 하면 드디어..


35번 라인에서 작업하는 html 파일이 <html>에서 </html>까지 들어있는 파일입니다.



html 파일의 내용..


주석 처리한 부분은 아직 작성하지 않은 부분입니다.

(기존의 코드이그나이터3에서 사용하던 파일을 그대로 가져와서;;)


디버그바가 BODY 태그안에 들어오게 됩니다.


왜냐면 toolbar 이후로 실행되기 때문에..


컨트롤러에서 작업된 뷰에 툴바 토드가 하단에 추가되고, 그 코드를 받아와서 HTML 작업을 하게 됩니다.


그래서 제가 작업한 코드를 보시면..


$format = $response->getHeaderLine('content-type');


헤더의 컨텐츠 타입을 가져옵니다.


if (!is_cli() && CI_DEBUG && strpos($format, 'html') !== false) {}


커맨드 실행이 아니고, 디버그 모드가 아니고, 페이지가 html 형식일때 실행이 됩니다.


$page = $response->getBody();


지금까지 작업된 뷰단의 코드를 가져옵니다.


코드이그나이터 2, 3으로 보자면, $output = $this->CI->output->get_output(); 입니다.


$response->setBody($html);


Filters 에서 작업한 코드를 셋팅합니다.


코드이그나이터 2, 3으로 보자면, $OUT->_display($output); 입니다.


위의 코드들은 application/Filters/DebugToolbar.php 에서 가져오거나 참고했습니다.


참고로 $response 에서 사용된 함수들은..


system/HTTP/Message.php 에 존재합니다.


이렇게 하면 일단 디버그바가 HTML 코드 밖으로 빠져나가는 문제점은 해결됩니다.


여기서 문제가 하나 발생하는데..


컨트롤러에서 Filters의 class에게 변수를 전달할 방법입니다.


아니, 컨트롤러가 아니어도 Filters 의 class에 변수를 전달하는 방법이 또 문제가 됩니다.


저대로만 하면 변수 전달이 안되기 때문에..


이제 확장한 컨트롤러에서 Filters로 변수를 지정해서 전달하는 방법입니다.


$view = new \App\Libraries\view();


제가 작성한 코드 스크린샷을 보면 위와 같은 코드가 주석이 되어있는데..


저 방법으로는 넘길 수 없습니다.


왜냐면 new로 새롭게 정의하는거니까..


그러면 컨트롤러에서 사용한 view();를 가져와야 한다는건데..


이것도 방법이 있습니다.


코드이그나이터4에서는 Services 라는게 추가되었습니다.


이게 뭐냐면 Services:: 로 각 클래스를 불러오는 거입니다.


이런게 왜 있을까에 대한 고민에 빠져보면..


application/Config/Services.php 파일에 사용자 서비스를 직접 추가 설정이 가능하게 되어있습니다.



저는 theme 라는 서비스를 등록했습니다.


잘 보시면 return new \App\Libraries\View(); 라고 되어있는데, 그 이유는 제가 코드이그나이터4의 코어인 view 클래스도 확장을 했기 때문입니다.

(코드이그나이터 관련으로 저와 함께 일해본 사람은 알겠지만, 전 뷰단 테마로 나눠서 작업하는.. 그래야 나중에 레이아웃 변경 작업할때 편해서;;)


확장을 안했다면, return new \CodeIgniter\View\View(); 로 될겁니다.


이 글을 읽는 분들의 설정에 맞게 추가하시면 됩니다.


저는 워차피 상속받아서 쓸거라 저렇게 추가했습니다.


application/Libraries/Controller.php 파일로 넘어가보면..



방금전에 추가한 theme 서비스를 사용하기 위해, use Config\Services; 를 추가(6라인)해줍니다.


$this->view = Services::theme();


그리고 위의 코드로 theme 서비스를 선언합니다.



application/Controllers/Test.php 로 돌아와서..


index 함수에 return $this->view->theme('test', $this->data, ['saveData'=>true]); 를 추가합니다.


test 라는 뷰 페이지에는 "Page Test." 만 들어있습니다.


그리고 $this->data 는 확장한 컨트롤러에서 선언되어있는 변수입니다.


그곳에 저는 html 파일에서 사용할 페이지 타이틀을 선언해뒀습니다.

(위위 이미지의 29 ~ 30 라인.)


뒤의 ['saveData'=>true] 는 변수를 계속해서 사용하기 위해서 저장한다는 의미입니다.


왜냐면 페이지만 만들고 끝내면 컨트롤러에서 작업해둔 html 변수들이 넘어가지를 못합니다.


그렇기에 마지막 작업인 html 작업이 끝날때까지 변수를 들고있어야 합니다.


※ 코드이그나이터 2, 3과 동일하게 오버라이팅 되기 때문에 변수명은 조심해야합니다. 의외로 많은 분들이 모르는데, 코드이그나이터 3버전도 변수를 계속 가지고 있는..

(의외로 코드이그나이터 (말로만) 고수라는 사람들도 모르더라..)

그래서 상단에서 뷰를 불러올때 $data 변수에 뭔가를 넣어서 던지면, 다음에 불러오는 뷰에서도 그 $data를 그대로 쓸 수 있는..

코드이그나이터3은 자동 초기화 하지 않는..

하지만 코드이그나이터4는 자동으로 초기화 합니다.


그렇게 컨트롤러에서 view(); 클래스로 던진 변수를 Filters 에서 가져다 쓸 수 있으면 성공입니다.


그럼 다시 application/Filters/Layout.php 로 돌아와서..



34번라인처럼 $view = Services::theme(true); 를 해줍니다.


기본값이 true이기 때문에 꼭 true는 안넣어줘도 됩니다.


false를 넣어주면 새롭게 선언을 해버리기 때문에, 조심해야합니다.


그렇게 html 페이지를 불러오면 컨트롤러에서 함께 넘겨줬던 변수가 적용되기 때문에, 페이지 타이틀이 보이게 됩니다.


기존의 코드이그나이터2, 3에서는 $this로 항상 따라다니던 애들이, 이제는 Services로 떨어져 나가서, 필요하다면 서비스를 선언하여, 매번 필요할때마다 변수로 받아서 사용해야 하는군요.

Posted by Pure Ani

RE:D Cherish! -Eternity Blood- CRYSTALiA

放課後シンデレラ2 HOOKSOFT

花鐘カナデ*グラム NanaWind

フタマタ恋愛 ASa Project

スタディ§ステディ2 ま~まれぇど

リンパにATATA! ~メス牡蠣ミルクどぴゅらっしゅ~ Hending

創作彼女の恋愛公式 Aino+Links

流星ワールドアクター Heliodor

Secret Agent~騎士学園の忍びなるもの~ ensemble

天冥のコンキスタ エウシュリー

HaremKingdom -ハーレムキングダム- SMEE

ラズベリーキューブ まどそふと

ノラと皇女と野良猫ハート2 -Nora, Princess, and Crying Cat.- HARUKAZE

『ノラと皇女と野良猫ハート2』応援中♪

ピュアソングガーデン PULLTOP

はにデビ! Honey&Devil eufonie

姫繰三六五 HIMEKURI365

姫繰三六五 公式ウェブサイト

はるるみなもに! クロシェット

死に逝く君、館に芽吹く憎悪 バグシステム

Sanguinea-サングイネア- すにぃる

麗華の館 しすたーそふと

カスタムメイドオンライン KISS