PHPackages                             bobby/api-framework - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. bobby/api-framework

ActiveProject[Framework](/categories/framework)

bobby/api-framework
===================

Powerful speed performance, concise, very loosely coupled modern API micro-framework, easy to expand and rapid business development.

1.1(7y ago)23MITPHPPHP &gt;=7.0

Since Feb 18Pushed 6y ago1 watchersCompare

[ Source](https://github.com/995933447/BobbysApiFrameWork)[ Packagist](https://packagist.org/packages/bobby/api-framework)[ RSS](/packages/bobby-api-framework/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (1)Dependencies (3)Versions (2)Used By (0)

php 微框架(带database版)
===================

[](#php-微框架带database版)

介绍
==

[](#介绍)

因开发公司的微服务网关（服务粘合层，暴露HTTP接口共前端调用），要求程序尽可能轻简快速。由于喜欢Laravel层次分明的设计模式和实用的功能，又喜欢Slim的轻量级和快速响应。于是参考Laravel的核心思想编写了一个类似Slim这样的微框架，自用于公司业务，代码也简单轻量容易根据应用场景做二次开发。框架极简但是响应速度快（初始化到启动完成1ms）。

框架功能:
=====

[](#框架功能)

- 1.利用反射机制自动解决依赖注入。
- 2.路由器
- 3.控制器
- 4.数据库DB组件
- 5.包装器(中间件)
- 6.事件监听系统
- 7.服务提供者
- 8.服务容器
- 9.代理
- 10.Config配置
- 11.Log日志
- 12.HTTP request组件
- 13.参数过滤器
- 14.Whoops友好异常提示

框架运行流程:
=======

[](#框架运行流程)

#### 请求-&gt;入口文件-&gt;框架引擎初始化环境(环境配置，异常处理注册，日志服务注册，服务提供者注册，代理服务注册，启动服务提供者)-&gt;解析http请求实例化Request类-&gt;服务容器注册绑定Request实例以供后续使用-&gt;路由寻址响应目标（如控制器方法）-&gt;前置路由包装器进行一系列前置处理动作（如过滤拦截，日志，事件监听等）-&gt;响应目标作出响应结果（包括业务逻辑，事件监听等）-&gt;后置路由包装器进行一系列后置处理动作（如日志记录，事件监听等）-&gt;完成

[](#请求-入口文件-框架引擎初始化环境环境配置异常处理注册日志服务注册服务提供者注册代理服务注册启动服务提供者-解析http请求实例化request类-服务容器注册绑定request实例以供后续使用-路由寻址响应目标如控制器方法-前置路由包装器进行一系列前置处理动作如过滤拦截日志事件监听等-响应目标作出响应结果包括业务逻辑事件监听等-后置路由包装器进行一系列后置处理动作如日志记录事件监听等-完成)

简单介绍使用:
=======

[](#简单介绍使用)

入口文件:
-----

[](#入口文件)

框架入口文件位于public/index.php，使用者可以自行修改入口文件位置。

框架初始化文件:
--------

[](#框架初始化文件)

框架初始化工作在文件bootstrap/app.php中完成，由入口文件public/index.php引入: bootstrap/app.php初始化工作:

```
//引入自动加载器
require '../vendor/autoload.php';

//实例框架核心引擎
$app = new \App\Core\Application;

//框架初始化
$app->boot();

return $app;
```

public/index.php请求入口:

```
//引入初始化脚本并获得框架核心引擎
$app = require '../bootstrap/app.php';

//获得当前请求封装类实例
$request = \Bobby\Component\Http\Request\InstanceFactory::make();

//根据请求路由寻址并进行一系列处理工作，响应结果
$app->responsePipeline($request);
```

路由:
---

[](#路由)

框架路由统一在app/route/route.php定义,示例:

```
//引入route组件代理类
use Bobby\Component\Proxy\Route;
use Bobby\Component\Proxy\Request;

//定义get方法请求路由,响应动作可以为闭包执行或控制器方法,此处是闭包*
Route::get('/', function(){
 	echo '
	do(9 ^ v ^)9 { Bobby :D\'s frame work started ; } while( 6 _ 6 )
	';
});

//定义任意方法请求路由,响应动作可以为闭包执行或控制器方法,此处是控制器,以下同理
Route::any('/example/{name}/{id}', 'ExampleController::iocExample')->wrappers(['example', 'before', 'after']);

//定义post方法请求路由
Route::post('/{member}/member', function($member, \StdClass $std) {*
	var_dump(Request::post(), Request::filter('post'), $member, $std);*
});

//路由组定义,路由组即同组的路由会享有共同的配置,路由组可嵌套
Route::group(['wrappers' => ['before', 'example']], function($route) {

	$route->group(['wrappers' => 'after'], function($route) {

		$route->get('/home', function(){

			//事件监听系统
			\Bobby\Component\Proxy\Event::fire(new \App\Event\Example("Event mode example "));

			echo 'This is home .';*
		});

	});
});
```

默认路由文件: 所有路由都定义在位于 app/Route/route.php 目录下的路由文件中，这些文件通过框架自动加载，相应逻辑位于 Bobby/Component/Provider/RouteProvider 类。路由定义文件可以在app/Config/app.php文件中修改route项修改。

有效的路由方法:

我们可以注册路由来响应任何 HTTP 请求动作：

- Route::get($uri, $callback);
- Route::post($uri, $callback);
- Route::put($uri, $callback);
- Route::delete($uri, $callback);
- Route::any($uri, $callback);

$callback可以是闭包或者控制器方法,控制器方法定义格式为 不带命名空间的控制器类名::方法名。控制器一般位于 \\App\\Controller\\ 命名空间或子空间下,按照psr4标准,即在app/Controller或者其子目录下。可以在app/Config/app.php文件中修改route项,包括路由定义文件以及路由缓存配置可在其中修改。

路由参数: 有时我们需要在路由中获取 URI 请求参数。例如，如果要从 URL 中获取用户ID，需要通过如下方式定义路由参数：

```
Route::get('user/{id}', function ($id) {
	return 'User ' . $id;
});
```

这样我们在浏览器中访问 [http://blog.test/user/1，就会得到以下输出：](http://blog.test/user/1%EF%BC%8C%E5%B0%B1%E4%BC%9A%E5%BE%97%E5%88%B0%E4%BB%A5%E4%B8%8B%E8%BE%93%E5%87%BA%EF%BC%9A)User 1

可以根据需要在路由中定义多个路由参数：

```
Route::get('posts/{post}/comments/{comment}', function ($post, $comment) {
	return $post . '-' . $comment;
});
```

根据上面的示例，路由参数需要通过花括号{}进行包裹，这些参数在路由被执行时会被传递到路由的闭包或控制器。路由参数可以由正则表达式限制特定规则,如{post:\[A-Za-z\]+}为$post不得为空且必须是字母,也可以自定义相应正则使其为可选参数。

路由分组: 路由分组的目的是让我们在多个路由中共享相同的路由属性，比如中间件和命名空间等，这样的话我们定义了大量的路由时就不必为每一个路由单独定义属性。共享属性以数组的形式作为第一个参数被传递给 Route::group 方法:

```
//路由组定义
Route::group(['wrappers' => ['before', 'example']], function($route) {
	//以下两个路由将经过同样的中间件:before和example中间件

	$route->get('/home', function(){
		echo 'This is home .';*
	});
	$route->post('/welcome', function(){
		echo 'Welcome .';*
	});

});
```

控制器:
----

[](#控制器)

*示例：*

```
namespace App\Controller;

use Bobby\Component\Proxy\Request; //Request组件的门面
use Bobby\Contract\Config\Config; //Config契约

/**
 * 控制器示例代码
 */
class ExampleController
{
	public function iocExample($name, $id, \StdClass $std, $default = 'ioc')
	{
	   	var_dump($name, $id, $std, $default, Request::get());
	}
}
```

控制器方法可自动注入路由参数,类,或者服务容器绑定的契约实现和代理,如参数没有在路由uri中定义还可以使用默认值。

数据库
---

[](#数据库)

数据库由Bobby/Component/Database组件完成。可直接使用代理类Bobby\\Component\\Proxy\\DB操作,示例: 数据库配置: 应用的数据库配置位于 app/config/database.php。在该文件中你可以定义所有的数据库连接，并指定哪个连接是默认连接。该文件中提供了所有支持数据库系统的配置示例。 return \[

```
'default' => 'mysql', //默认使用的数据库连接

//数据库连接列表
'connections' => [

    'mysql' => [

        'driver' => 'mysql',        //数据库驱动
        'host' => '127.0.0.1:3306', //连接主机
        'user' => 'root',           //用户名
        'password' => '',           //密码
        'database' => 'test',       //数据库
        'charset' => 'utf8mb4',     //字符集
        'prefix' => '',             //表前缀
        'timeout' => 1,             //连接超时时间，false表示无限制
        'error_mode' => 2,          //0 静默模式,默认的出错了不管;1 警告模式,如果出错了就会报出警告;2 异常模式,如果出错会采用异常来处理（PDOException）
        'pconnect' => true,         //是否开启长连接
    ]

]

```

\]; 有时候你希望使用专门数据库连接做查询，有专门数据库连接做插入、更新和删除。

想要知道如何配置读/写连接，可以参考下面这个例子：

```
return [

    'default' => 'mysql', //默认使用的数据库连接

    //数据库连接列表
    'connections' => [

        'mysql' => [

            'driver' => 'mysql',        //数据库驱动
            'user' => 'root',           //用户名
            'password' => '',           //密码
            'database' => 'test',       //数据库
            'charset' => 'utf8mb4',     //字符集
            'prefix' => '',             //表前缀
            'timeout' => 1,             //连接超时时间，false表示无限制
            'error_mode' => 2,          //0 静默模式,默认的出错了不管;1 警告模式,如果出错了就会报出警告;2 异常模式,如果出错会采用异常来处理（PDOException）
            'pconnect' => true,         //是否开启长连接

            //读写分离配置
             'read' => [

                [
                    'host' => '127.0.0.2:3306',
                ],
                [
                     'host' => '127.0.0.3:3306',
                     'user' => 'admin',
                     'password' => '123456'
                ]

             ],

             'write' => [
		[
		     'host' => '127.0.0.2:3306',
		],
             ]

        ]

    ]

];
```

注意我们在配置数组中新增了2个键：read、write，read 和 write 这两个键对应值都有一个包含单个键“host”的数组，而其所映射的 IP 值分别就是读连接和写连接，读/写连接的其它数据库配置项都共用主数组配置。如果我们想要覆盖主数组中的配置，只需要将相应配置项放到 read 和 write 数组中即可。在读写数据时会从提供的 IP 中随机选一个进行连接。

数据库操作使用代理Bobby\\Component\\Proxy\\DB:

```
use Bobby\Component\Proxy\DB;
```

使用不同数据库连接： 使用多个数据库连接的时候，可以通过 DB 代理上的 connectRead或connectWrite 方法访问不同连接： $users = DB::connectRead()-&gt;select(...); 甚至还可以用make方法指定数据库配置： $users = DB::make('mysql2')-&gt;connectRead()-&gt;select(...);

运行原生 SQL 查询 配置好数据库连接后，就可以使用 DB 门面来运行查询。DB 门面为每种操作提供了相应方法：select, update, insert, delete。

```
$users = DB::query('select * from users where active = ?', [1]);
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Bobby']);
$affected = DB::update('update users set votes = 100 where name = ?', ['Bobby']);
$deleted = DB::delete('delete from users where id = ?', [1]);
```

开启事务:

```
$connector = DB::connectWrite();
DB::query('begin', [], $connector);
#do something
DB::query('commit', [], $connector);
```

查询构建器:数据库查询构建器提供了一个方便的流接口用于创建和执行数据库查询。查询构建器可以用于执行应用中绝大部分数据库操作。

指定一张表:

```
$user = DB::table('user');
```

从一张表中取出所有行

```
DB::table('users')->select();
```

从一张表中取出一行

```
DB::table('users')->find();
```

聚合函数 查询构建器还提供了多个聚合方法，如count, max, min, average 和 sum，你可以在构造查询之后调用这些方法：

```
$users = DB::table('users')->count();

$price = DB::table('orders')->max('price');
```

```
当然，你可以联合其它查询子句和聚合函数来构建查询：

$price = DB::table('orders')
                ->where('finalized', 1)
                ->average('price');
```

当然，我们并不总是想要获取数据表的所有列，使用 column 方法，你可以为查询指定自定义的 column 子句：

```
$users = DB::table('users')->column(['name', 'email as user_email'])->select();
```

你可以通过原生sql指定column：

```
$users = DB::table('users')->columnRaw('name, email as user_email')->select();
```

可以用子查询作为column：

```
$users = DB::table('users')->columnSub(function($query) {
  $query->table('config')->find();
})->select();
//或者
$query = DB::table('config')->find();
DB::table('users')->columnSub($query)->select();
```

distinct 方法允许你强制查询返回不重复的结果集：

```
$users = DB::table('users')->distinct()->select();
```

Where 子句 简单 Where 子句 使用查询构建器上的 where 方法可以添加 where 子句到查询中，调用where 最基本的方式需要传递3个参数，第一个参数是列名，第二个参数是任意一个数据库系统支持的操作符，第三个参数是该列要比较的值,你可以传递第四个参数指定连接类型。

例如，下面是一个验证“votes”列的值是否等于 100 的查询：

```
$users = DB::table('users')->where('votes', '=', 100)->select();
```

为了方便，如果你只是简单比较列值和给定数值是否相等，可以将数值直接作为where 方法的第二个参数：

```
$users = DB::table('users')->where('votes', 100)->select();
```

当然，你还可以使用其它操作符来编写 where 子句：

```
$users = DB::table('users')
            ->where('votes', '>=', 100)
            ->select();

$users = DB::table('users')
            ->where('votes', '', 100)
            ->find();

$user = DB::table('users')
	    ->where('name', '=', 'john')
	    ->find();

$user = DB::table('users')
	    ->where('name', 'john')
	    ->find();

$users = DB::table('users')
            ->where('name', 'like', 'T%')
	    ->where('status', 1)
            ->select();

//复杂where条件
$user = DB::table('users')
	    ->where(function($query) {
	       $query->where(id, 2)->where('name', 'born');
	    })
	    ->find();

//子查询作为where条件
$users = DB::table('users')
	     ->where('name', 'in', function($query) {
	     	$query->table('orders')->where('goods', 'apple')->column('name');
	     })
	     ->select();
//或者
$query = DB::table('orders')->where('goods', 'apple')->column('name');
$users = DB::table('users')->where('name', 'in', $query)->select();
```

还可以传递条件数组到 where 方法：

```
$users = DB::table('users')->where([
    ['status', '=', '1'],
    ['name', 'john'],
    ['subscribed', '', '1', 'or'],
])->select();
```

or 语句 你可以通过方法链将多个 where 约束链接到一起，也可以添加 or where子句到查询：

```
$users = DB::table('users')
             ->where('votes', '>', 100)
             ->where('name', '=' ,'John', 'or')
             ->select();
```

in 语句:

```
$users = DB::table('users')
             ->where('name', 'in', ['John', 'or'])
             ->select();
```

原生where:

```
$users = DB::table('users')
             ->whereRaw('name in (?, ?)', ['John', 'or'])
             ->select();
```

join查询:

```
$users = DB::table('users')
            ->join('contacts', 'users.id', '=', 'contacts.user_id', 'LEFT')
            ->join('orders', 'users.id', '=', 'orders.user_id')
            ->column('users.*', 'contacts.phone', 'orders.price')
            ->find();

//join添加and条件子句
$users = DB::table('users')
            ->join('contacts', function($query) {
		$query->on('orders', 'users.id', '=', 'orders.user_id')
		->and('users.id', '=', 2);
            }, null, null, 'LEFT')
            ->select();
```

group by分组：

```
$users = DB::table('users')->groupBy(['sex', 'tall'])->having('age', '=', '18')->select();
```

having筛选：

```
$users = DB::table('users')->groupBy(['sex', 'tall'])->having('age', '=', '18')->select();
//或者
$users = DB::table('users')->groupBy(['sex', 'tall'])->having('age', '18')->select();

//可以通过原生sql进行having筛选
$users = DB::table('users')->groupBy(['sex', 'tall'])->havingRaw('age = ?', [18])->select();
```

order by排序

```
DB::table('users')->select()->orderBy('id', 'ASC')->orderBy('score', 'DESC')->select();

//你也可以通过原生sql指定排序方式:
DB::table('users')->select()->orderByRaw('id ASC, score, DESC')->select();
```

offset和limit查询:

```
DB::table('users')->offset(5)->limit(10)->select();
```

union查询:

```
$query = DB::table('users')->where('id', 10)->find();
DB::table('users')->union($query)->find();

//union all查询
$query = DB::table('users')->where('id', '
