Zhu Jinhui 7 年之前
父節點
當前提交
5d6161fd09

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+.idea

+ 105 - 0
Qii/Application.php

@@ -0,0 +1,105 @@
+<?php
+namespace Qii;
+
+use \Qii\Autoloader;
+
+/**
+ * Qii 框架基本库所在路径
+ */
+define('Qii_DIR', dirname(__FILE__));
+/**
+ * DIRECTORY_SEPARATOR 的简写
+ */
+define('DS', DIRECTORY_SEPARATOR);
+/**
+ * 定义包含的路径分隔符
+ */
+define('PS', PATH_SEPARATOR);
+/**
+ * 定义操作系统类型
+ */
+define('OS', strtoupper(substr(PHP_OS, 0, 3)));
+
+define('IS_CLI', php_sapi_name() == 'cli' ? true : false);
+
+include(Qii_DIR . DS .'Autoloader'. DS . 'Factory.php');
+include(Qii_DIR . DS .'Config'. DS . 'Arrays.php');
+
+class Application 
+{
+    /**
+     * 存储网站配置文件内容
+     *
+     * @var array $_config 配置内容
+     */
+    protected static $_config = [];
+
+	public function __construct()
+	{
+		
+	}
+
+    /**
+     * 初始化本实例对象
+     *
+     * @return object
+     */
+	public static function getInstance()
+	{
+
+	    return \Qii\Autoloader\Factory::getInstance('\Qii\Application');
+	}
+
+    /**
+     * 设置网站配置文件
+     *
+     * @param array $config 配置文件
+     */
+	public function setConfig($config = [])
+	{
+        \Qii\Autoloader\Factory::getInstance('\Qii\Config\Arrays')
+            ->set('Application', $config);
+	}
+
+    /**
+     * 获取指定配置内容key的值
+     *
+     * @param string $key 配置内容key
+     * @return mixed|null
+     */
+	public function getConfig($key = null)
+    {
+        if(!$key) {
+            return \Qii\Autoloader\Factory::getInstance('\Qii\Config\Arrays')
+                ->get('Application');
+        }
+
+        return \Qii\Autoloader\Factory::getInstance('\Qii\Config\Arrays')
+            ->get('Application['.$key.']');
+    }
+
+	public function setRoute($route = [])
+    {
+        Application::$_config['route'] = $route;
+    }
+	
+	public function run()
+	{
+		print_r($this->getConfig());
+	}
+
+	public static function _i()
+    {
+
+    }
+
+    /**
+     * 抛出异常
+     *
+     * @return mixed
+     */
+    public static function _e()
+    {
+        return call_user_func_array(array('\Qii\Exceptions\Errors', 'e'), func_get_args());
+    }
+}

+ 25 - 0
Qii/Autoloader/Factory.php

@@ -0,0 +1,25 @@
+<?php
+namespace Qii\Autoloader;
+
+use \Qii\Exceptions;
+
+class Factory
+{
+    protected static $_instance = [];
+
+    public static function getInstance($className)
+    {
+        if(!$className)
+        {
+            return \_e('CLASS_NAME_IS_NULL', $className);
+        }
+        if(isset(Factory::$_instance[$className]) &&
+            Factory::$_instance[$className] != null
+        ){
+            return Factory::$_instance[$className];
+        }
+        Factory::$_instance[$className] = new $className;
+
+        return Factory::$_instance[$className];
+    }
+}

+ 0 - 0
Qii/Autoloader/Import.php


+ 415 - 0
Qii/Autoloader/Psr.php

