09/09
                                    2017
                                
                            
                        dev-master
9999999-dev简单的PHP初学者框架
MIT
The Requires
by aiden knight
 Wallogit.com
                    
                    2017 © Pedro Peláez
                         Wallogit.com
                    
                    2017 © Pedro Peláez
                    
                    
                    
                    
                
                
            
简单的PHP初学者框架
项目提交composer的packagist
项目提交至github
github注册账号
 
创建一个项目
, (*1)
安装composer, (*2)
composer init 初始化项目composer init初始化之后会自动声场vendor目录以及composer.json文件
|--app 应用目录 | |--home home模块 | | |--controller 控制器 | | |--view 视图 |--houdunwang 框架核心 | |--core 核心文件 | |--model 模型 | |--view 视图 |--public | |--static 静态资源 | |--view 视图(成功提示模板) |--system | |--config 配置文件 | |--model 模型
类名和文件名首字母大写
<?php
//命名空间
namespace houdunwang\core;
class Boot
{
    public static function run ()
        {
        echo 'run';
    }
}
<?php
namespace houdunwang\core;
class Boot
{
    public static function run ()
    {
        //错误处理
        self::handler();
        //初始化框架
        self::init();
        //执行应用
        self::appRun ();
    }
    public static function handler(){
        $whoops = new \Whoops\Run;
        $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
        $whoops->register();
    }
    public static function init()
    {
        session_id () || session_start ();
        date_default_timezone_set ('PRC');
    }
    public static function appRun ()
    {
        if ( isset( $_GET[ 's' ] ) ) {
            $info = explode ('/',$_GET['s']);
            $info[1] = ucfirst ($info[1]);
            $class = "\app\\{$info[0]}\controller\\{$info[1]}";
            $action = $info[2];
            define ('MODULE',strtolower ($info[0]));
            define ('CONTROLLER',lcfirst ($info[1]));
            define ('ACTION',$info[2]);
        } else {
            $class = "\app\home\controller\Entry";
            $action = "index";
            define ('MODULE','home');
            define ('CONTROLLER','entry');
            define ('ACTION',$action);
        }
        echo call_user_func_array ( [ new $class , $action ] , [] );
        exit;
    }
}
###4.在public目录中创建index.php单一入口文件
<?php
require_once '../vendor/autoload.php';
\houdunwang\core\Boot::run ();
###5.访问框架入口:http://localhost:8080/frame/public/
这个时候报错:
Fatal error: Class 'houdunwang\core\Boot' not found in /Applications/MAMP/htdocs/frame/public/index.php on line 3
因为类加载使用时需满足:include加载文件和导入命名空间<br>
继续往下解决这个问题
###6.配置composer配置文件
修改composer.json文件。注意`autoload`该项需自己增加
{
    "name": "chaorenwubin/frame",
    "description": "后盾网c86php框架系统",
    "type": "project",
    "licence":"MIT",
    "authors": [
        {
            "name": "武斌",
            "email": "wubin.mail@foxmail.com"
        }
    ],
    "minimum-stability": "dev",
    "require": {},
    "autoload":{
        "files":[],
        "psr-4":{
           "houdunwang\\":"houdunwang\\",
           "app\\":"app\\"
        }
    }
}
PSR-4
1.是制定的代码规范,简称PSR,是代码开发的事实标准
2.PSR-4使代码更加规范,能够满足面向package的自动加载,它规范了如何从文件路径自动加载类,同时规范了自动加载文件的位置
3.如果是: "houdunwang\\":"houdunwang\\",当实例化\houdunwang\core\Boot类时,会加载houdunwang/core/Boot.php
4.如果是: "houdunwang\\":"hdphp\\",当实例化\houdunwang\core\Boot类时,hdphp/core/Boot.php
5.如果是: "houdunwang\\":"",当实例化\houdunwang\core\Boot类时,Boot.php
5.反斜线是转义
生成composer自动载入文件,在Terminal中进入项目跟目录执行:
composer dump
这时,访问项目入口public文件输出`run`
###7.Boot.php中书写appRun方法:
引入助手函数
1.将以前我们写的helper.php文件放入system/helper.php
2.修改composer.json文件中autoload项的files
"autoload":{
        "files":[
            "system/helper.php"
        ],
        "psr-4":{
           "houdunwang\\":"houdunwang\\",
           "app\\":"app\\"
        }
}
3.在Teminal终端执行composer dump
appRun方法具体代码
public static function appRun ()
    {
        if(isset($_GET['s'])){
            //通过?s=模块/控制器/方法(?s=home/entry/index)进行访问
            //接受get参数s,并将其转为数组
            $info = explode ('/',$_GET['s']);
            //dd($info);
            $info[1] = ucfirst ($info[1]);
            //dd($info);
            $c = "app\\{$info[0]}\controller\\{$info[1]}";
            $a  = $info[2];
            define ('MODULE',strtolower ($info[0]));
            define ('CONTROLLER',strtolower ($c));
            define ('ACTION',$a);
        }else{
            $c = "\app\home\controller\\entry";//控制器类
            $a = 'index';//方法
            define ('MODULE','home');
            define ('CONTROLLER','entry');
            define ('ACTION',$a);
        }
        return call_user_func_array ([new $c,$a],[]);
    }
