프로그래밍/PHP

[PHP] CodeIgniter 2단계 이상의 하위 폴더로 소스 관리하는 방법

채윤아빠 2019. 12. 29. 13:22
728x90
반응형



개요

CodeIgniter를 이용하여 REST API를 개발하던 중에 다음과 같은 형태로 폴더 구조를 만들고, API를 호출하면 무조건 "404 Not found" 오류를 반환하였습니다.

application / controllers / rapi / v1.0 / Welcome.php

application / controllers / rapi / Welcome.php
curl -XGET "http://localhost/rapi/v1.0/Welcome

동일한 "Welcome.php" 소스를 "rapi" 폴더에 복사하고 다음과 같이 호출하면 정상적으로 호출됩니다.

curl -XGET "http://localhost/rapi/Welcome

검색하여 보니 기본적으로 CodeIgniter를 이용하여 controllers 폴더 하위에 폴더를 생성하여 각 폴더별로 소스를 관리하는 것이 가능하기는 하지만, 1단계 하위 폴더까지만 인식이 되고 그 하위 폴더들은 인식이 되지 않고 무조건 404 오류가 반환되도록 되어 있는 것이었습니다.

1단계 하위 폴더 아래 추가로 하위 폴더를 더 만들어서 소스들을 관리하기 위해서는 CodeIgniter의 기본 Router 클래스를 상속받아 확장해야만 가능합니다.

작업 내용

2단계가 넘어가는 하위 폴더별로 프로젝트 소스를 분리하여 관리하기 위해서는 다음의 "MY_Router.php" 소스를 "application/core" 폴더 아래에 복사합니다.

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * MY_Router Class *
 * An extension to the core router class to allow controllers to be in multi-level directories.
 *
 * @package   Router
 * @version   1.0
 * @author    Damien K.
 * @copyright Copyright (c) 2010, Ollie Rattue
 * @license   http://www.opensource.org/licenses/mit-license.php
 * @link      https://github.com/ollierattue/codeigniter-multi-level-controller-extension
 */

class MY_Router extends CI_Router {

    // --------------------------------------------------------------------

    /**
     * OVERRIDE
     *
     * Validates the supplied segments.  Attempts to determine the path to
     * the controller.
     *
     * @access    private
     * @param    array
     * @return    array
     */
    function _validate_request($segments)
    {
        if (count($segments) == 0)
        {
            return $segments;
        }

        // Does the requested controller exist in the root folder?
        if (file_exists(APPPATH.'controllers/'.$segments[0] . '.php'))
        {
            return $segments;
        }

        // Is the controller in a sub-folder?
        if (is_dir(APPPATH.'controllers/'.$segments[0]))
        {
            // @edit: Support multi-level sub-folders
            $dir = '';

            do
            {
                if (strlen($dir) > 0)
                {
                    $dir .= '/';
                }

                $dir .= $segments[0];
                $segments = array_slice($segments, 1);
            } while (count($segments) > 0 && is_dir(APPPATH.'controllers/'.$dir.'/'.$segments[0]));

            // Set the directory and remove it from the segment array
            $this->set_directory($dir);
            // @edit: END

            // @edit: If no controller found, use 'default_controller' as defined in 'config/routes.php'
            if (count($segments) > 0 && ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0] . '.php'))
            {
                array_unshift($segments, $this->default_controller);
            }
            // @edit: END

            if (count($segments) > 0)
            {
                // Does the requested controller exist in the sub-folder?
                if (!file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0] . '.php'))
                {
                    // show_404($this->fetch_directory().$segments[0]);
                    // @edit: Fix a "bug" where show_404 is called before all the core classes are loaded
                    $this->directory = '';
                    // @edit: END
                }
            }
            else
            {
                // Is the method being specified in the route?
                if (strpos($this->default_controller, '/') !== FALSE)
                {
                    $x = explode('/', $this->default_controller);

                    $this->set_class($x[0]);
                    $this->set_method($x[1]);
                }
                else
                {
                    $this->set_class($this->default_controller);
                    $this->set_method('index');
                }

                // Does the default controller exist in the sub-folder?
                if (!file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller . '.php'))
                {
                    $this->directory = '';
                    return array();
                }

            }

            return $segments;
        }

        // If we've gotten this far it means that the URI does not correlate to a valid
        // controller class.  We will now see if there is an override
        if (!empty($this->routes['404_override']))
        {
            $x = explode('/', $this->routes['404_override']);

            $this->set_class($x[0]);
            $this->set_method(isset($x[1]) ? $x[1] : 'index');

            return $x;
        }

        // Nothing else to do at this point but show a 404
        show_404($segments[0]);
    }

    // --------------------------------------------------------------------

    /**
     * OVERRIDE
     *
     * Set the directory name
     *
     * @access    public
     * @param    string
     * @return    void
     */
    function set_directory($dir, $append = false)
    {
        $this->directory = $dir . '/'; // @edit: Preserve '/'
    }

    // --------------------------------------------------------------------
}

결론

CodeIgniter에서는 기본적으로 controllers 폴더 아래 1단계 하위에 폴더까지만 각 폴더별로 소스를 관리하는 것이 가능하고, 1단계 하위 폴더 아래 추가로 하위 폴더를 더 만들어서 소스들을 관리하기 위해서는 CodeIgniter의 기본 Router 클래스를 상속받아 확장해야만 가능합니다.

2단계가 넘어가는 하위 폴더별로 프로젝트 소스를 분리하여 관리하기 위해서는 본문의 "MY_Router.php" 소스를 "application/core" 폴더 아래에 복사해 두면, 서브 폴더를 다단계로 나누어 소스의 관리가 가능합니다.

참고자료