SG :一个简单的PHP语法糖扩展

奇技指南 语法糖往往给程序员提供了更实用的编码方式,可以使代码更简洁流畅,语义更自然。本文介绍笔者自己写的PHP语法糖扩展,扩展了一种全新的PHP超全局变量获取方式。 本文作者范家鹏,360技术委员会--WEB服务端分TC委员。

1、说说语法糖

首先说说“语法糖”这个词绝非贬义词,它可以给我们的开发工作带来便利,是一种轻量级便捷的写法,既不会对语言本身的使用造成不利影响,也不会在性能上带来损失。

通常情况下,使用语法糖能够增加程序的可读性,减少程序复杂性,减少编码中出错的机会,也对开发工程师具有友好性,能够提升我们的开发效率。 

优秀的语法糖,应该是一种灵魂思想的注入,简单写法的应用。我这里用一幅图来表示:

2、什么是SG?

SG 全称 Superglobals,引用全局作用域中可用的全部变量。SG扩展了一种全新的PHP超全局变量获取方式。 

这些超全局变量是:_SERVER,_GET,_POST,_FILES,_COOKIE,_SESSION,_REQUEST,_ENV。 

当然了,也可以应用到自定义变量场景。

非常重要的一点是:它很简单

2.1 项目背景

这个idea出发点很简单,从扩展名称我们应该能猜到它是做什么的。

在性能最优的前提下: 

  • 能通俗易懂地简化HTTP参数获取方法
  • 需要对HTTP参数值进行统一过滤、转换、解密操作
  • 获取HTTP参数前,需要进行一些Predefined Operation
  • 针对HTTP参数的一切行为,需要同步更新对应的PHP Superglobal
  • 声明时才使用,而非请求一开始就对PHP Superglobals扫荡式处理
  • 在global语法上,扩展一项能获取HTTP参数的能力

So,SG出现就是为了解决上面这些问题而来,它提供了一种更加甜蜜的语法,当前已经发布了v3.0.0。

2.2 项目地址

https://github.com/yulonghu/sg

欢迎大家来提交Issues~

当前支持的PHP版本,如下图所示:

3、SG的特性

  • 简单,快速,轻量 
  • 零拷贝访问PHP超全局变量,使用SG会同步更新PHP超全局变量 
  • 支持取值前调用自定义函数,默认情况下,字符串变量会自动调用 PHP trim 
  • 解决使用PHP超全局变量时出现未定义系列的问题 (Undefined variable, Undefinedoffset) 
  • 采用静态方法时,以小数点代替PHP数组维度 
  • 采用global声明方式时,以下划线代替PHP数组维度
  • 支持可配置的global $variable查找深度,默认一级查找

4、配置项(php.ini)

配置项

权限

类型

默认值

说明

sg.enable

PHP_INI_SYSTEM

bool

0

0 关闭 1 开启

sg.global_level

PHP_INI_SYSTEM

bool

1

1 只支持一级查找 0 无限制查找

sg.func_name

PHP_INI_ALL

char

trim

默认调用 PHP trim 函数,也支持自定义函数

5、Hash Map

PHP 超全局变量

SG key (关键字缩写)

global 声明

函数

$GLOBALS

sg::all()

$_SERVER

s

global $s

sg::get/set/has/del('s')

$_GET

g

global $g

sg::get/set/has/del('g')

$_POST

p

global $p

sg::get/set/has/del('p')

$_FILES

f

global $f

sg::get/set/has/del('f')

$_COOKIE

c

global $c

sg::get/set/has/del('c')

$_SESSION

n

global $n

sg::get/set/has/del('n')

$_REQUEST

r

global $r

sg::get/set/has/del('r')

$_ENV

e

global $e

sg::get/set/has/del('e')

6、流程图

6.1 global 声明方式(PHP7)

6.2 函数方式

7、API

7.1 global 声明方式

global $g_key, $p_key, $c_key, $s_key, $f_key, $n_key, $e_key, $r_key

7.2 静态方法

1bool sg::set(string $key, mixed $value) 2mixed sg::get(string $key [, mixed $default_value = null]) 3bool sg::has(string $key) 4bool sg::del(string $key [, mixed $... ]) 5array sg::all(void)

8、例子

8.1 global 声明例子

8.1.1 sg.global_level = 1

1<?php 2 3$_GET['key'] = 'GET_test_key'; 4 5function testGlobal() 6{ 7 global $g_key; 8 9 var_dump($g_key); 10 11 $g_key = 'NEW_GET_test_key'; 12} 13 14testGlobal(); 15 16var_dump(sg::get('g.key')); 17var_dump($GLOBALS['g_key']); 18var_dump($g_key); 19var_dump($_GET['key']);

以上例子输出的结果:

1string(12) "GET_test_key" 2string(16) "NEW_GET_test_key" 3string(16) "NEW_GET_test_key" 4string(16) "NEW_GET_test_key" 5string(16) "NEW_GET_test_key"