###8.测试访问app中我们构建的程序
在app/home/controller中创建Entry.php
<?php
namespace app\home\controller;
class Entry
{
    public function index(){
        echo 'Welcome';
    }
}
通过地址栏访问`public`或`public/index.php`或`public/index.php?s=home/entry/index`<br>
也可通过尝试其他地址访问,如:`public/index.php?s=home/entry/store`<br>
浏览器正常输出`Welcome`
###9.构建控制器层 C
public/view放入message.php模板文件<br>
自己参考代码
在 core 目录中创建Controller.php,并让app\home\controller\Entry.php及以后类继承Controller
<?php
namespace houdunwang\core;
class Controller
{
    private $url;
    protected function message($msg){
        include './view/message.php';
        exit;
    }
    protected function setRedirect($url = ''){
        if($url){
            $this->url = "location.href='$url'";
        }else{
            $this->url = "window.history.back()";
        }
        return $this
    }
}
app/controller/Entry.php,中增加store方法进行测试,增加store方法进行测试<br>
通过地址栏访问store方法:`public/index.php?s=home/entry/store`<br>
可看到提示页面,3秒之后自动跳转
<?php
namespace app\home\controller;
use houdunwang\core\Controller;
class Entry extends Controller
{
    public function index(){
        echo 'Welcome';
    }
    public function store(){
        $this->setRedirect ('?s=home/entry/index')->message ('添加成功');
    }
}
###10.构建视图层 V
在core/view目录中建立View.php和Base.php<br>
View.php
<?php
namespace houdunwang\view;
class View
{
    public function __call ( $name , $arguments )
    {
        // TODO: Implement __call() method.
        return self::parseAction ( $name , $arguments );
    }
    public static function __callStatic ( $name , $arguments )
    {
        // TODO: Implement __callStatic() method.
        return self::parseAction ( $name , $arguments );
    }
    public static function parseAction ( $name , $arguments )
    {
        return call_user_func_array ( [ new Base , $name ] , $arguments );
    }
}
Base.php
<?php
namespace houdunwang\view;
class Base
{
    private $file;
    private $data;
    public function make ()
    {
        $this->file = "../app/" . MODULE . '/view/' . CONTROLLER . '/' . ACTION . '.php';
        return $this;         
    }
    public function with ( $var )
    {
        $this->data = $var;
        return $this;
    }
    //当输出对象的时候出发,比如说echo $obj->make();
    public function __toString ()
    {
        // TODO: Implement __toString() method.
        extract ($this->data);
        include $this->file;
        return '';
    }
}
###11构建模型层和数据库ORM数据对象关系映射
数据库配置项文件`system/config/database.php`
<?php
return [
    'driver'=>'mysql',
    'host'     => '127.0.0.1',
    'user'     => 'root',
    'password' => 'root',
    'dbname'     => 'c86',
];
system/helper.php助手函数中增加加载配置项的c函数
function c ( $path )
    {
        $info   = explode ( '.' , $path );
        $config = include "../system/config/" . $info[ 0 ] . '.php';
        return isset( $config[ $info[ 1 ] ] ) ? $config[ $info[ 1 ] ] : null;
    }