@@ -0,0 +1,415 @@
+<?php
+namespace \Qii\Autoloader;
+
+/**
+ * Psr4 规范
+ *
+ */
+class Psr4
+{
+    /**
+     * 将查找过的文件放入缓存
+     */
+    protected static $cachedFiles = array();
+    /**
+     * 是否使用namespace
+     */
+    protected $useNamespace = array();
+    /**
+     * 添加namespace前缀对应的目录,只要是以这个前缀开头的文件都在指定目录中去查找
+     * 前缀可以对应多个目录,找的时候会去遍历数组
+     * @var array
+     */
+    protected $prefixes = array();
+
+    /**
+     * 当前class的初始化
+     */
+    private static $_instance = null;
+
+    /**
+     * @var APP_LOAD_PREFIX 保存类到以APP_LOAD_PREFIX开头的key中
+     */
+    const APP_LOAD_PREFIX = '__qii_psr4_instance';
+    /**
+     * @var $_loadedClass 保存加载过的类
+     */
+    protected static $_loadedClass = array();
+
+    /**
+     * @var $_realpath 将转换后的路径存放到此变量中
+     */
+    protected static $_realpath = array();
+
+    /**
+     * 最后一次没有加载到文件的错误路径
+     * @var array $lastErrorLoadedFile
+     */
+    protected static $lastErrorLoadedFile = array();
+
+    /**
+     * 注册自动加载类
+     *
+     */
+    private function __construct()
+    {
+    }
+
+    /**
+     * 单例模式
+     */
+    public static function getInstance()
+    {
+        if (self::$_instance == null) {
+            self::$_instance = new self();
+        }
+        return self::$_instance;
+    }
+
+    /**
+     * 注册自动加载类
+     *
+     * @return void
+     */
+    public function register()
+    {
+        spl_autoload_register(array($this, 'loadFileByClass'));
+        return $this;
+    }
+
+    /**
+     * Setting is use namespace for class
+     *
+     * @param $prefix 以prefix前缀开头的使用namespace
+     * @param bool $useNamespace
+     * @return object $this
+     */
+    public function setUseNamespace($prefix, $useNamespace = true)
+    {
+        $this->useNamespace[$prefix] = $useNamespace;
+        return $this;
+    }
+
+    /**
+     * Adds a base directory for a namespace prefix.
+     *
+     * @param string $prefix The namespace prefix.
+     * @param string $baseDir A base directory for class files in the
+     * namespace.
+     * @param bool $prepend If true, prepend the base directory to the stack
+     * instead of appending it; this causes it to be searched first rather
+     * than last.
+     * @return void
+     */
+    public function addNamespace($prefix, $baseDir, $prepend = false)
+    {
+        // normalize namespace prefix
+        $prefix = trim($prefix, '\\') . '\\';
+
+        // normalize the base directory with a trailing separator
+        $baseDir = rtrim($baseDir, '/') . DIRECTORY_SEPARATOR;
+        $baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR) . '/';
+
+        // initialize the namespace prefix array
+        if (isset($this->prefixes[$prefix]) === false) {
+            $this->prefixes[$prefix] = array();
+        }
+        if (in_array($baseDir, $this->prefixes[$prefix])) {
+            return $this;
+        }
+        // retain the base directory for the namespace prefix
+        if ($prepend) {
+            array_unshift($this->prefixes[$prefix], $baseDir);
+        } else {
+            array_push($this->prefixes[$prefix], $baseDir);
+        }
+        return $this;
+    }
+
+    /**
+     * 移除某一个namespace下的指定路径
+     * @param string $prefix 前缀
+     * @param string $baseDir 路径
+     * @return array
+     */
+    public function removeNameSpace($prefix, $baseDir)
+    {
+        // normalize namespace prefix
+        $prefix = trim($prefix, '\\') . '\\';
+
+        // normalize the base directory with a trailing separator
+        $baseDir = rtrim($baseDir, '/') . DIRECTORY_SEPARATOR;
+        $baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR) . '/';
+        // initialize the namespace prefix array
+        if (isset($this->prefixes[$prefix]) === false) {
+            return false;
+        }
+        foreach ($this->prefixes[$prefix] AS $key => $dir) {
+            if ($dir == $baseDir) unset($this->prefixes[$prefix][$key]);
+        }
+        return $this->prefixes;
+    }
+
+    /**
+     * 返回namespace路径
+     */
+    public function getNamespace($prefix)
+    {
+        // normalize namespace prefix
+        $prefix = trim($prefix, '\\') . '\\';
+        if (isset($this->prefixes[$prefix])) return $this->prefixes[$prefix];
+        return '';
+    }
+
+    /**
+     * 通过文件名返回路径
+     * @param string $fileName 文件名
+     * @return string
+     */
+    public function getFileByPrefix($fileName)
+    {
+        $fileName = str_replace(array('/', '\\'), DS, $fileName);
+        $prefixes = explode(DS, $fileName, 2);
+        $dirs = isset($this->prefixes['workspace\\']) ? $this->prefixes['workspace\\'] : array();
+        if (count($prefixes) == 2) {
+            if (isset($this->prefixes[$prefixes[0]])) $dirs = $this->prefixes[$prefixes[0]];
+        }
+        foreach ($dirs as $baseDir) {
+            if (is_file($baseDir . DS . $fileName)) {
+                return $baseDir . DS . $fileName;
+            }
+        }
+        return $fileName;
+    }
+
+    /**
+     * 获取指定文件夹路径
+     * @param string $folder 路径
+     * @return string 路径
+     */
+    public function getFolderByPrefix($folder)
+    {
+        $fileName = str_replace(array('/', '\\'), DS, $folder);
+        $prefixes = explode(DS, $fileName, 2);
+        $dirs = isset($this->prefixes['workspace\\']) ? $this->prefixes['workspace\\'] : array();
+        if (count($prefixes) == 2) {
+            if (isset($this->prefixes[$prefixes[0]])) $dirs = $this->prefixes[$prefixes[0]];
+        }
+        foreach ($dirs as $baseDir) {
+            return $baseDir . DS . $folder;
+        }
+        return $folder;
+    }
+
+    /**
+     * 通过类名加载文件
+     * @param string $class 类名
+     * @return string 文件路径
+     */
+    public function loadFileByClass($class)
+    {
+        // the current namespace prefix
+        //replace "_" to "\" use common method to load class
+        $class = str_replace("_", "\\", $class);
+        $prefix = $class;
+        // work backwards through the namespace names of the fully-qualified
+        // class name to find a mapped file name
+        while (false !== $pos = strrpos($prefix, '\\')) {
+            // retain the trailing namespace separator in the prefix
+            $prefix = substr($class, 0, $pos + 1);
+
+            // the rest is the relative class name
+            $relativeClass = substr($class, $pos + 1);
+
+            // try to load a mapped file for the prefix and relative class
+            $mappedFile = $this->loadMappedFile($prefix, $relativeClass);
+            if ($mappedFile) {
+                return $mappedFile;
+            }
+
+            // remove the trailing namespace separator for the next iteration
+            // of strrpos()
+            $prefix = rtrim($prefix, '\\');
+        };
+        //如果没有找到就在workspace中去找对应的文件 额外添加的方法
+        $mappedFile = $this->loadMappedFile('workspace\\', $class);
+        if ($mappedFile) {
+            return $mappedFile;
+        }
+        $notLoaded = isset(self::$lastErrorLoadedFile[$class]) ? self::$lastErrorLoadedFile[$class] : self::getClassName($class);
+        throw new \Qii\Exceptions\FileNotFound(\Qii::i(1405, $notLoaded), __LINE__);
+    }
+
+    /**
+     * loadClass返回真正的类名
+     *
+     * @param string $class 类名
+     */
+    public function getClassName($class)
+    {
+        //如果是不使用namespace,就将namespace转换成下划线的形式
+        $useNamespace = false;
+        //将_隔开的统一替换成namespace方式,如果不使用namespace就再替换回来
+        $class = str_replace('_', '\\', $class);
+        if (stristr($class, '\\')) {
+            $prefix = explode('\\', ltrim($class, '\\'))[0];
+            $useNamespace = isset($this->useNamespace[$prefix]) && $this->useNamespace[$prefix] ? true : false;
+        }
+        if (!$useNamespace) {
+            $class = str_replace('\\', '_', $class);
+        }
+        return $class;
+    }
+
+    /**
+     * Loads the class file for a given class name.
+     *
+     * @param string $class The fully-qualified class name.
+     * @return mixed The mapped file name on success, or boolean false on
+     * failure.
+     */
+    public function loadClass($class)
+    {
+        $args = func_get_args();
+        //去掉第一个斜杠
+        $class = array_shift($args);
+        $class = preg_replace("/^\\\\/", "", $class);
+        $class = $this->getClassName($class);
+        array_unshift($args, $class);
+
+        if (class_exists($class, false)) {
+            return call_user_func_array(array($this, 'instance'), $args);
+        }
+        if ($this->loadFileByClass($class)) {
+            return call_user_func_array(array($this, 'instance'), $args);
+        }
+        throw new \Qii\Exceptions\ClassNotFound(\Qii::i(1103, $class), __LINE__);
+    }
+
+    /**
+     * 调用静态的方法
+     * @param string $class 类名
+     * @param string $method 方法名
+     * @return mixed
+     */
+    public static function loadStatic($class, $method)
+    {
+        $args = func_get_args();
+        $class = \Qii\Autoloader\Psr4::getInstance()->getClassName(array_shift($args));
+        $method = array_shift($args);
+        return call_user_func_array(array($class, $method), $args);
+    }
+
+    /**
+     * 获取文件的绝对路径
+     * @param string $path
+     * @param bool $exists 是否使用realpath
+     * @return string  真实路径
+     */
+    public static function realpath($path)
+    {
+        if (isset(self::$_realpath[$path])) return self::$_realpath[$path];
+        $drive = '';
+        if (OS === 'WIN') {
+            $path = preg_replace('/[\\\\\/]/', DIRECTORY_SEPARATOR, $path);
+            if (preg_match('/(phar\:\\\\|[a-zA-Z]\:)(.*)/', $path, $matches)) {
+                list(, $drive, $path) = $matches;
+            } else {
+                $cwd = getcwd();
+                $drive = substr($cwd, 0, 2);
+                if (substr($path, 0, 1) != DIRECTORY_SEPARATOR) {
+                    $path = substr($cwd, 3) . DIRECTORY_SEPARATOR . $path;
+                }
+            }
+        } elseif (substr($path, 0, 1) != DIRECTORY_SEPARATOR) {
+            $path = getcwd() . DIRECTORY_SEPARATOR . $path;
+        }
+        $stack = array();
+        $parts = explode(DIRECTORY_SEPARATOR, $path);
+        foreach ($parts as $dir) {
+            if (strlen($dir) && $dir !== '.') {
+                if ($dir == '..') {
+                    array_pop($stack);
+                } else {
+                    array_push($stack, $dir);
+                }
+            }
+        }
+        $realPath = str_replace(DIRECTORY_SEPARATOR, '/', $drive . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $stack));
+        self::$_realpath[$path] = $realPath;
+        return $realPath;
+    }
+
+    /**
+     * Load the mapped file for a namespace prefix and relative class.
+     *
+     * @param string $prefix The namespace prefix.
+     * @param string $relativeClass The relative class name.
+     * @return mixed Boolean false if no mapped file can be loaded, or the
+     * name of the mapped file that was loaded.
+     */
+    protected function loadMappedFile($prefix, $relativeClass)
+    {
+        if (isset(self::$cachedFiles[$prefix . '_' . $relativeClass])) return self::$cachedFiles[$prefix . '_' . $relativeClass];
+        // are there any base directories for this namespace prefix?
+        if (isset($this->prefixes[$prefix]) === false) {
+            //if there any base directories , add self to prefix
+            $this->addNamespace($prefix, $prefix);
+            //return false;
+        }
+        $prefix = trim($prefix, '\\') . '\\';
+        $file = '';
+        // look through base directories for this namespace prefix
+        foreach ($this->prefixes[$prefix] as $baseDir) {
+            $file = str_replace("/", DS, $baseDir
+                . str_replace('\\', DS, $relativeClass)
+                . '.php');
+            // if the mapped file exists, require it
+            if ($this->requireFile($file)) {
+                self::$cachedFiles[$prefix . '_' . $relativeClass] = $file;
+                return $file;
+            }
+        }
+        self::$lastErrorLoadedFile[$relativeClass] = $file;
+        // never found it
+        return false;
+    }
+
+    /**
+     * If a file exists, require it from the file system.
+     *
+     * @param string $file The file to require.
+     * @return bool True if the file exists, false if not.
+     */
+    protected function requireFile($file)
+    {
+        return \Qii\Autoloader\Import::requires($file);
+    }
+
+    /**
+     * instance class
+     * @param string $class
+     * @return object
+     */
+    public function instance()
+    {
+        $args = func_get_args();
+        $class = array_shift($args);
+        $className = $this->getClassName($class);
+        if (isset(self::$_loadedClass[$className])) return self::$_loadedClass[$className];
+        if (!class_exists($className, false)) {
+            throw new \Qii\Exceptions\CallUndefinedClass(\Qii\Application::i('1105', $className), __LINE__);
+        }
+        $loader = new \ReflectionClass($className);
+        //try {
+        self::$_loadedClass[$className] = $instance = $loader->newInstanceArgs($args);
+        //如果有_initialize方法就自动调用_initialize方法,并将参数传递给_initialize方法
+        if ($loader->hasMethod('_initialize')) {
+            call_user_func_array(array($instance, '_initialize'), $args);
+        }
+        return $instance;
+        /*} catch (Exception $e) {
+            throw new \Exception($e->getMessage(), __LINE__);
+        }*/
+    }
+}

+ 158 - 0
Qii/Config/Arrays.php

