Laravel框架学习笔记

001需求和安装 需求 PHP >= 7.3 BCMath PHP 拓展 Ctype PHP 拓展 Fileinfo PHP 拓展 JSON PHP 拓展 Mbstring PHP 拓展 OpenSSL PHP 拓展 PDO PHP 拓展 Tokenizer PHP 拓展 XML PHP 拓展 安装 composer create-project --prefer-dist laravel/laravel blog 运行 php artisan serve 注: 需要给storage文件夹写权限 002文件夹结构的详细 根目录 app 目录 bootstrap 目录 config 目录 database 目录 public 目录 resources 目录 routes 目录 storage 目录 tests 目录 vendor 目录 APP目录 Broadcasting 目录 Console 目录 用于控制台注册 Events 目录 Exceptions 目录 注册处理异常方法 Http 目录 Jobs 目录 Listeners 目录 Mail 目录 Models 目录 Notifications 目录 Policies 目录 Providers 目录 Rules 目录 M:app/Models V:resource/views C:app/Controllers ...

2018-07-30 · 9 分钟 · 1798 字 · 王站站

workerman学习笔记

序言 Workerman, 高性能socket框架. Workerman是一款纯PHP开发的开源高性能的PHP socket 服务框架。 Workerman每个进程能维持上万并发连接。 同时支持TCP、UDP、UNIXSOCKET,支持长连接,支持Websocket、HTTP、WSS、HTTPS等通讯协议以及各种自定义协议。拥有定时器、异步socket客户端、异步Mysql、异步Redis、异步Http、异步消息队列等众多高性能组件。 应用方向 1、即时通讯类 2、物联网类 3、游戏服务器类 4、HTTP服务 5、SOA服务化 6、其它服务器软件 7、中间件 原理 Worker是WorkerMan中最基本容器, 采用Epoll(需要装event扩展)+非阻塞IO,每个Worker进程都能上万的客户端连接,并处理这些连接上发来的数据。 主进程与worker子进程关系[https://wenda.workerman.net/uploads/answer/20140815/5670ea17653a1a6e6811ed5148f77c96.png] 开发必读 1、windows环境限制 2、workerman不依赖apache或者nginx 3、workerman是命令行启动的 4、长连接必须加心跳 5、客户端和服务端协议一定要对应才能通讯 6、连接失败可能的原因 7、不要使用exit die sleep语句 8、不要使用pcntl_fork函数 9、业务代码里不要有死循环 10、改代码要重启 11、长连接应用建议用GatewayWorker框架 12、支持更高并发 入门指引 特性 1、纯PHP开发 2、支持PHP多进程 3、支持TCP、UDP 4、支持长连接 5、支持各种应用层协议 6、支持高并发 7、支持服务平滑重启 8、支持文件更新检测及自动加载 9、支持以指定用户运行子进程 10、支持对象或者资源永久保持 11、高性能 12、支持HHVM 13、支持分布式部署 14、支持守护进程化 15、支持多端口监听 16、支持标准输入输出重定向 简单的开发示例 创建http_test.php文件 <?php use Workerman\Worker; require_once __DIR__ . '/Workerman/Autoloader.php'; // 创建一个Worker监听2345端口,使用http协议通讯 $http_worker = new Worker("http://0.0.0.0:2345"); // 启动4个进程对外提供服务 $http_worker->count = 4; // 接收到浏览器发送的数据时回复hello world给浏览器 $http_worker->onMessage = function($connection, $data) { // 向浏览器发送hello world $connection->send('hello world'); }; // 运行worker Worker::runAll(); php http_test.php start … ...

2018-05-28 · 3 分钟 · 435 字 · 王站站

phalapi框架学习笔记

1 快速开发 1.1 安装 composer一键安装 composer create-project phalapi/phalapi 手动下载安装 下载 phalapi 项目master-2x分支 composer update Nginx配置 ...... location / { index index.php; } # 开启URI路由匹配 # location / { # try_files $uri $uri/ /?$args; # } # if (!-e $request_filename) { # rewrite ^/(.*)$ /index.php last; # } ...... nginx -t nginx -s reload 1.2 运行Hello world 点击此处 1.3 如何请求接口服务 开启url匹配 扩展:如何定制接口服务的传递方式? 1.4 接口响应与在线调试 跨域 在./config/di.php后面的位置添加 // 允许跨域 $response = \PhalApi\DI()->response; $response->addHeaders('Access-Control-Allow-Origin', '*'); // *代表允许任何网址请求 // $response->addHeaders('Access-Control-Allow-Origin', 'www.phalapi.net'); // 推荐指定网站 $response->addHeaders('Access-Control-Allow-Methods', 'POST,GET,OPTIONS,DELETE'); // 允许请求的类型 $response->addHeaders('Access-Control-Allow-Credentials', 'true'); // 设置是否允许发送 cookies $response->addHeaders('Access-Control-Allow-Headers', 'Content-Type,Content-Length,Accept-Encoding,X-Requested-with, Origin'); // 设置允许自定义请求头的字段 在线调试 单次请求开启调试:默认添加请求参数&__debug__=1 全部请求开启调试:把配置文件./config/sys.php文件中的配置改成'debug' => true, 自定义埋点 // 添加纪录埋点,并指定节点标识 PhalApi\DI()->tracer->mark('DO_SOMETHING'); 自定义调试信息 $x = 'this is x'; $y = array('this is y'); \PhalApi\DI()->response->setDebug('XXX_x', $x); // XXX扩展 \PhalApi\DI()->response->setDebug('XXX_y', $y); 1.5 Api接口层 异常抛出 use App\Common\AppException; ...... throw new AppException('提示消息', 1000); ...... 手动指定ret状态码 // 手动设置ret为1000 // ret=200时表示正常返回,ret=4xx表示额端非法请求,ret=500表示服务器内部错误,手动设置时应设置成其他整数范围,避免语义冲突 \PhalApi\DI()->response->setRet(1000); // 手动设置提示消息 \PhalApi\DI()->response->setMsg('手动设置提示消息'); 钩子函数 PhalApi\Api::getRules(),获取参数设置的规则,可由开发人员根据需要重载 PhalApi\Api::userCheck(),用户身份验证,可由开发人员根据需要重载,此通用操作一般可以使用委托或者放置在应用接口基类 1.6 DataApi通用数据接口 DataApi有哪些接口? PhalApi\Api\DataApi目前有5个数据接口(后面会进一步扩展): ...

2018-05-07 · 6 分钟 · 1140 字 · 王站站

gorm中文文档

入门指南 概述 全功能 ORM 关联 (Has One、Has Many、Belongs To、Many To Many、多态、单表继承) Create、Save、Update、Delete、Find 前/后的勾子 基于Preload、Joins的预加载 事务、嵌套事务、保存点、回滚至保存点 Context、Prepared Statment 模式、DryRun 模式 批量插入、FindInBatches、查询至 Map SQL Builder, Upsert, Locking, Optimizer/Index/Comment Hints 复合主键 自动迁移 自定义 Logger 灵活的可扩展插件 API:Database Resolver(读写分离)、Prometheus… 所有特性都通过了测试 开发者友好 快速入门 package main import ( "gorm.io/gorm" "gorm.io/driver/sqlite" ) type Product struct { gorm.Model Code string Price uint } func main() { db, err := gorm.Open(sqlite.Open("test.db"), &amp;gorm.Config{}) if err != nil { panic("failed to connect database") } // 迁移 schema db.AutoMigrate(&amp;Product{}) // Create db.Create(&amp;Product{Code: "D42", Price: 100}) // Read var product Product db.First(&amp;product, 1) // 根据整形主键查找 db.First(&amp;product, "code = ?", "D42") // 查找 code 字段值为 D42 的记录 // Update - 将 product 的 price 更新为 200 db.Model(&amp;product).Update("Price", 200) // Update - 更新多个字段 db.Model(&amp;product).Updates(Product{Price: 200, Code: "F42"}) // 仅更新非零值字段 db.Model(&amp;product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"}) // Delete - 删除 product db.Delete(&amp;product, 1) } 声明模型 type User struct { ID uint Name string Email *string Age uint8 Birthday *time.Time MemberNumber sql.NullString ActivedAt sql.NullTime CreatedAt time.Time UpdatedAt time.Time } gorm.Model ...

2018-03-26 · 10 分钟 · 2019 字 · 王站站

gin中文文档

Gin 是一个高性能 Go Web 框架。GitHub 安装 go get -u github.com/gin-gonic/gin import "github.com/gin-gonic/gin" Hello World package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "pong"}) }) r.Run() // 0.0.0.0:8080 } go run main.go 路由 HTTP 方法 router.GET("/someGet", getting) router.POST("/somePost", posting) router.PUT("/somePut", putting) router.DELETE("/someDelete", deleting) router.PATCH("/somePatch", patching) 路径参数 // 匹配 /user/john,不匹配 /user/ router.GET("/user/:name", func(c *gin.Context) { name := c.Param("name") c.String(http.StatusOK, "Hello %s", name) }) // 匹配 /user/john/send 等 router.GET("/user/:name/*action", func(c *gin.Context) { name := c.Param("name") action := c.Param("action") c.String(http.StatusOK, name+" is "+action) }) Query 参数 // /welcome?firstname=Jane&lastname=Doe router.GET("/welcome", func(c *gin.Context) { firstname := c.DefaultQuery("firstname", "Guest") lastname := c.Query("lastname") c.String(http.StatusOK, "Hello %s %s", firstname, lastname) }) Post 参数 router.POST("/form_post", func(c *gin.Context) { message := c.PostForm("message") nick := c.DefaultPostForm("nick", "anonymous") c.JSON(200, gin.H{"status": "posted", "message": message, "nick": nick}) }) 路由分组 v1 := router.Group("/v1") { v1.POST("/login", loginEndpoint) v1.POST("/submit", submitEndpoint) } 中间件 r := gin.New() r.Use(gin.Logger()) r.Use(gin.Recovery()) authorized := r.Group("/") authorized.Use(AuthRequired()) { authorized.POST("/login", loginEndpoint) } 文件上传 // 单文件 router.POST("/upload", func(c *gin.Context) { file, _ := c.FormFile("file") c.SaveUploadedFile(file, "./"+file.Filename) c.String(http.StatusOK, "'%s' uploaded!", file.Filename) }) // 多文件 router.POST("/upload", func(c *gin.Context) { form, _ := c.MultipartForm() files := form.File["upload[]"] for _, file := range files { c.SaveUploadedFile(file, "./"+file.Filename) } c.String(http.StatusOK, "%d files uploaded!", len(files)) }) 模型绑定 type Login struct { User string `form:"user" json:"user" binding:"required"` Password string `form:"password" json:"password" binding:"required"` } router.POST("/login", func(c *gin.Context) { var json Login if err := c.ShouldBindJSON(&json); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"status": "logged in"}) }) Cookie router.GET("/cookie", func(c *gin.Context) { cookie, err := c.Cookie("gin_cookie") if err != nil { c.SetCookie("gin_cookie", "test", 3600, "/", "localhost", false, true) } _ = cookie }) 优雅重启 srv := &http.Server{Addr: ":8080", Handler: router} go srv.ListenAndServe() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() srv.Shutdown(ctx) 测试 func TestPingRoute(t *testing.T) { router := setupRouter() w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/ping", nil) router.ServeHTTP(w, req) assert.Equal(t, 200, w.Code) assert.Equal(t, "pong", w.Body.String()) } 参考 gin 中文文档

2018-03-19 · 2 分钟 · 326 字 · 王站站