首先需要确定一下思路:我希望基于swoole的扩展开发的代码在run起来的时候,在接收到ws或是tcp等消息时,自动路由到某个类上,同时类可以实现加载类的依赖注入功能。目前市面上占据主流的一款框架Laravel,其中有一个依赖注入的功能非常的便捷。一般在通常的框架中拉取Class是这样做的:

class a {
public $bClassInstance;
public function __construct(Class b) {
$classInstance = new b();
}
public function doSth() {
return $this->bClassInstance->xxx();
}
} $b = new b();
$a = new a($b)
$a->doSth();

而在Laravel中则可以省略一些实例化的步骤, 直接通过类型约束的语法在方法的形参上指定某类的命名空间就自动实例化该类进来了。

class a {
public function doSth(b $b) {
return $b->xxx();
}
}

想要实现这一点,必须要了解php的反射机制。反射是一个比较冷门的类,他可以做到:使用namespace实例化一个类、调用类的方法等,利用这一点,可以构造一个自动装箱的类。

<?php
/***
* 依赖注入容器,若要执行依赖注入,请确保类包含构造函数!
*/
namespace App\Server; class Container
{
public $config;
public $reflection;
public function __construct($namespace)
{
try
{
$this->reflection = new \ReflectionClass($namespace);
}
catch (Exception $e)
{
echo $namespace;
}
}
public function builderController($fn, $server, $frame, $userMessage)
{
//从route中得到的control名称
$this->reflection->getMethod($fn)->invoke($this->autoBuilder(), $server, $frame, $userMessage);
} public function builderTask($fn, $server, $userMessage)
{
$this->reflection->getMethod($fn)->invoke($this->autoBuilder(), $server, $userMessage);
} public function autoBuilder()
{
#对构造函数赋值
return $this->batchInstantiation($this->getPrototypeController($this->reflection)#获得字串
);
} protected final function getPrototypeController(\ReflectionClass $object)
{
$prototype = false;
//批量从反射类中获取原型字串
foreach ($object->getConstructor()->getParameters() as $parameter)
{
$prototype[] = $parameter->getClass()->name;
} return $prototype ?: [];
} protected final function batchInstantiation(array $prototypeArr)
{
foreach ($prototypeArr as $item)
{
$container = new container($item);
$insArr[] = $container->autoBuilder();//进行递归注入
} return empty($prototypeArr) ? $this->reflection->newInstance() : $this->reflection->newInstanceArgs($insArr);
}
}

有了这个简易的装箱类后,可以着手实现类的路由功能,我们首先创建composer.json,键入如下内容。

{
"require": { },
"autoload": {
"psr-4": {
"App\\": "App/"
}
}
}

下一步,我们需要创建一个处理路由的类,这个类在常规的框架中,一般用来映射http请求到对应的类的函数上,而在swoole里,请求会来自长连接。那么在route类中则需要做相应的处理。

class Route
{
public $websocketServer;
public $model;
public $cache;
public function __construct() {
$this->websocketServer = new \swoole_websocket_server("0.0.0.0", "8002");
}
public function start_ws() {
// 这里设置一些swoole的参数 ...
// 最后执行启动swoole
$this->websocketServer->start();
} public function ws_onMessage(\swoole_websocket_server $server, $frame)
{
$userMessage = $this->filter_arr(json_decode($frame->data, true));
if (!$userMessage) {
return false;
} if (!$userMessage['type'] || !$userMessage['action']) {
return $this->call_shell("Type or action not found! ");
}
//使用依赖注入容器做伪路由
$App = new Container('\App\Controller\\'.$userMessage['type']);
return $App->builderController($userMessage['action'], $server, $frame,$userMessage);
} }

最后一步,创建一个入口文件,引导路由类的执行。

<?php
require "vendor/autoload.php"; use App\Server\Route; $App = new Route();
$App->start_ws();