@@ -0,0 +1,158 @@
+<?php
+namespace Qii\Config;
+/**
+ * 实现PHP中数组功能
+ *
+ * 用法:
+ *
+ * $array = new \Qii\Config\Arrays();
+ *
+ * $data = array();
+ * $data['common']['one'] = '1';
+ * $data['common']['two'] = '1';
+ * $data['common']['three'] = '1';
+ *
+ * $array->getValueFromArray($data, '[common][three]');
+ *
+ * $array->set('string', 'string');
+ * $array->set('array[val][]', array(1, 2));
+ * $array->set('array[val][]', array(3, 4));
+ *
+ * $array->get('string');
+ *
+ * $array->get('array[val]');
+ *
+ * $array->get('array[val][0]');
+ *
+ * $array->get('array[val][1]');
+ *
+ *
+ */
+
+class Arrays
+{
+	const VERSION = '1.2';
+	protected $_private = array();
+
+	public function __construct()
+	{
+
+	}
+
+	public function __toString()
+	{
+		return self::VERSION;
+	}
+
+	/**
+	 * 直接从数组中获取指定key的值
+	 *
+	 * @param Array $data
+	 * @param String $key
+	 * @return Mix
+	 */
+	public function getValueFromArray($data, $key)
+	{
+		if (preg_match('/^\s*$/', $key)) {
+			return $data;
+		}
+		preg_match_all("/(.*?)\[(.*?)\]/", $key, $match);
+
+		$name = $match[1][0];
+		$keys = $match[2];
+
+		if ($name == '') {
+			return isset($data[$key]) ? $data[$key] : '';
+		}
+		if (!isset($data[$name])) {
+			return '';
+		}
+		$value = $data[$name];
+		foreach ($keys AS $key) {
+			if ($key == '') {
+				$value = $value;
+			} else {
+				$value = $value[$key];
+			}
+		}
+		return $value;
+	}
+
+	/**
+	 * 实现PHP数组赋值
+	 *
+	 * @param String $key
+	 * @param Mix $value
+	 * @return Array
+	 */
+	public function set($key, $value)
+	{
+		preg_match_all("/(.*?)\[(.*?)\]/", $key, $match);
+		$name = '';
+		if (isset($match[1]) && isset($match[1][0])) {
+			$name = $match[1][0];
+		}
+		$keys = $match[2];
+		if ($name == '') {
+			$name = $key;
+		}
+		if (empty($keys)) {
+			$this->_private[$key] = $value;
+			return $this->_private;
+		}
+		$private = array();
+		$private = array_merge($private, $keys);
+		$privates = null;
+		if (is_array($value) || is_object($value)) {
+			$array = str_replace('[\'\']', '[]', '$privates[\'' . join("']['", $private) . '\']=$value;');
+		} else {
+			$array = str_replace('[\'\']', '[]', '$privates[\'' . join("']['", $private) . '\']=\'' . $value . '\';');
+		}
+		eval($array);
+		if (isset($this->_private[$name])) {
+			if (!is_array($this->_private[$name])) {
+				unset($this->_private[$name]);
+				$this->_private[$name] = $privates;
+			} else {
+				$this->_private[$name] = array_merge_recursive($this->_private[$name], $privates);
+			}
+		} else {
+			$this->_private[$name] = $privates;
+		}
+		return $this->_private;
+	}
+
+	/**
+	 * 获取通过setPrivate key对应的值
+	 *
+	 * @param String $key
+	 * @return Mix
+	 */
+	public function get($key)
+	{
+		if (preg_match('/^\s*$/', $key)) {
+			return $this->_private;
+		}
+		preg_match_all("/(.*?)\[(.*?)\]/", $key, $match);
+		$name = '';
+		if (isset($match[1]) && isset($match[1][0])) {
+			$name = $match[1][0];
+		}
+		$keys = $match[2];
+		if ($name == '') {
+			return isset($this->_private[$key]) ? $this->_private[$key] : '';
+		}
+		if (!isset($this->_private[$name])) {
+			return '';
+		}
+		$value = $this->_private[$name];
+		foreach ($keys AS $key) {
+			if ($key == '') {
+				$value = $value;
+			} else {
+				$value = $value[$key];
+			}
+		}
+		return $value;
+	}
+}

+ 331 - 0
Qii/Config/Register.php

@@ -0,0 +1,331 @@
+<?php
+namespace \Qii\Consts;
+
+/**
+ * 将键值保存到\Qii\Config\Register::$config中
+ * 用于保存系统相关设置,保存项目相关的配置,请注意不出现key相互覆盖的情况,可以考虑加前缀
+ *
+ * @author Jinhui Zhu
+ * @version 1.3
+ *
+ * Usage:
+ *    保存值:
+ *        \Qii\Config\Register::set($key, $val);
+ *    读取值:
+ *        \Qii\Config\Register::get($key, $default);
+ *        \Qii\Config\Register::$key($default);
+ *
+ *
+ */
+class Register
+{
+	const VERSION = '1.3';
+	/**
+	 * 存储键值的变量
+	 *
+	 * @var Array
+	 */
+	public static $_cache;
+
+	/**
+	 * 设置键值
+	 *
+	 * @param String $key
+	 * @param String $val
+	 * @param Bool overwrite 是否覆盖之前保存的值,如果之前保存了值,要想再保存需要额外设置它为true,否则不让保存
+	 */
+	public static function set($key, $val, $overwrite = true)
+	{
+		if (!\Qii\Config\Register::isValid($key, $overwrite)) \Qii\Application::_e('Overwrite', $key, __LINE__);
+		\Qii\Config\Register::$_cache[$key] = $val;
+	}
+
+	/**
+	 * 设置键
+	 *
+	 * @param String $index
+	 * @param String $key
+	 * @param String $val
+	 */
+	public static function add($index, $key, $val)
+	{
+		$added = \Qii\Config\Register::get(\Qii\Consts\Config::APP_LOADED_FILE, array());
+		$added[$index][$key] = $val;
+		\Qii\Config\Register::$_cache[$index] = $added;
+	}
+
+	/**
+	 * 移除某一个key
+	 * @param String $key
+	 */
+	public static function remove($key)
+	{
+		if (!isset(\Qii\Config\Register::$_cache[$key])) return;
+		unset(\Qii\Config\Register::$_cache[$key]);
+	}
+
+	/**
+	 * 获取保存的值
+	 *
+	 * @param String $key
+	 * @param String $index
+	 * @param Mix $default
+	 * @return Mix
+	 */
+	public static function get($key, $default = null)
+	{
+		if (!$key) throw new Qii_Exceptions_Variable(\Qii::i(1003), __LINE__);
+		//优先调用存在的get方法
+		$method = 'get' . $key;
+		if (method_exists('\Qii\Config\Register', $method)) return \Qii\Config\Register::$method();
+
+		if (isset(\Qii\Config\Register::$_cache[$key])) {
+			return \Qii\Config\Register::$_cache[$key];
+		}
+		return $default;
+	}
+
+	/**
+	 * 通过\Qii\Config\Register::$key($defaultVal)来获取内容
+	 *
+	 * @param String $method
+	 * @param Array $argvs
+	 * @return Mix
+	 */
+	public static function __callStatic($method, $argvs)
+	{
+		$default = array_shift($argvs);
+		return \Qii\Config\Register::get($method, $default);
+	}
+
+	/**
+	 * 整理数组,将0.key 最后会整理到 [0][key]中
+	 * @param Array $array
+	 * @return multitype:
+	 */
+	public static function feval($array)
+	{
+		$data = array();
+		foreach ($array AS $key => $value) {
+			$keys = explode('.', $key);
+			if (is_array($value)) {
+				$string = "\$data['" . join("']['", $keys) . "']=" . var_export(\Qii\Config\Register::feval($value), true) . ";";
+			} else {
+				$string = "\$data['" . join("']['", $keys) . "']='" . $value . "';";
+			}
+			eval($string);
+		}
+		return $data;
+	}
+
+	/**
+	 * 读取ini配置文件
+	 *
+	 * @param String $fileName
+	 * @return Array
+	 */
+	public static function ini($fileName)
+	{
+		if (!$fileName) throw new Qii_Exceptions_Variable(\Qii::i(1408), __LINE__);
+		$ini = parse_ini_file($fileName, true);
+		if (!$ini) throw new \Qii_Exceptions_InvalidFormat($fileName, __LINE__);
+		$config = array();
+		foreach ($ini AS $namespace => $properties) {
+			$properties = \Qii\Config\Register::feval($properties);
+			$extends = '';
+			$name = $namespace;
+			$namespaces = array();
+			if (stristr($namespace, ':')) {
+				$namespaces = explode(':', $namespace);
+				$name = array_shift($namespaces);
+			}
+			$name = trim($name);
+			$config[$name] = $properties;
+			if (count($namespaces) > 0) {
+				foreach ($namespaces AS $space) {
+					//如果space以“.”开头,与key的方式放在当前key下边如[dev:.space],那么生成后的数据就是这样的[dev][space]否则是[space+dev]
+					if (substr($space, 0, 1) == '.') {
+						$space = substr($space, 1);
+						if (isset($config[$space])) $config[$name][$space] = $config[$space];
+						continue;
+					}
+					if (isset($config[$space])) $config[$name] = array_merge($config[$space], $config[$name]);
+				}
+			}
+		}
+		return $config;
+	}
+
+	/**
+	 * 返回cache的名称
+	 * @param String $iniFile
+	 * @return String
+	 */
+	public static function getCacheName($iniFile)
+	{
+		$cacheName = basename($iniFile);
+		$environs = \Qii\Config\Register::get(\Qii\Consts\Config::APP_ENVIRONS, array());
+		if (isset($environs[$cacheName])) {
+			$environ = $environs[$cacheName];
+			$cacheName = $environ . '.' . $cacheName;
+		}
+		return $cacheName;
+	}
+
+	/**
+	 * 覆盖/添加ini文件的key对应的值
+	 * @param String $iniFile ini文件名
+	 * @param String $key 需覆盖的key
+	 * @param String $val key对应的值
+	 */
+	public static function rewriteConfig($iniFile, $key, $val)
+	{
+		$config = \Qii\Config\Register::getIniConfigure($iniFile);
+		$cacheName = \Qii\Config\Register::getCacheName($iniFile);
+		$config[$key] = $val;
+		\Qii\Config\Register::set($cacheName, $config);
+	}
+	/**
+	 * 删除ini配置文件中对应的key
+	 * @param string $iniFile ini配置我呢见
+	 * @param string $key 陪删除的key
+	 */
+	public static function removeAppConfigure($iniFile, $key)
+	{
+		$config = \Qii\Config\Register::getIniConfigure($iniFile);
+		$cacheName = \Qii\Config\Register::getCacheName($iniFile);
+		unset($config[$key]);
+		\Qii\Config\Register::set($cacheName, $config);
+	}
+
+	/**
+	 * 合并ini文件生成的数组
+	 * @param String $iniFile ini文件名
+	 * @param Array $array
+	 */
+	public static function mergeAppConfigure($iniFile, $array)
+	{
+		if (!is_array($array)) return;
+		$config = \Qii\Config\Register::getIniConfigure($iniFile);
+
+		$environs = \Qii\Config\Register::get(\Qii\Consts\Config::APP_ENVIRONS, array());
+
+		$cacheName = basename($iniFile);
+		if (isset($environs[$cacheName])) {
+			$environ = $environs[$cacheName];
+			$cacheName = $environ . '.' . $cacheName;
+		}
+		$config = array_merge($config, $array);
+		\Qii\Config\Register::set($cacheName, $config);
+	}
+
+	/**
+	 * 获取配置ini文件
+	 * @param String $iniFile
+	 * @param String $environ
+	 * @return boolean
+	 */
+	public static function setConfig($iniFile, $environ = 'product')
+	{
+		$cacheName = basename($iniFile);
+		$environs = \Qii\Config\Register::get(\Qii\Consts\Config::APP_ENVIRONS, array());
+		$environs[$cacheName] = $environ;
+		\Qii\Config\Register::set(\Qii\Consts\Config::APP_ENVIRONS, $environs);
+
+		$cacheName = $environ . '.' . $cacheName;
+		if (!is_file($iniFile)) return false;
+		$cacheFile = \Qii\Autoloader\Psr4::getInstance()->getFileByPrefix(\Qii\Config\Register::get(\Qii\Consts\Config::APP_CACHE_PATH) . DS . $cacheName . '.php');
+		if (\Qii\Config\Register::get(\Qii\Consts\Config::APP_CACHE_PATH)) {
+			if (is_file($cacheFile)) {
+				if (filemtime($cacheFile) == filemtime($iniFile)) {
+					$common = include($cacheFile);
+					\Qii\Config\Register::set($cacheName, $common);
+					return $common;
+				}
+			}
+		}
+		$array = \Qii\Config\Register::ini($iniFile);
+		if (!$array) return false;
+
+		$common = $array['common'];
+		if (isset($array[$environ])) {
+			$environConfig = $array[$environ];
+			$common = array_merge($common, $environConfig);
+		}
+		//如果文件不可写,touch就有问题,就不写缓存文件
+		if (is_writeable($iniFile)) {
+			file_put_contents($cacheFile, "<?php \n return " . var_export($common, true) . "\n?>", LOCK_EX);
+			touch($iniFile);
+		}
+		\Qii\Config\Register::set($cacheName, $common);
+		return $common;
+	}
+
+	/**
+	 * 设置网站的配置文件
+	 *
+	 * @param String $iniFile 配置我呢见
+	 * @param string $environ 环境变量
+	 * @return Object self
+	 */
+	public static function setAppConfigure($iniFile, $environ = 'product')
+	{
+		return \Qii\Config\Register::setConfig($iniFile, $environ);
+	}
+
+	/**
+	 * 获取配置ini文件相关信息
+	 * @param String $fileName 文件名
+	 * @return Ambigous <Mix, multitype:>
+	 */
+	public static function getIniConfigure($fileName)
+	{
+		$cacheName = basename($fileName);
+		$environs = \Qii\Config\Register::get(\Qii\Consts\Config::APP_ENVIRONS, array());
+		if (isset($environs[$cacheName])) {
+			$cacheName = $environs[$cacheName] . '.' . $cacheName;
+		}
+		return \Qii\Config\Register::get($cacheName);
+	}
+
+	/**
+	 * 获取网站的配置信息
+	 *
+	 * @return Array
+	 */
+	public static function getAppConfigure($iniFile = \Qii\Consts\Config::APP_INI, $key = NULL)
+	{
+		$appConfigure = \Qii\Config\Register::getIniConfigure($iniFile);
+		if ($key == null) return $appConfigure;
+		return isset($appConfigure[$key]) ? $appConfigure[$key] : NULL;
+	}
+
+	/**
+	 * 验证是否之前已经保存过这个属性,如果保存过,不覆盖属性对应的值就不保存
+	 *
+	 * @param String $key
+	 * @param Bool $overwrite
+	 * @return Bool
+	 */
+	public static function isValid($key, $overwrite = false)
+	{
+		if ($overwrite) return true;
+		if (isset(\Qii\Config\Register::$_cache[$key])) return false;
+		return true;
+	}
+
+	/**
+	 * 获取当前系统环境
+	 * @return Ambigous <Mix, multitype:>
+	 */
+	public static function getAppEnviron()
+	{
+		return isset(\Qii\Config\Register::$_cache[\Qii\Consts\Config::APP_ENVIRON]) ?
+                    \Qii\Config\Register::$_cache[\Qii\Consts\Config::APP_ENVIRON]
+                    : \Qii\Consts\Config::APP_DEFAULT_ENVIRON;
+	}
+
+	public function __call($method, $argvs)
+	{
+	}
+}

+ 88 - 0
Qii/Config/Setting.php

@@ -0,0 +1,88 @@
+<?php
+namespace \Qii\Config;
+/**
+ * 系统设置
+ *
+ */
+class Setting
+{
+    protected static $_instance;
+    public $language;
+
+    private function __construct()
+    {
+
+    }
+
+    /**
+     * 返回Qii初始化类
+     */
+    public static function getInstance()
+    {
+        if (self::$_instance == null) {
+            self::$_instance = new self();
+        }
+        return self::$_instance;
+    }
+
+    /**
+     * 设置默认语言
+     *
+     * @return $this
+     * @throws Exception
+     */
+    public function setDefaultLanguage()
+    {
+        $this->language = \Qii_Autoloader_Psr4::getInstance()->loadClass('Qii_Language_Loader');
+        //加载语言包
+        $this->language->load('error', Qii_DIR);
+        $this->language->load('exception', Qii_DIR);
+        return $this;
+    }
+
+    /**
+     * 设置区域
+     *
+     * @return $this
+     */
+    public function setDefaultTimeZone()
+    {
+        //设置时区
+        $timezone = \Qii::getInstance()->appConfigure('timezone');
+        if ($timezone) date_default_timezone_set($timezone);
+        return $this;
+    }
+
+    /**
+     * 设置默认的controller和action
+     */
+    public function setDefaultControllerAction()
+    {
+        //设置默认controller及controller方法前缀
+        \Qii_Config_Register::set(\Qii_Const_Config::APP_DEFAULT_CONTROLLER, \Qii::getInstance()->appConfigure('controller')['default']);
+        \Qii_Config_Register::set(\Qii_Const_Config::APP_DEFAULT_CONTROLLER_PREFIX, \Qii::getInstance()->appConfigure('controller')['prefix']);
+
+        //设置默认action及方法名后缀
+        \Qii_Config_Register::set(\Qii_Const_Config::APP_DEFAULT_ACTION, \Qii::getInstance()->appConfigure('action')['default']);
+        \Qii_Config_Register::set(\Qii_Const_Config::APP_DEFAULT_ACTION_SUFFIX, \Qii::getInstance()->appConfigure('action')['suffix']);
+        return $this;
+    }
+
+    /**
+     * 设置默认的namespace
+     */
+    public function setDefaultNamespace()
+    {
+        //配置文件中如果设置了使用namespace就将指定的前缀添加到namespace中
+        $namespaces = \Qii::appConfigure('namespace');
+        if (is_array($namespaces) && isset($namespaces['use'])
+            && $namespaces['use'] && isset($namespaces['list'])
+            && is_array($namespaces['list'])
+        ) {
+            foreach ($namespaces['list'] AS $namespace => $val) {
+                \Qii::getInstance()->setUseNamespace($namespace, $val);
+            }
+        }
+        return $this;
+    }
+}

