03. Site 라이브러리

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>태그를 이용하지 않고 위의 함수를 이용하면 다음과 같은 장점이 있습니다.

  1. 동일한 경로의 css를 실수로 두번 불러오지 않게 막을수 있다.
  2. 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;
    }
}

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다

This site uses Akismet to reduce spam. Learn how your comment data is processed.