在swoole中制作一款仿制laravel的框架的更多相关文章

  1. 使用 CSS & jQuery 制作一款漂亮的多彩时钟

    大家可能见过各种各样的时钟效果,比如多年前非常流行的 Flash 制作的各种新奇的动画时钟,现在的 Web 开发者们又开始应用 CSS3 和 Canvas 等最新技术来实现.而今天这里要分享的这款漂亮 ...

  2. 教你如何用PS制作多款按钮UI设计教程

    教你如何用PS制作多款按钮UI设计教程 本文教大家制作按钮的方法 LV. ★ 初入设计,学做按钮.只会套个底色,加个阴影,字体纯白,小聪明的弄个圆角. LV. ★★(描边.字体.内阴影) 看了很多案例 ...

  3. 用Html5结合Qt制作一款本地化EXE游戏-太空大战(Space War)

    本次来说一说如何利用lufylegend.js引擎制作一款html5游戏后将其通过Qt转换成EXE程序.步骤其实非常简单,接下来就一步步地做一下解释和说明. 首先我们来开发一个有点类似于太空大战的游戏 ...

  4. 如何制作一款HTML5 RPG游戏引擎——第五篇,人物&人物特效

    上一次,我们实现了对话类,今天就来做一个游戏中必不可少的——人物类. 当然,你完全是可以自己写一个人物类,但是为了方便起见,还是决定把人物类封装到这个引擎里. 为了使这个类更有意义,我还给人物类加了几 ...

  5. 如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话

    今天我们来实现情景对话.这是一个重要的功能,没有它,游戏将变得索然无味.所以我们不得不来完成它. 但是要知道,使用对话可不是一件简单的事,因为它内部的东西很多,比如说人物头像,人物名称,对话内容... ...

  6. 如何制作一款HTML5 RPG游戏引擎——第三篇,利用幕布切换场景

    开言: 在RPG游戏中,如果有地图切换的地方,通常就会使用幕布效果.所谓的幕布其实就是将两个矩形合拢,直到把屏幕遮住,然后再展开直到两个矩形全部移出屏幕. 为了大家做游戏方便,于是我给这个引擎加了这么 ...

  7. 如何制作一款HTML5 RPG游戏引擎——第二篇,烟雨+飞雪效果

    今天我们来实现烟雨+飞雪效果.首先来说,一款经典的RPG游戏难免需要加入天气的变化.那么为了使我们的RPG游戏引擎更完美,我们就只好慢慢地实现它. 本文为该系列文章的第二篇,如果想了解以前的文章可以看 ...

  8. cocos2d-x之道~制作第一款文字游戏(二)

    在 cocos2d-x之道~制作第一款文字游戏(一)中,使用cocos2d-x把主界面显示出来.分别有每一个级别提供的初始短语TileView,和目标短语TargetView.初步接触了cocos2d ...

  9. 在mysql数据库中制作千万级测试表

    在mysql数据库中制作千万级测试表 前言: 最近准备深入的学一下mysql,包括各种引擎的特性.性能优化.分表分库等.为了方便测试性能.分表等工作,就需要先建立一张比较大的数据表.我这里准备先建一张 ...

随机推荐

  1. UESTC - 1222 Sudoku(深搜)

    Yi Sima was one of the best counselors of Cao Cao. He likes to play a funny game himself. It looks l ...

  2. IDEA 安装常用操作二

    一.IDEA启动慢,因为启动时编译.缓存.创建索引等,如果断电等启动异常,可以让缓存索引失效 迁移IDEAD时,可以找到config.system等文件夹, 随着时间使用越久,空间占用越大,另外觉得浪 ...

  3. Object 循环引用 All In One

    Object 循环引用 All In One circular reference bug var a = {}; a.a = a; refs deep copy bug https://segmen ...

  4. TypeScript with React

    TypeScript with React # Make a new directory $ mkdir react-typescript # Change to this directory wit ...

  5. Node.js & BFF & FaaS

    Node.js & BFF & FaaS server https://github.com/PacktPublishing/Node.js-Web-Development-Fourt ...

  6. css dark theme & js theme checker

    css dark theme & js theme checker live demo https://codepen.io/xgqfrms/pen/GRprYLm <!DOCTYPE ...

  7. 【java】ObjectOutputStream & ObjectInputStream 多次写入发生重复写入相同数据的问题

    今日份代码,解决 ObjectOutputStream 多次写入发生重复写入相同数据的问题 核心区别如下: package com.sxd.swapping.objoutputstream; impo ...

  8. C++算法代码——级数求和[NOIP2002 普及组]

    题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1078 或者:https://www.luogu.com.cn/problem/P10 ...

  9. 为什么Linux需要虚拟内存

    本文转载自为什么 Linux 需要虚拟内存 导语 操作系统中的 CPU 和主内存(Main memory)都是稀缺资源,所有运行在当前操作系统的进程会共享系统中的 CPU 和内存资源,操作系统会使用 ...

  10. springboot项目启动后tomcat服务器自动关闭 解决方法

    需要在pom.xml中添加 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...