+ 37 - 0
Qii/Consts/Config.php

@@ -0,0 +1,37 @@
+<?php
+namespace Qii\Consts;
+
+/**
+ * App系统配置
+ * @author Jinhui.Zhu <jinhui.zhu@live.cn> 2015-09-21 11:31
+ *
+ */
+class Config
+{
+	const VERSION = '1.2';
+	const APP_SYS = 'Qii';//框架名,用户保存框架实例化对象
+	const APP_ENVIRONS = 'QII_ENVIRONS';//配置文件使用环境
+	const APP_ENVIRON = 'QII_ENVIRON';//当前系统使用的环境
+	const APP_DEFAULT_ENVIRON = 'product';//默认系统环境
+	const APP_DB = 'QII_APP_DB';//数据库配置
+	const APP_CONFIGURE = 'AppConfigure';//系统配置,不能修改为其他值,默认会调用此方法
+	const APP_LOADED_FILE = 'QII_APP_LOADED_FILE';//加载的文件列表
+	const APP_INI_FILE = 'QII_APP_INI_FILE';//网站配置文件列表
+	const APP_INCLUDES_FILE = 'QII_APP_INCLUDES_FILE';//保存includes过的文件列表
+	const APP_SITE_METHOD = 'rewriteMethod';//网站路由
+	const APP_SITE_ROUTER = 'QII_APP_SITE_ROUTER';//网站路由
+	const APP_DISPATCHER = 'Qii_Dispatcher';
+	const APP_SYS_DISPATCHER = 'QII_APP_SYS_DISPATCHER';
+	const APP_LOAD_PREFIX = 'Qii_Load_';//不能随意修改
+	const APP_LOAD_SYS_PREFIX = 'Qii_Load_Qii_';//不能随意修改
+	const APP_CACHE_PATH = 'QII_CACHE_PATH';//App缓存目录
+	const APP_CACHE_SYSTEM_PATH = 'QII_CACHE_SYSTEM_PATH';//框架缓存目录
+	const APP_INI = 'app.ini';//网站配置文件
+	const APP_LANGUAGE_CONFIG = 'QII_LANGUAGE_CONFIG';//语言包
+	const APP_OUTPUT_CHARSET = 'utf-8';
+	const APP_VIEW = 'QII_VIEW';//controller->_view
+	const APP_DEFAULT_CONTROLLER = 'APP_DEFAULT_CONTROLLER';//默认controller
+	const APP_DEFAULT_CONTROLLER_PREFIX = 'APP_DEFAULT_CONTROLLER_PREFIX';//默认controller
+	const APP_DEFAULT_ACTION = 'APP_DEFAULT_ACTION';//默认Action
+	const APP_DEFAULT_ACTION_SUFFIX = 'APP_DEFAULT_ACTION_SUFFIX';//默认Action后缀
+}

+ 17 - 0
Qii/Exceptions/AccessDenied.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class AccessDenied extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/Cache.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class Cache extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/CallUndefinedClass.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class CallUndefinedClass extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/ClassInstanceof.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class ClassInstanceof extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/ClassNotFound.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class ClassNotFound extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 146 - 0
Qii/Exceptions/Error.php

@@ -0,0 +1,146 @@
+<?php
+namespace \Qii\Exceptions;
+
+/**
+ *
+ * Class Qii_Exceptions_Error
+ * @package Qii
+ */
+class Error
+{
+	const VERSION = '1.2';
+
+	public function __construct()
+	{
+
+	}
+
+	public static function index()
+	{
+		$args = func_get_args();
+		echo \Qii::i('1108', $args[0], $args[1]);
+	}
+
+	/**
+	 * 返回程序的调用栈
+	 */
+	static public function getTrace()
+	{
+		return debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+	}
+
+	/**
+	 * 程序的调用栈生成字符串
+	 */
+	static public function getTraceAsString()
+	{
+		$e = new \Exception();
+		$trace = explode("\n", $e->getTraceAsString());
+		$trace = array_reverse($trace);
+		array_shift($trace);
+		array_pop($trace);
+		$length = count($trace);
+		$result = array();
+
+		for ($i = 0; $i < $length; $i++) {
+			$result[] = ($i + 1) . ')' . substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering
+		}
+
+		return "\t" . implode("\n\t", $result);
+	}
+
+	/**
+	 * 错误描述
+	 * @return string
+	 */
+	static public function getMessage()
+	{
+		$e = new \Exception();
+		return $e->getMessage();
+	}
+
+	/**
+	 * 错误码
+	 * @return int
+	 */
+	static public function getCode()
+	{
+		return __LINE__;
+	}
+
+	/**
+	 * 错误设置,如果满足给定的条件就直接返回false,否则在设置了错误页面的情况下返回true
+	 * 如果出错后要终止的话,需要自行处理,此方法不错停止不执行
+	 *
+	 * @param bool $condition
+	 * @param int $line 出错的行数,这样以便轻松定位错误
+	 * @param string $msg
+	 * @param int|string $code
+	 * @param string $args ...
+	 * @return bool
+	 */
+	public static function setError($condition, $line = 0, $code, $args = null, $msg = null)
+	{
+		if ($condition) {
+			return false;
+		}
+		$appConfigure = \Qii_Config_Register::AppConfigure();
+		//如果是调试模式就直接抛出异常
+		$isDebug = $appConfigure['debug'];
+		$message = array();
+		$message[] = explode("\n", self::getTraceAsString());
+		if (\Qii::getInstance()->logerWriter != null) {
+			$message[] = 'Referer:' . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : \Qii::getInstance()->request->url->getCurrentURL());
+			\Qii::getInstance()->logerWriter->writeLog($message);
+		}
+		if ($isDebug) {
+			$args = array_slice(func_get_args(), 2);
+			throw new \Exception(call_user_func_array(array('\Qii', 'i'), $args), $line);
+		}
+		$errorPage = $appConfigure['errorPage'];
+		$env = \Qii_Config_Register::get(\Qii_Const_Config::APP_ENVIRON, 'dev');
+		if ($env != 'product' && $errorPage != null) {
+			list($controller, $action) = explode(':', $appConfigure['errorPage']);
+			$controllerCls = \Qii_Config_Register::get(\Qii_Const_Config::APP_DEFAULT_CONTROLLER_PREFIX) . '_' . $controller;
+			$action = preg_replace('/(Action)$/i', "", $action);
+			$filePath = \Qii_Autoloader_Import::requireByClass($controllerCls);
+			if (!is_file($filePath)) {
+				if ($env == 'product') return '';
+				\Qii_Autoloader_Import::requires(Qii_DIR . DS . 'Exceptions' . DS . 'Error.php');
+				call_user_func_array(array('\Qii_Exceptions_Error', 'index'), array($controller, $action));
+				die();
+			} else {
+				\Qii::getInstance()->request->setControllerName($controller);
+                \Qii::getInstance()->request->setActionName($action);
+                \Qii::getInstance()->dispatcher->setRequest(\Qii::getInstance()->request);
+				\Qii::getInstance()->dispatcher->dispatch($controller, $action, new \Exception($msg ? $msg : self::getTraceAsString(), $code));
+				die();
+			}
+			return;
+		}
+		return true;
+	}
+
+	/**
+	 * 显示错误信息
+	 * @param Array $message
+	 */
+	public static function showError($message)
+	{
+		include(join(DS, array(Qii_DIR ,'Exceptions', 'view', 'error.php')));
+	}
+
+	/**
+	 * 显示错误信息
+	 * @param Array $message
+	 */
+	public static function showMessage($message)
+	{
+		include(join(DS, array(Qii_DIR, 'Exceptions', 'view', 'message.php')));
+	}
+
+	public function __call($method, $args)
+	{
+		if (method_exists(self, $method)) return call_user_func_array(array('Qii_Exceptions_Error', $method), $args);
+	}
+}

+ 143 - 0
Qii/Exceptions/Errors.php

@@ -0,0 +1,143 @@
+<?php
+namespace \Qii\Exceptions;
+
+class Errors extends \Exception
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 获取两个文件的相对路径
+	 * @param String $cur
+	 * @param String $absp
+	 * @return String
+	 */
+	public static function getRelatePath($cur, $absp)
+	{
+		$cur = str_replace('\\', '/', $cur);
+		$absp = str_replace('\\', '/', $absp);
+		$sabsp = explode('/', $absp);
+		$scur = explode('/', $cur);
+		$la = count($sabsp) - 1;
+		$lb = count($scur) - 1;
+		$l = max($la, $lb);
+
+		for ($i = 0; $i <= $l; $i++) {
+			if ($sabsp[$i] != $scur[$i])
+				break;
+		}
+		$k = $i - 1;
+		$path = "";
+		for ($i = 1; $i <= ($lb - $k - 1); $i++)
+			$path .= "../";
+		for ($i = $k + 1; $i <= ($la - 1); $i++)
+			$path .= $sabsp[$i] . "/";
+		$path .= $sabsp[$la];
+		return $path;
+	}
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+		$message = array();
+		if (isset($_GET['isAjax']) && $_GET['isAjax'] == 1) {
+			echo json_encode(array('code' => $e->getCode(), 'msg' => strip_tags($e->getMessage())), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
+			return;
+		}
+		$message[] = Qii::i('Error file', self::getRelatePath($_SERVER['SCRIPT_FILENAME'], $e->getFile()));
+		$message[] = Qii::i('Error code', $e->getCode());
+		$message[] = Qii::i('Error description', $e->getMessage());
+		$message[] = Qii::i('Error line', $e->getLine() . ' on ' . self::getLineMessage($e->getFile(), $e->getLine()));
+		$traceString = Qii::i('Trace as below') . '<br />';
+		$traces = explode("\n", $e->getTraceAsString());
+		foreach ($traces AS $trance) {
+			$traceString .= "&nbsp;&nbsp;&nbsp;&nbsp;" . $trance . '<br />';
+		}
+		$message[] = $traceString;
+		if (\Qii::getInstance()->logerWriter != null) {
+			$message[] = 'Source URL:' . \Qii::getInstance()->request->url->getCurrentURL();
+			$message[] = 'Referer URL:' . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : \Qii::getInstance()->request->url->getCurrentURL());
+			\Qii::getInstance()->logerWriter->writeLog($message);
+		}
+		$appConfigure = Qii_Config_Register::AppConfigure();
+
+		$env = Qii_Config_Register::get(\Qii_Const_Config::APP_ENVIRON, 'dev');
+		if ($env == 'product' || ($appConfigure['errorPage'] && (isset($appConfigure['debug']) && $appConfigure['debug'] == 0))) {
+			list($controller, $action) = explode(':', $appConfigure['errorPage']);
+			$controllerCls = \Qii_Config_Register::get(\Qii_Const_Config::APP_DEFAULT_CONTROLLER_PREFIX) . '_' . $controller;
+			$action = preg_replace('/(Action)$/i', "", $action);
+			$filePath = \Qii_Autoloader_Import::requireByClass($controllerCls);
+			if (!is_file($filePath)) {
+				if ($env == 'product') return '';
+				\Qii_Autoloader_Import::requires(Qii_DIR . DS . 'Exceptions' . DS . 'Error.php');
+				call_user_func_array(array('\Qii_Exceptions_Error', 'index'), array($controller, $action));
+				die();
+			} else {
+				\Qii::getInstance()->request->setControllerName($controller);
+				\Qii::getInstance()->request->setActionName($action);
+				\Qii::getInstance()->dispatcher->setRequest(\Qii::getInstance()->request);
+				\Qii::getInstance()->dispatcher->dispatch($controller, $action, $e);
+				die();
+			}
+		}
+		include(join(DS, array(Qii_DIR, 'Exceptions', 'View', 'error.php')));
+	}
+
+	/**
+	 * 获取指定文件的指定行内容
+	 *
+	 * @param String $fileName 文件名
+	 * @param Int $line 行号
+	 * @return String
+	 */
+	public static function getLineMessage($fileName, $line)
+	{
+		$seekline = max(0, $line - 1);
+		$spl = new \SplFileObject($fileName);
+		$code = array();
+		if ($line > 1) {
+			$maxLine = 10;
+			$firstLine = max(0, $seekline - $maxLine);
+
+			$spl->seek($firstLine);
+			$min = $seekline - $maxLine;
+			$max = $seekline + $maxLine + 1;
+
+			for ($i = $min; $i < $max; $i++) {
+				$currentLine = $i + ($min < 0 ? abs($min) : 0) + 1;
+				$color = $currentLine == $line ? ' color="red"' : '';
+				if ($spl->eof()) break;
+				$code[] = '<font ' . $color . '>' . $currentLine . ':</font>' . "\t" . '<font ' . $color . '>' . htmlspecialchars(rtrim($spl->current())) . '</font>';
+				$spl->next();
+			}
+		} else {
+			$spl->seek($seekline);
+			$code[] = htmlspecialchars(rtrim($spl->current()));
+		}
+		return '<pre style="font-weight:bold;">' . join("<br />", $code) . '</pre>';
+	}
+
+	/**
+	 * sprintf 格式化语言错误信息内容
+	 *
+	 *
+	 * Qii::e($message, $argv1, $argv2, ..., $line);
+	 * $message = sprintf($message, $argv1, $argv2, ...);
+	 * throw new \Qii_Exceptions_Errors($message, $line);
+	 */
+	public static function e()
+	{
+		$argvs = func_get_args();
+		$count = count($argvs);
+		$message = array_shift($argvs);
+		$line = (int) array_pop($argvs);
+		if ($count == 2) {
+			throw new \Qii_Exceptions_Errors($message, $line);
+		}
+		$message = vsprintf($message, $argvs);
+		throw new \Qii_Exceptions_Errors($message, $line);
+	}
+}

+ 17 - 0
Qii/Exceptions/FileNotFound.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class FileNotFound extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/FolderDoesNotExist.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class FolderDoesNotExist extends Errors
+{
+    const VERSION = '1.2';
+
+    /**
+     * 显示错误
+     *
+     * @param Object $e Exception
+     */
+    public static function getError($e)
+    {
+
+    }
+}

+ 17 - 0
Qii/Exceptions/InvalidFormat.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class InvalidFormat extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 16 - 0
Qii/Exceptions/MethodNotFound.php

@@ -0,0 +1,16 @@
+<?php
+namespace \Qii\Exceptions;
+
+class MethodNotFound extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+	}
+}

+ 17 - 0
Qii/Exceptions/NotAllowed.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class NotAllowed extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/Overwrite.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class Overwrite extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/Response.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class Response extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/TableException.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class TableException extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/Unsupport.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class Unsupport extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 17 - 0
Qii/Exceptions/Variable.php

@@ -0,0 +1,17 @@
+<?php
+namespace \Qii\Exceptions;
+
+class Variable extends Errors
+{
+	const VERSION = '1.2';
+
+	/**
+	 * 显示错误
+	 *
+	 * @param Object $e Exception
+	 */
+	public static function getError($e)
+	{
+
+	}
+}

+ 1 - 0
Qii/Exceptions/View/404.php

@@ -0,0 +1 @@
+404 Not found.

+ 31 - 0
Qii/Exceptions/View/error.php

@@ -0,0 +1,31 @@
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta http-equiv="content-type" content="text/html;charset=utf-8">
+    <title><?php echo Qii::i('Throw Exception'); ?></title>
+    <?php
+    include(dirname(__FILE__) . DS . 'style.php');
+    ?>
+</head>
+<body>
+
+<h1><font color="red"><?php echo Qii::i('Throw Exception'); ?></font></h1>
+
+<p style="text-align:right;"><?php echo Qii::i('The page you are looking at is being generated dynamically by Qii'); ?></p>
+
+<ul><?php echo Qii::i('Error information'); ?>
+    <?php
+    //$messageArray = Qii::getPrivate('error');
+    foreach ($message AS $error) {
+        ?>
+        <li><code><?= $error; ?></code></li>
+        <?php
+    }
+    ?>
+</ul>
+<?php
+include(dirname(__FILE__) . DS . 'footer.php');
+?>
+
+</body>
+</html>

+ 372 - 0
Qii/Exceptions/View/example.php