8.1.2 sg.global_level = 0

1<?php 2 3$_GET['key']['key1']['key2'] = 'GET_test_key'; 4 5function testGlobal() 6{ 7 global $g_key_key1_key2; 8} 9 10testGlobal(); 11 12var_dump(sg::get('g.key.key1.key2')); 13var_dump($GLOBALS['g_key_key1_key2']); 14var_dump($g_key_key1_key2); 15var_dump($_GET['key']['key1']['key2']);

以上例子输出的结果:

1string(12) "GET_test_key" 2string(12) "GET_test_key" 3string(12) "GET_test_key" 4string(12) "GET_test_key"

8.1.3 sg.func_name

1<?php 2 3ini_set('sg.func_name', 'decryptTest'); 4 5$_POST['key'] = 'IEEgQmFuYW5hIA=='; 6 7function decryptTest($data) 8{ 9 return trim(base64_decode($data)); 10} 11global $p_key; 12var_dump($p_key);

以上例子输出的结果:

string(8) "A Banana"

8.2 静态方法例子

8.2.1 get/set/has/del()

1<?php 2 3$key = 'test'; 4$val = 'A Banana'; 5 6echo "------------------start\n"; 7var_dump(sg::get($key)); 8var_dump(sg::get($key, 'def')); 9var_dump(sg::has($key)); 10 11echo "------------------set\n"; 12var_dump(sg::set($key, $val)); 13 14echo "------------------get\n"; 15var_dump(sg::get($key)); 16var_dump(sg::get($key, 'def')); 17var_dump(sg::has($key)); 18 19echo "------------------del\n"; 20var_dump(sg::del($key)); 21 22echo "------------------get\n"; 23var_dump(sg::get($key)); 24var_dump(sg::has($key));

以上例子输出的结果:

1------------------start 2NULL 3string(3) "def" 4bool(false) 5------------------set 6bool(true) 7------------------get 8string(8) "A banana" 9string(8) "A banana" 10bool(true) 11------------------del 12bool(true) 13------------------get 14NULL 15bool(false)

8.2.2 sg.func_name

1<?php 2 3ini_set('sg.func_name', 'decryptTest'); 4 5function decryptTest($data) 6{ 7 return trim(base64_decode($data)); 8} 9 10function encryptTest($data) 11{ 12 return base64_encode(trim($data)); 13} 14 15sg::set('user', encryptTest(' A Banana ')); 16var_dump(sg::get('user'));

以上例子输出的结果:

string(8) "A Banana"

9、性能测试

噼里啪啦说了大半天,性能到底怎么样呢?我在本地环境做了一个简单的ab测试(ab -c100 -n10000),PHP测试代码如下:

9.1 default - 源码

1<?php 2/* default.php */ 3for($i = 0; $i < 1000; $i++) { 4 if(isset($_GET['key'])) { 5 var_dump(trim($_GET['key'])); 6 } 7}

9.2 global 声明方式 - 源码

1<?php 2/* sg.php */ 3for($i = 0; $i < 1000; $i++) { 4 global $g_key; 5 var_dump($g_key); 6}

ab 测试的结果如下:

9.3 default - 结果

1$ ab -c100 -n10000 localhost/default.php?key=hello_world 2 3 4Concurrency Level: 100 5Time taken for tests: 1.615 seconds 6Complete requests: 10000 7Failed requests: 0 8Write errors: 0 9Total transferred: 251370000 bytes 10HTML transferred: 250000000 bytes 11Requests per second: 6190.21 [#/sec] (mean) 12Time per request: 16.155 [ms] (mean) 13Time per request: 0.162 [ms] (mean, across all concurrent requests) 14Transfer rate: 151956.36 [Kbytes/sec] received

9.4 global 声明方式 - 结果

1$ ab -c100 -n10000 localhost/sg.php?key=hello_world 2 3 4Concurrency Level: 100 5Time taken for tests: 1.441 seconds 6Complete requests: 10000 7Failed requests: 0 8Write errors: 0 9Total transferred: 251931544 bytes 10HTML transferred: 250557708 bytes 11Requests per second: 6938.67 [#/sec] (mean) 12Time per request: 14.412 [ms] (mean) 13Time per request: 0.144 [ms] (mean, across all concurrent requests) 14Transfer rate: 170709.87 [Kbytes/sec] received

10、总  结

SG具有以下优势:

  • 兼容了当前的主流PHP版本 
  • 提供了一种更加甜蜜的语法,丰富了Superglobals的应用
  • 我们始终相信:简单才是王道

注意:global 声明方式,当前只支持不可变变量名。

(360技术原创内容,转载请务必保留文末二维码,谢谢~)

关于360技术

360技术是360技术团队打造的技术分享公众号,每天推送技术干货内容

更多技术信息欢迎关注“360技术”微信公众号

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )