application/libraries 폴더에 Site.php 파일을 추가합니다.
이 파일은 사이트의 전반적인 조작을 담당할 예정입니다.
먼저 클래스를 선언하고 기본적으로 아래와 같이 변수를 선언합니다.
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/*************************************************************
* Class Site
************************************************************/
class Site {
protected $CI;
// 현재 테마보기 모드입니다. Desktop용 화면보기/모바일용 화면보기
public $view_mode;
// 실제 접속한 기기입니다.
public $device;
// 데이타베이스에서 불러온 환경설정을 저장해둘 변수입니다.
protected $config;
// 프론트엔드상의 불러올 CSS파일과 JS파일을 담아둘 변수입니다.
protected $css_before = array();
protected $css_after = array();
protected $js_before = array();
protected $js_after = array();
// 메타태그에 출력할 부분을 저장할 변수입니다.
public $meta_title = "";
public $meta_description = "";
public $meta_keywords = "";
public $meta_image = "";
// 생성자 (라이브러리가 초기화 되었을때 실행됩니다)
function __construct()
{
$this->CI =& get_instance();
}
}
그 다음으로 이전포스팅에서 만들었던 테이블의 데이타를 쉽게 불러올수 있도록 함수를 만들어 보겠습니다. 함수의 코드는 먼저 아래와 같습니다.
/**********************************************************
* 사이트 전역설정중 특정 컬럼의 값을 반환한다.
* @param $column 반활할 컬럼 이름
* @param $default_value 값이 없을시 기본적으로 리턴할 값
* @return var 컬럼의 값
*********************************************************/
public function config($column, $default_value=NULL) {
// 컬럼값이 없으면 리턴한다.
if( empty($column) ) return NULL;
// 캐시 드라이버 로드
$CI =& get_instance();
$CI->load->driver('cache', array('adapter' => 'apc', 'backup' => 'file', 'key_prefix' => PROJECT_NAME));
// 캐시에 저장되어 있는 환경설정내역을 불러오고 없다면 데이타베이스에서 새로 불러온다.
if( ! $config = $CI->cache->get('site_config') )
{
// DB에서 환경설정값 전체를 불러온다.
$config_list = $CI->db->get("config")->result_array();
// cfg_key를 키값으로, cfg_value를 값으로 하는 배열을 만든다.
$config = array();
foreach( $config_list as $row ) {
$config[$row['cfg_key']] = $row['cfg_value'];
}
// 불러온 파일은 300초간 캐시로 저장한다.
$CI->cache->save('site_config', $config, 300);
}
return element($column, $config, $default_value);
}
매번 페이지를 로드할때마다 데이타베이스에서 불러오는 것은 불필요한 DB콜을 늘리기 때문에, 한번 불러온 환경설정파일은 300초간 캐시로 저장해두도록 합니다.
마지막에 return 에 사용된 element라는 함수는 다음 포스팅에서 다를 common_helper.php에서 작성할 함수입니다. 일단은 그대로 입력해주세요.
다음으로 현재접속한 기기에 따라 어떤레이아웃을 가져올지 판별할 함수를 추가합니다.
/*********************************************************
* 현재 접속 기기에 따라 필요한 레이아웃을 가져온다.
*********************************************************/
public function layout()
{
return ( $this->view_mode == DEVICE_MOBILE ) ? THEME_MOBILE : THEME_DESKTOP;
}
DEVICE_MOBILE 과 THEME_MOBILE, THEME_DESKTOP 은 application/config/wwconfig.php 에서 상수로 선언한것들입니다.
다음으로 프론트엔드에서 사용할 css와 js를 담아둘수 있는 함수를 선언합니다.
아래와 같은 코드를 복사합니다.
/*********************************************************
* 사이트에 사용할 CSS를 추가합니다.
* @param $url 추가할 CSS
* @param bool $insert_last 마지막에 추가할지 처음에 추가할지
********************************************************/
public function add_css( $url, $insert_first = FALSE) {
if(!empty($url) && ! in_array($url, $this->css_after) && !in_array($url, $this->css_before)) {
if( $insert_first ) {
array_push($this->css_before, $url);
}
else {
array_push($this->css_after, $url);
}
}
}
/*********************************************************
* 사이트에 사용할 JS를 추가한다.
* @param $url 추가할 JS
* @param bool $insert_last 마지막에 추가할것인가?
********************************************************/
public function add_js( $url, $insert_first = FALSE ) {
if(!empty($url) && ! in_array($url, $this->js_before) && ! in_array($url, $this->js_after)) {
if( $insert_first ) {
array_push($this->js_before, $url);
}
else {
array_push($this->js_after, $url);
}
}
}
/******************************************************************************************
* 해당 URL이 우리 서버 도메인을 가르키는지 확인한다.
* @param $url 체크할 URL
* @param bool $check_file_exist 파일존재 여부까지 확인한다.
* @return bool
*****************************************************************************************/
private function is_my_domain($url, $check_file_exist = TRUE)
{
// 처음 시작이 / 이고 두번제 문자가 /이 아닐경우
if( substr($url,0,1) === '/' && substr($url,1,1) !== '/' )
{
if( $check_file_exist ) {
return file_exists( FCPATH . $url );
}
return TRUE;
}
if( strpos( $url, base_url()) !== FALSE ) {
if( $check_file_exist ) {
return file_exists( FCPATH . str_replace( base_url(), "", $url ));
}
return TRUE;
}
return FALSE;
}
/*********************************************************
* 배열에 담긴 CSS를 메타태그와 함께 같이 출력한다.
* @return string
********************************************************/
public function display_css() {
$return = '';
$css_array = array_merge($this->css_before, $this->css_after);
$css_array = array_unique($css_array);
foreach($css_array as $css) {
if( $this->is_my_domain( $css ) ) {
$filepath = str_replace(base_url(), "/", $css);
$css .= "?" . date('YmdHis', filemtime( FCPATH.ltrim($filepath,DIRECTORY_SEPARATOR) ));
if( ! (strpos($css, base_url()) !== FALSE) ) {
$css = base_url($css);
}
}
$return .= '<link rel="stylesheet" href="'.$css.'" />'.PHP_EOL;
}
return $return;
}
/*********************************************************
* 배열에 담긴 JS를 메타태그와 함께 같이 출력한다.
* @return string
********************************************************/
public function display_js() {
$return = '';
$js_array = array_merge($this->js_before, $this->js_after);
$js_array = array_unique($js_array);
foreach($js_array as $js) {
if( $this->is_my_domain( $js ) ) {
$filepath = str_replace(base_url(), "/", $js);
$js .= "?" . date('YmdHis', filemtime( FCPATH.ltrim($filepath,DIRECTORY_SEPARATOR) ));
if( ! (strpos($js, base_url()) !== FALSE) ) {
$js = base_url($js);
}
}
$return .= '<script src="'.$js.'"></script>'.PHP_EOL;
}
// 사이트를 위한 javascript
$return .= '<script>';
$return .= 'var base_url="'.base_url().'";';
$return .= 'var current_url="'.current_url().'";';
$return .= 'var cookie_domain="'.COOKIE_DOMAIN.'";';
$return .= 'var is_admin='.( IS_ADMIN_PAGES ? 'true' : 'false' ).';';
$return .= '</script>';
return $return;
}
add_css 와 add_js 함수를 사용하여 페이지에 불러올 css와 js를 미리 추가한뒤, display_css 와 display_js 로 필요한 부분에 저장해둔 css와 js 파일들을 한번에 출력해줍니다.
페이지 레이아웃이나 각 페이지에서 <link>나 <script>태그를 이용하지 않고 위의 함수를 이용하면 다음과 같은 장점이 있습니다.
- 동일한 경로의 css를 실수로 두번 불러오지 않게 막을수 있다.
- css와 js파일이 기본적으로 캐싱이 되게 하되, 파일이 수정되면 캐시없이 다시 불러올수 있도록 css파일과 js 파일뒤에 파일수정시간을 자동으로 붙여준다.
마지막으로 메타태그를 생성하기 위한 함수를 만들어줍니다.
/*********************************************************
* 페이지의 타이틀을 가져온다.
********************************************************/
public function page_title() {
$config_title = $this->config('site_title');
$this->meta_title = str_replace(" :: {$config_title}", "", $this->meta_title);
$this->meta_title = $this->meta_title ? $this->meta_title : $this->config('site_subtitle');
if( ! empty($this->meta_title) ) $this->meta_title .= ' :: ';
$this->meta_title .= $config_title;
return $this->meta_title;
}
/*********************************************************
* 메타태그를 자동으로 생성하여 표시한다.
********************************************************/
public function display_meta()
{
// Default 값 설정
$this->page_title();
$this->meta_description = $this->meta_description ? $this->meta_description : $this->config('site_meta_description',"");
$this->meta_keywords = $this->meta_keywords ? $this->meta_keywords : "";
$this->meta_image = $this->meta_image ?
$this->meta_image : str_replace(DIRECTORY_SEPARATOR, "/", $this->config('site_meta_image' ,"")
? base_url(str_replace(DIRECTORY_SEPARATOR, "/", $this->config('site_meta_image' ))) : NULL);
$default_keywords = explode(",", $this->config('site_meta_keywords'));
$in_keywords = explode(",", $this->meta_keywords);
foreach($in_keywords as $keyword) {
$keyword = trim($keyword);
if(! in_array($keyword, $default_keywords)) {
array_push($default_keywords, $keyword);
}
}
$default_keywords = array_unique($default_keywords);
$this->meta_keywords = "";
// 합친 키워드를 다시 직렬화
foreach($default_keywords as $keyword) {
$this->meta_keywords .= $keyword.",";
}
$this->meta_keywords = rtrim($this->meta_keywords,",");
// 기본태그
$return = "";
// 기본 메타 태그
$return .= '<title>' . $this->meta_title . '</title>'.PHP_EOL;
$return .= '<meta name="description" content="'.$this->meta_description.'">'.PHP_EOL;
$return .= '<meta name="keywords" content="'. $this->meta_keywords.'">'.PHP_EOL;
$return .= ($this->meta_image ? '<link rel="image_src" href="'.$this->meta_image.'">': '') .PHP_EOL;
// 페이스북 메타 태그
$return .= '<meta property="og:title" content="'.$this->meta_title.'" />' .PHP_EOL;
$return .= '<meta property="og:type" content="article" />' .PHP_EOL;
$return .= '<meta property="og:url" content="'.current_url().'" />' .PHP_EOL;
$return .= ($this->meta_image ? '<meta property="og:image" content="'.$this->meta_image.'" />': '') .PHP_EOL;
$return .= '<meta property="og:description" content="'.$this->meta_description.'" />'.PHP_EOL;
$return .= '<meta property="og:site_name" content="'.$this->config('site_title').'" />'.PHP_EOL;
// 트위터 메타 태그
$return .= '<meta name="twitter:card" content="summary"/>'.PHP_EOL;
$return .= '<meta name="twitter:site" content="'.$this->config('site_title').'"/>'.PHP_EOL;
$return .= '<meta name="twitter:title" content="'.$this->meta_title.'">'.PHP_EOL;
$return .= '<meta name="twitter:description" content="'.$this->meta_description.'"/>'.PHP_EOL;
$return .= '<meta name="twitter:creator" content="'.$this->config('site_title').'"/>'.PHP_EOL;
$return .= ($this->meta_image ? '<meta name="twitter:image:src" content="'.$this->meta_image.'"/>' : '').PHP_EOL;
$return .= '<meta name="twitter:domain" content="'.base_url().'"/>'.PHP_EOL;
// 네이트온 메타 태그
$return .= '<meta name="nate:title" content="'.$this->meta_title.'" />'.PHP_EOL;
$return .= '<meta name="nate:description" content="'.$this->meta_description.'" />'.PHP_EOL;
$return .= '<meta name="nate:site_name" content="'.$this->config('site_title').'" />'.PHP_EOL;
$return .= '<meta name="nate:url" content="'.current_url().'" />'.PHP_EOL;
$return .= ($this->meta_image ? '<meta name="nate:image" content="'.$this->meta_image.'" />' : '').PHP_EOL;
$return .= '<link rel="canonical" href="'.current_full_url().'">'.PHP_EOL;
$return .= $this->display_css().PHP_EOL;
// 추가로 관리자에서 설정한 Head 태그가 있다면 메타태그 추가
if(! empty($this->config('extra_tag_meta')) ) $return .= $this->config('extra_tag_meta') .PHP_EOL;
return $return;
}
이부분에서 처음에 만든 함수 config() 를 아낌없이 사용하였습니다. 외부 클래스에서는 $this->site->config() 처럼 사용하여야 하나, 클래스 내부이므로 $this->config() 형식으로 불러옵니다.
추가로 관리자에서 Head 태그내에 meta tag를 추가해야할 상황에 관리자에서 추가 스크립트를 넣을수 있도록 하기위해 환경설정 키 하나를 더 생성해줍니다.
관리자가 필요에따라 구글/네이버 사이트소유확인 코드나, 구글애널리틱스, 픽셀코드, 구글태그매니저등의 여러가지 코드를 관리자에서 설정할수 있도록 하기 위함입니다.
완성된 전체 코드는 아래와 같습니다.
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/*************************************************************
* Class Site
************************************************************/
class Site {
protected $CI;
// 현재 테마보기 모드입니다. Desktop용 화면보기/모바일용 화면보기
public $view_mode;
// 실제 접속한 기기입니다.
public $device;
// 데이타베이스에서 불러온 환경설정을 저장해둘 변수입니다.
protected $config;
// 프론트엔드상의 불러올 CSS파일과 JS파일을 담아둘 변수입니다.
protected $css_before = array();
protected $css_after = array();
protected $js_before = array();
protected $js_after = array();
// 메타태그에 출력할 부분을 저장할 변수입니다.
public $meta_title = "";
public $meta_description = "";
public $meta_keywords = "";
public $meta_image = "";
function __construct()
{
$this->CI =& get_instance();
}
/**********************************************************
* 사이트 전역설정중 특정 컬럼의 값을 반환한다.
* @param $column 반활할 컬럼 이름
* @param $default_value 값이 없을시 기본적으로 리턴할 값
* @return var 컬럼의 값
*********************************************************/
public function config($column, $default_value=NULL) {
// 컬럼값이 없으면 리턴한다.
if( empty($column) ) return NULL;
// 캐시 드라이버 로드
$CI =& get_instance();
$CI->load->driver('cache', array('adapter' => 'apc', 'backup' => 'file', 'key_prefix' => PROJECT_NAME));
// 캐시에 저장되어 있는 환경설정내역을 불러오고 없다면 데이타베이스에서 새로 불러온다.
if( ! $config = $CI->cache->get('site_config') )
{
// DB에서 환경설정값 전체를 불러온다.
$config_list = $CI->db->get("config")->result_array();
// cfg_key를 키값으로, cfg_value를 값으로 하는 배열을 만든다.
$config = array();
foreach( $config_list as $row ) {
$config[$row['cfg_key']] = $row['cfg_value'];
}
// 불러온 파일은
$CI->cache->save('site_config', $config, 300);
}
return element($column, $config, $default_value);
}
/*********************************************************
* 현재 접속 기기에 따라 필요한 레이아웃을 가져온다.
*********************************************************/
public function layout()
{
return ( $this->view_mode == DEVICE_MOBILE ) ? THEME_MOBILE : THEME_DESKTOP;
}
/*********************************************************
* 사이트에 사용할 CSS를 추가합니다.
* @param $url 추가할 CSS
* @param bool $insert_last 마지막에 추가할지 처음에 추가할지
********************************************************/
public function add_css( $url, $insert_first = FALSE) {
if(!empty($url) && ! in_array($url, $this->css_after) && !in_array($url, $this->css_before)) {
if( $insert_first ) {
array_push($this->css_before, $url);
}
else {
array_push($this->css_after, $url);
}
}
}
/*********************************************************
* 사이트에 사용할 JS를 추가한다.
* @param $url 추가할 JS
* @param bool $insert_last 마지막에 추가할것인가?
********************************************************/
public function add_js( $url, $insert_first = FALSE ) {
if(!empty($url) && ! in_array($url, $this->js_before) && ! in_array($url, $this->js_after)) {
if( $insert_first ) {
array_push($this->js_before, $url);
}
else {
array_push($this->js_after, $url);
}
}
}
/******************************************************************************************
* 해당 URL이 우리 서버 도메인을 가르키는지 확인한다.
* @param $url 체크할 URL
* @param bool $check_file_exist 파일존재 여부까지 확인한다.
* @return bool
*****************************************************************************************/
private function is_my_domain($url, $check_file_exist = TRUE)
{
// 처음 시작이 / 이고 두번제 문자가 /이 아닐경우
if( substr($url,0,1) === '/' && substr($url,1,1) !== '/' )
{
if( $check_file_exist ) {
return file_exists( FCPATH . $url );
}
return TRUE;
}
if( strpos( $url, base_url()) !== FALSE ) {
if( $check_file_exist ) {
return file_exists( FCPATH . str_replace( base_url(), "", $url ));
}
return TRUE;
}
return FALSE;
}
/*********************************************************
* 배열에 담긴 CSS를 메타태그와 함께 같이 출력한다.
* @return string
********************************************************/
public function display_css() {
$return = '';
$css_array = array_merge($this->css_before, $this->css_after);
$css_array = array_unique($css_array);
foreach($css_array as $css) {
if( $this->is_my_domain( $css ) ) {
$filepath = str_replace(base_url(), "/", $css);
$css .= "?" . date('YmdHis', filemtime( FCPATH.ltrim($filepath,DIRECTORY_SEPARATOR) ));
if( ! (strpos($css, base_url()) !== FALSE) ) {
$css = base_url($css);
}
}
$return .= '<link rel="stylesheet" href="'.$css.'" />'.PHP_EOL;
}
return $return;
}
/*********************************************************
* 배열에 담긴 JS를 메타태그와 함께 같이 출력한다.
* @return string
********************************************************/
public function display_js() {
$return = '';
$js_array = array_merge($this->js_before, $this->js_after);
$js_array = array_unique($js_array);
foreach($js_array as $js) {
if( $this->is_my_domain( $js ) ) {
$filepath = str_replace(base_url(), "/", $js);
$js .= "?" . date('YmdHis', filemtime( FCPATH.ltrim($filepath,DIRECTORY_SEPARATOR) ));
if( ! (strpos($js, base_url()) !== FALSE) ) {
$js = base_url($js);
}
}
$return .= '<script src="'.$js.'"></script>'.PHP_EOL;
}
// 사이트를 위한 javascript
$return .= '<script>';
$return .= 'var base_url="'.base_url().'";';
$return .= 'var current_url="'.current_url().'";';
$return .= 'var cookie_domain="'.COOKIE_DOMAIN.'";';
$return .= 'var is_admin='.( IS_ADMIN_PAGES ? 'true' : 'false' ).';';
$return .= '</script>';
return $return;
}
/*********************************************************
* 페이지의 타이틀을 가져온다.
********************************************************/
public function page_title() {
$config_title = $this->config('site_title');
$this->meta_title = str_replace(" :: {$config_title}", "", $this->meta_title);
$this->meta_title = $this->meta_title ? $this->meta_title : $this->config('site_subtitle');
if( ! empty($this->meta_title) ) $this->meta_title .= ' :: ';
$this->meta_title .= $config_title;
return $this->meta_title;
}
/*********************************************************
* 메타태그를 자동으로 생성하여 표시한다.
********************************************************/
public function display_meta()
{
// Default 값 설정
$this->page_title();
$this->meta_description = $this->meta_description ? $this->meta_description : $this->config('site_meta_description',"");
$this->meta_keywords = $this->meta_keywords ? $this->meta_keywords : "";
$this->meta_image = $this->meta_image ?
$this->meta_image : str_replace(DIRECTORY_SEPARATOR, "/", $this->config('site_meta_image' ,"")
? base_url(str_replace(DIRECTORY_SEPARATOR, "/", $this->config('site_meta_image' ))) : NULL);
$default_keywords = explode(",", $this->config('site_meta_keywords'));
$in_keywords = explode(",", $this->meta_keywords);
foreach($in_keywords as $keyword) {
$keyword = trim($keyword);
if(! in_array($keyword, $default_keywords)) {
array_push($default_keywords, $keyword);
}
}
$default_keywords = array_unique($default_keywords);
$this->meta_keywords = "";
// 합친 키워드를 다시 직렬화
foreach($default_keywords as $keyword) {
$this->meta_keywords .= $keyword.",";
}
$this->meta_keywords = rtrim($this->meta_keywords,",");
// 기본태그
$return = "";
// 기본 메타 태그
$return .= '<title>' . $this->meta_title . '</title>'.PHP_EOL;
$return .= '<meta name="description" content="'.$this->meta_description.'">'.PHP_EOL;
$return .= '<meta name="keywords" content="'. $this->meta_keywords.'">'.PHP_EOL;
$return .= ($this->meta_image ? '<link rel="image_src" href="'.$this->meta_image.'">': '') .PHP_EOL;
// 페이스북 메타 태그
$return .= '<meta property="og:title" content="'.$this->meta_title.'" />' .PHP_EOL;
$return .= '<meta property="og:type" content="article" />' .PHP_EOL;
$return .= '<meta property="og:url" content="'.current_url().'" />' .PHP_EOL;
$return .= ($this->meta_image ? '<meta property="og:image" content="'.$this->meta_image.'" />': '') .PHP_EOL;
$return .= '<meta property="og:description" content="'.$this->meta_description.'" />'.PHP_EOL;
$return .= '<meta property="og:site_name" content="'.$this->config('site_title').'" />'.PHP_EOL;
// 트위터 메타 태그
$return .= '<meta name="twitter:card" content="summary"/>'.PHP_EOL;
$return .= '<meta name="twitter:site" content="'.$this->config('site_title').'"/>'.PHP_EOL;
$return .= '<meta name="twitter:title" content="'.$this->meta_title.'">'.PHP_EOL;
$return .= '<meta name="twitter:description" content="'.$this->meta_description.'"/>'.PHP_EOL;
$return .= '<meta name="twitter:creator" content="'.$this->config('site_title').'"/>'.PHP_EOL;
$return .= ($this->meta_image ? '<meta name="twitter:image:src" content="'.$this->meta_image.'"/>' : '').PHP_EOL;
$return .= '<meta name="twitter:domain" content="'.base_url().'"/>'.PHP_EOL;
// 네이트온 메타 태그
$return .= '<meta name="nate:title" content="'.$this->meta_title.'" />'.PHP_EOL;
$return .= '<meta name="nate:description" content="'.$this->meta_description.'" />'.PHP_EOL;
$return .= '<meta name="nate:site_name" content="'.$this->config('site_title').'" />'.PHP_EOL;
$return .= '<meta name="nate:url" content="'.current_url().'" />'.PHP_EOL;
$return .= ($this->meta_image ? '<meta name="nate:image" content="'.$this->meta_image.'" />' : '').PHP_EOL;
$return .= '<link rel="canonical" href="'.current_full_url().'">'.PHP_EOL;
$return .= $this->display_css().PHP_EOL;
// 추가로 관리자에서 설정한 Head 태그가 있다면 메타태그 추가
if(! empty($this->config('extra_tag_meta')) ) $return .= $this->config('extra_tag_meta') .PHP_EOL;
return $return;
}
}