@@ -0,0 +1,372 @@
+<html xmlns="http://www.w3.org/1999/html">
+<head>
+    <title>使用方法 - Qii Framework</title>
+    <meta name="keywords" content="Qii框架,PHP开发框架">
+	<meta name="description" content="Qii 框架,以最简单的方式创建你的Web应用。" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta http-equiv="content-type" content="text/html;charset=utf-8">
+    <?php include(Qii_DIR . '/view/style.php'); ?>
+</head>
+<body>
+<h1>使用方法:</h1>
+<ul>
+    <li><a href="#createProject">创建项目</a></li>
+    <li><a href="#env">设置环境</a></li>
+    <li><a href="#useFramework">框架的使用</a>
+        <ul>
+            <li><a href="#useCommandLine">1)命令行运行程序</a></li>
+            <li><a href="#autoload">2) 自动加载类</a></li>
+            <li><a href="#basicMethod">3) Qii 基本功能:</a></li>
+            <li><a href="#supportMultDomain"> 4) 多域名支持:</a></li>
+            <li><a href="#modle"> 5) 数据库使用示例:</a></li>
+            <li><a href="#view"> 6) View的支持</a></li>
+            <li><a href="#controller"> 7) Controller的使用</a></li>
+            <li><a href="#cache"> 8) Cache支持</a></li>
+        </ul>
+    </li>
+    <li><a href="#download">下载</a></li>
+</ul>
+<pre>
+<a id="createProject"> 1、创建项目</a>
+<code>
+    通过命令行进入当前目录,并执行:php -q _cli.php create=yes workspace=../project cache=tmp useDB=1
+    Command line usage:
+    >php -q _cli.php create=yes workspace=../project cache=tmp useDB=1
+    * create: is auto create default:yes;
+    * workspace: workspace
+    * cache : cache dir
+    * useDB : use db or not
+    程序将自动创建工作目录,并生成首页及配置相关文件。设置好Web网站目录,开启.htaccess即可直接访问。
+    相关的配置文件见 configure/app.ini及configure/db.ini文件
+</code>
+<a id="env">2、设置环境</a>
+<code>
+    1、安装服务器软件(详情google或百度)
+    2、设置服务器的Rewrite规则:
+    Apache:
+    RewriteEngine On
+    RewriteCond %{REQUEST_FILENAME} !-d
+    RewriteCond %{REQUEST_FILENAME} !-f
+    RewriteCond $1 !^(index.php|images|robots.txt)
+    RewriteRule (.*)$ index.php/$1 [L,QSA,PT]
+    RewriteRule ^(.*)\.phar$ - [F]
+    RewriteRule ^(.*)\.ini$ - [F]
+    Nginx:
+    if (!-f $request_filename){
+    rewrite (.*) /index.php;
+    }
+    location ~* /.(ini|phar){
+    deny all;
+    }
+</code>
+<a id="useFramework">3、框架的使用</a>
+<code>
+    <a id="useCommandLine"> 1) 命令行运行程序</a>
+    <code>
+        仅支持GET方法
+        1. normal模式
+        php -q index.php controller=index/action=home/id=100
+        php -q index.php controller=plugins/action=index/page=2
+
+        2. middle模式
+        php -q index.php controller/index/action/home/id/100
+        php -q index.php controller/plugins/action/index/page/2
+
+        3. short模式
+        php -q index.php index/home/100
+        php -q index.php plugins/page/2.html
+    </code>
+    <a id="autoload">2) 自动加载类</a>
+    <code>
+        new \controller\user(); === require("controller<?= DS ?>user.php"); new \controller\user();
+        new \model\user(); === require("model<?= DS ?>user.php"); new \model\user();
+        new \model\test\user(); === require("model<?= DS ?>test<?= DS ?>user.php"); new \model\test\user();
+    </code>
+    <a id="basicMethod">3) Qii 基本功能:</a>
+    <code>
+        Qii\Instance::Instance(className, param1, param2, param3[,...]); === ($class = new className(param1, param2,
+        param3[,...]));
+        Qii\Load::load(className)->method(); === $class->method();
+        Qii\Import::requires(fileName); 如果指定的文件无法找到则会在get_include_path()和站点配置文件的[path]的目录中去搜索,直到搜索到一个则停止。
+        Qii\Import::includes(fileName); == include(fileName);
+        Qii::setPrivate($key, $value);保存到私有变量 $_global[$key]中, $value可以为数组,如果是数组的话会将数组合并到已经存在$key的数组中去。
+        Qii::getPrivate($key, $index);获取$_global[$key][$index]的值
+        Qii::setError($condition, $code, $argv1, $argv2, ...);
+        检查$condition是否成立,成立就没有错,返回false,否则有错,返回true并将错误信息,详细代码错误$code详情见<?php echo Qii::getPrivate('qii_sys_language'); ?>
+        。
+    </code>
+    <a id="supportMultDomain"> 4) 多域名支持:</a>
+    <code>
+        开启多域名支持,不同域名可以访问不同目录中的controller,在app.ini中的common下添加以下内容,注意:hosts中的内容会覆盖网站中对应的配置
+        hosts[0.domain] = test.xxx.wang
+        hosts[0.ext] = test
+
+        hosts[1.domain] = admin.xxx.wang
+        hosts[1.ext] = admin
+    </code>
+    <a id="modle"> 5) 数据库使用示例:</a>
+    <code>
+        1、创建配置文件:configure/istudy.istudy_user.config.php,你可以设置好数据库配置文件或者在这里<a
+                href="<?= $this->_request->getFullUrl('main') . '?url=' . urlencode($this->_request->getFullUrl('database/creator')); ?>"><b>生成</b></a>配置文件并下载保存到本地目录。
+        <?php highlight_file('configure/istudy.istudy_user.config.php') ?>
+        namespace Model;
+        use \Qii\Model;
+
+        class user extends Model
+        {
+        public function __construct()
+        {
+        parent::__construct();
+        }
+
+        public function saveUserInfo()
+        {
+        $user = (new \Qii\Driver\Easy())->_initialize();
+        //设置数据表的主键,保存的时候会自动验证指定数据是否已经存在
+        $user->setPrivateKey(array('email'));
+        //设置规则
+        $user->setRules(new \Qii\Driver\Rules(\Qii\Import::includes('configure/istudy.istudy_user.config.php')));
+        $user->nickname = 'antsnet';
+        $user->sex = 1;
+        $user->email = 'antsnet4@163.com';
+        $user->password = 'A123456a';
+        $user->add_time = time();
+        $user->update_time = time();
+        $user->status = 0;
+        //此处返回response对象
+        $response = $user->_save();
+
+        if($response->isError())
+        {
+        return $response->getErrors();
+        }
+        return array('uid' => $response->getResult('_result'));
+        }
+
+        /**
+        * 获取用户信息
+        */
+        public function userInfo($email)
+        {
+        return $this->db->getRow('SELECT * FROM istudy_user WHERE email = "'.$this->db->setQuote($email).'"');
+        //或者
+        return $this->db->where(array('email' => $email))->selectOne('istudy_user');
+        //或者使用以下代码
+        $user = (new \Qii\Driver\Easy('istudy_user'))->_initialize();
+        //设置规则
+        $user->setRules(new \Qii\Driver\Rules(\Qii\Import::includes('configure/istudy.istudy_user.config.php')));
+        //操作的时候会根据规则自动验证对应字段是否符合指定规则,不符合就不做查询操作
+        $response = $user->_getRowByEmail('antsnet@163.com');
+        if($response->isError())
+        {
+        return array('users' => array(), 'error' => $user->getErrors());
+        }
+        return array('users' => $response->getResult('_result'));
+        }
+        /**
+        * 登录
+        */
+        public function login($email, $password)
+        {
+        $user = (new \Qii\Driver\Easy('istudy_user'))->_initialize();
+        //设置规则
+        $user->setRules(new \Qii\Driver\Rules(\Qii\Import::includes('configure/istudy.istudy_user.config.php')));
+        $user->setPrivateKey(array('email'));
+        $user->email = $email;
+        $response = $user->_exist();
+        if($response->isError())
+        {
+        return array('login' => false, 'error' => $response->getErrors());
+        }
+        $data = $response->getResult();
+        if($data['password'] != md5($password))
+        {
+        return array('login' => false, 'error' => 'invalid password');
+        }
+        return array('login' => true, 'res' => $data);
+        }
+
+        public function update($email, $password)
+        {
+        $user = (new \Qii\Driver\Easy('istudy_user'))->_initialize();
+        //设置规则
+        $user->setRules(new \Qii\Driver\Rules(\Qii\Import::includes('configure/istudy.istudy_user.config.php')));
+        $user->setPrivateKey(array('email'));
+        $user->email = $email;
+        $user->func('md5', 'password', $password);
+
+        $response = $user->_update();
+        if($response->isError())
+        {
+        return array('update' => false, 'msg' => $response->getErrors());
+        }
+        return array('update' => true);
+        }
+        public function remove($email)
+        {
+        $user = (new \Qii\Driver\Easy('istudy_user'))->_initialize();
+        //设置规则
+        $user->setRules(new \Qii\Driver\Rules(\Qii\Import::includes('configure/istudy.istudy_user.config.php')));
+        $user->setPrivateKey(array('email'));
+        $user->email = $email;
+
+        $response = $user->_remove();
+        if($response->isError())
+        {
+        return array('remove' => false, 'msg' => $response->getErrors());
+        }
+        return array('remove' => true);
+        }
+        }
+        使用方法:
+        namespace controller;
+        use \Qii\Controller_Abstract;
+        class test extends Controller_Abstract
+        {
+        //启用模板引擎支持
+        protected $enableView = true;
+        //启用数据库支持
+        protected $enableModel = true;
+        //修改默认模板引擎
+        protected $viewType = array('engine' => 'include');
+        public function __construct()
+        {
+        parent::__construct();
+        }
+
+        public function indexAction()
+        {
+        $this->_model->getRow('SELECT * FROM user WHERE email = "antsnet@163.com"');
+        print_r($this->_load->model('user')->saveUserInfo());
+        print_r($this->_load->model('user')->userInfo('antsnet@163.com'));
+        print_r($this->_load->model('user')->login('antsnet@163.com', 'A123456a'));
+        print_r($this->_load->model('user')->update('antsnet@163.com', 'A123456a'));
+        print_r($this->_load->model('user')->remove('antsnet@163.com'));
+        }
+        }
+    </code>
+    <a id="view"> 6) View的支持</a>
+    <code>
+        view支持smarty及php
+        use \Qii\Controller_Abstract;
+        class index extends Controller_Abstract
+        {
+        //启用view,在调用parent::__construct()时自动初始化view
+        protected $enableView = true;
+        //启用database在调用parent::__construct()时自动初始化database
+        protected $enableModel = true;
+        //修改默认模板引擎
+        protected $viewType = array('engine' => 'include');
+        public function __construct()
+        {
+        parent::__construct();//默认是app.ini中的view[engine],你可以在此处选择是用include或者require,只要将参数默认传给enableView即可
+        $this->_view->display('tpl'); //$this->view即为使用的模板引擎
+        }
+        }
+    </code>
+    <a id="controller"> 7) Controller的使用</a>
+    <code>
+        namespace controller;
+        use \Qii\Controller_Abstract;
+        class test extends Controller_Abstract
+        {
+        //为了避免Controller逻辑过于复杂,可以将Action拆到单独的文件
+        //当在调用dummy方法的时候会自动执行actions\dummy中的execute方法
+        public $actions = array(
+        "dummy" => "actions\dummy",
+        );
+        public function __construct()
+        {
+        parent::__construct();
+        }
+        public function indexAction()
+        {
+        //转发到\controller\test的indexAction方法上
+        $this->dispatch('test', 'index');
+        //执行结束后再转发
+        $this->forward('test', 'index');
+        }
+        //在执行parent::__construct()的时候会自动调用,如果return false即直接退出程序
+        protected function beforeRun()
+        {
+        return true;
+        }
+        /**
+        * 执行完dispatch后调用
+        */
+        protected function afterRun()
+        {
+        }
+        }
+    </code>
+    <a id="cache"> 8) Cache支持</a>
+    <code>
+        Controller中使用Cache
+        namespace controller;
+        use \Qii\Controller_Abstract;
+        class cache extends Controller_Abstract
+        {
+        public function __construct()
+        {
+        parent::__construct();
+        }
+        public function cacheTest()
+        {
+        $cache_id = 'cache_test';
+        //文件缓存
+        $this->setCache('file', array('path' => 'tmp'));
+        //Memcache缓存
+        $this->setCache('memcache', array('servers' => array( array('host'=>'127.0.0.1','port'=>11211) )
+        ,'life_time'=>600));
+        //xcache
+        $this->setCache('xcache', array('life_time'=>600));
+        //缓存内容
+        $this->_cache->set($cache_id, 'cache内容');
+        //redis缓存
+        $this->setCache('redis', array('servers' => array('127.0.0.1.6379')));
+        $this->_cache->set($cache_id, array('cache' => 'cache 内容'));
+        //获取缓存内容
+        $this->_cache->get($cache_id);
+        //移除缓存
+        $this->_cache->remove($cache_id);
+        }
+        }
+
+        Model中使用
+        namespace Model;
+        use \Qii\Model;
+        class cache extends Model
+        {
+        public function __construct()
+        {
+        parent::__construct();
+        }
+        public function cacheTest()
+        {
+        $cache_id = 'cache_test';
+        //文件缓存
+        $this->setCache('file', array('path' => 'tmp'));
+        //Memcache缓存
+        $this->setCache('memcache', array('servers' => array( array('host'=>'127.0.0.1','port'=>11211) )
+        ,'life_time'=>600));
+        //xcache
+        $this->setCache('xcache', array('life_time'=>600));
+        //缓存内容
+        $this->_cache->set($cache_id, 'cache内容');
+        //获取缓存内容
+        $this->_cache->get($cache_id);
+        //移除缓存
+        $this->cache->remove($cache_id);
+        }
+        }
+    </code>
+</code>
+<a id="download">下载</a>
+<code>
+    测试阶段暂时不提供下载
+
+</code>
+</pre>
+<?php include(Qii_DIR . '/view/footer.php'); ?>
+</body>
+</html>