`houdunwang/model/Model.php`
<?php
namespace houdunwang\model;
class Model
{
    /**
     * @param $name
     * @param $arguments
     */
    public function __call ( $name , $arguments )
    {
        // TODO: Implement __call() method.
        return self::parseAction ( $name , $arguments );
    }
    /**
     * @param $name
     * @param $arguments
     */
    public static function __callStatic ( $name , $arguments )
    {
        // TODO: Implement __callStatic() method.
        return self::parseAction ( $name , $arguments );
    }
    /**
     * @param $name
     * @param $arguments
     *
     * @return mixed
     */
    public static function parseAction ( $name , $arguments )
    {
        $class = get_called_class ();
        return call_user_func_array ( [ new Base($class) , $name ] , $arguments );
    }
}
base.php
<?php
namespace houdunwang\model;
use PDO;
use PDOException;
use Exception;
/**
 * 模型基础类
 * Class Base
 *
 * @package houdunwang\model
 */
class Base
{
    protected $table;
    protected $pdo;
    private   $where = '';
    private   $field = '';
    public function __construct ( $class )
    {
        //1.链接数据库
        $this->connect ();
        //$class打印结果:system\model\Article
        $class       = explode ( '\\' , $class );
        $this->table = strtolower ( $class[ 2 ] );
    }
    private function connect ()
    {
        $dsn      = c ( 'database.driver' ) . ":host=" . c ( 'database.host' ) . ";dbname=" . c ( 'database.dbname' );
        $user     = c ( 'database.user' );
        $password = c ( 'database.password' );
        try {
            $this->pdo = new PDO( $dsn , $user , $password );//链接数据库
            $this->pdo->query ( 'SET NAMES UTF8' );//设置字符集
            //设置错误属性
            $this->pdo->setAttribute ( PDO::ATTR_ERRMODE , PDO::ERRMODE_EXCEPTION );
        } catch ( PDOException $e ) {
            //输出错误
            exit( $e->getMessage () );
        }
    }
    /**
     * 获取单一数据
     *
     * @param $pk    主键值
     */
    public function find ( $pk )
    {
        //获得主键
        $priKey = $this->getPk ();
        //组合where条件,调用where方法
        $this->where ( "{$priKey}={$pk}" );
        //组合sql语句
        $field = empty( $this->field ) ? '*' : $this->field;
        $sql   = "select {$field} from {$this->table} {$this->where}";
        //执行查询
        $data = $this->query ( $sql );
        if ( $data ) {
            //存储到data属性,使用toarray方法获得数据
            $this->data = current ( $data );
            return $this;
        }
        return [];
    }
    /**
     * 获取全部数据
     *
     * @return $this|array
     */
    public function get ()
    {
        $field = empty( $this->field ) ? '*' : $this->field;
        $sql   = "select {$field} from {$this->table}";
        $data  = $this->query ( $sql );
        if ( $data ) {
            $this->data = $data;
            return $this;
        }
        return [];
    }
    /**
     * 删除操作
     *
     * @return bool
     */
    public function destory ()
    {
        //没有where条件不能执行删除
        if ( empty( $this->where ) )
            return false;
        $sql = "delete from {$this->table} {$this->where}";
        return $this->exec ( $sql );
    }
    /**
     * 更新数据
     *
     * @param $data
     *
     * @return bool
     */
    public function update ( array $data )
    {
        //更新的时候没有where条件不允许更新
        if ( empty( $this->where ) )
            return false;
        $fields = '';
        foreach ( $data as $k => $v ) {
            $fields .= "{$k}='{$v}',";
        }
        //将最后,去掉
        $fields = rtrim ( $fields , ',' );
        $sql    = "update {$this->table} set {$fields} {$this->where}";
        //执行sql语句
        return $this->exec ( $sql );
    }
    /**
     * 数据写入
     *
     * @param array $data
     *
     * @return mixed    返回自增id
     */
    public function insert ( array $data )
    {
        $fields = '';
        $values = '';
        foreach ( $data as $field => $value ) {
            $fields .= "$field,";
            $values .= is_int ( $value ) ? "$value," : "'$value',";
        }
        //将最后侧的,去掉
        $fields = rtrim ( $fields , ',' );
        $values = rtrim ( $values , ',' );
        //insert into article (atitle,time) values ('hello',180);
        $sql = "insert into {$this->table} ($fields) values ($values)";
        return $this->exec ( $sql );
    }
    /**
     * 查询数据获取制定字段
     *
     * @param $data
     *
     * @return $this
     */
    public function field ( $data )
    {
        $this->field = $data;
        return $this;
    }
    /**
     * 统计
     * @return mixed
     */
    public function count ()
    {
        $sql  = "select count(*) as total from {$this->table} {$this->where}";
        $data = $this->query ( $sql );
        return $data[ 0 ][ 'total' ];
    }
    /**
     * 将对象转为数组
     *
     * @return array
     */
    public function toArray ()
    {
        if ( isset( $this->data ) ) {
            return $this->data;
        }
        return [];
    }
    /**
     * 组合where条件
     *
     * @param $where  条件语句
     *
     * @return $this
     */
    public function where ( $where )
    {
        //将wher条件存储到where属性中
        $this->where = " where $where";
        return $this;
    }
    /**
     * 获得主键
     */
    private function getPk ()
    {
        $sql  = "desc " . $this->table;// desc article
        $data = $this->query ( $sql );//执行sql语句,调用自定义的query方法
        $pk   = '';
        foreach ( $data as $d ) {
            if ( $d[ 'Key' ] == 'PRI' ) {
                //说明该数据中的Field是主键
                $pk = $d[ 'Field' ];
                break;//终止循环
            }
        }
        return $pk;
    }
    /**
     * 执行有结果集的查询
     *
     * @param $sql  查询的sql语句
     *
     * @return mixed  查询结果结
     */
    public function query ( $sql )
    {
        try {
            $res = $this->pdo->query ( $sql );
            return $res->fetchAll ( PDO::FETCH_ASSOC );
        } catch ( PDOException $e ) {
            throw new Exception( "sql:{$sql} | " . $e->getMessage () );
        }
    }
    public function exec ( $sql )
    {
        try {
            $affectedRows = $this->pdo->exec ( $sql );
            if ( $lastInsertId = $this->pdo->lastInsertId () ) {
                //返回自增id
                return $lastInsertId;
            } else {//否则返回受影响的条数
                return $affectedRows;
            }
        } catch ( PDOException $e ) {
            throw new Exception( "sql:{$sql} | " . $e->getMessage () );
        }
    }
}
需要在system/model建立Article.php进行协助测试测试,Article.php名字不是固定的
<?php
namespace system\model;
use houdunwang\model\Model;
class Article extends Model
{
}
在Entry.php中进行测试,注意system中的类不会自动进行加载,需要修改composer.json配置项
"autoload":{
        "files":[
            "system/helper.php"
        ],
        "psr-4":{
            "houdunwang\\":"houdunwang",
            "app\\":"app\\",
            "system\\":"system\\"
        }
    }
然后执行
composer dump
###错误处理方法
composer的packagist(https://packagist.org/)搜索:`whoop`<br>
选择第一个:filp/whoops<br>
进入到项目根目录执行:
composer require filp/whoops
在houdunwang/core/Boot.php中加入
    $whoops = new \Whoops\Run;
   $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
   $whoops->register();
推送上到composer仓库之后即可以下载了
composer create-project chaorenwubin/frame c86frame dev-master --prefer-dist
        简单的PHP初学者框架
MIT