+ 0 - 0
Qii/Exceptions/View/footer.php


+ 30 - 0
Qii/Exceptions/View/message.php

@@ -0,0 +1,30 @@
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta http-equiv="content-type" content="text/html;charset=utf-8">
+    <title><?php echo Qii::i('Show Message'); ?></title>
+    <?php
+    include(dirname(__FILE__) . DS . 'style.php');
+    ?>
+</head>
+<body>
+
+<h1><font color="red"><?php echo Qii::i('Show Message'); ?></font></h1>
+
+<p><?php echo Qii::i('The page you are looking at is being generated dynamically by Qii'); ?></p>
+
+<ul>Messages:
+    <?php
+    foreach ($message AS $error) {
+        ?>
+        <li><code><?= $error; ?></code></li>
+        <?php
+    }
+    ?>
+</ul>
+<?php
+include(dirname(__FILE__) . DS . 'footer.php');
+?>
+
+</body>
+</html>

+ 67 - 0
Qii/Exceptions/View/style.php

@@ -0,0 +1,67 @@
+<style type="text/css">
+
+    body {
+        background-color: #fff;
+        margin: 40px;
+        font-family: Lucida Grande, Verdana, Sans-serif;
+        font-size: 14px;
+        color: #4F5155;
+    }
+
+    a {
+        color: #003399;
+        background-color: transparent;
+        font-weight: normal;
+    }
+
+    h1 {
+        color: #444;
+        background-color: transparent;
+        border-bottom: 1px solid #D0D0D0;
+        font-size: 16px;
+        font-weight: bold;
+        margin: 24px 0 2px 0;
+        padding: 5px 0 6px 0;
+    }
+
+    code {
+        width: 98%;
+        font-family: Monaco, Verdana, Sans-serif;
+        word-wrap: break-word;
+        word-break: break-all;
+        font-size: 12px;
+        color: #002166;
+        display: block;
+        line-height: 20px;
+        padding: 10px 20px;
+        margin: 15px 0;
+        border: 1px solid rgba(0, 0, 0, 0.2);
+        border-radius: 5px;
+        background-color: #eee;
+        position: relative;
+    }
+
+    pre {
+        font-size: 14px;
+        white-space: pre-wrap; /* css3.0 */
+        white-space: -moz-pre-wrap; /* Firefox */
+        white-space: -pre-wrap; /* Opera 4-6 */
+        white-space: -o-pre-wrap; /* Opera 7 */
+        word-wrap: break-word; /* Internet Explorer 5.5+ */
+    }
+
+    ul {
+        list-style: lower-roman;
+        line-height: 18px;
+        padding: 0px 0px;
+        margin: 0px 0px;
+    }
+
+    ul ul {
+        padding-left: 20px;
+    }
+
+    li {
+        line-height: 25px;
+    }
+</style>

+ 6 - 0
Qii/Functions/Funcs.php

@@ -0,0 +1,6 @@
+<?php
+use \Qii\Application;
+function _i()
+{
+    return call_user_func_array('Application::i', func_get_args());
+}

+ 5 - 0
public/index.php

@@ -0,0 +1,5 @@
+<?php
+require_once('../Qii/Application.php');
+$app = \Qii\Application::getInstance();
+$app->setConfig('site', ['env' => 'product']);
+$app->run();