诚挚先生

诚挚先生 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑

那个喜欢看夕阳的男孩。偏执、有梦想、童心不改。

个人动态

诚挚先生 关注了专栏 · 9月5日

Swoole

PHP的协程框架

关注 5386

诚挚先生 收藏了文章 · 9月1日

关于javascript跨域及JSONP的原理与应用

一、同源策略

同源策略,它是由Netscape提出的一个著名的安全策略,现在所有的可支持javascript的浏览器都会使用这个策略。

为什么需要同源策略,这里举个例子:

假设现在没有同源策略,会发生什么事情呢?大家知道,JavaScript可以做很多东西,比如:读取/修改网页中某个值。恩,你现在打开了浏览器,在一 个tab窗口中打开了银行网站,在另外一个tab窗口中打开了一个恶意网站,而那个恶意网站挂了一个的专门修改银行信息的JavaScript,当你访问 这个恶意网站并且执行它JavaScript时,你的银行页面就会被这个JavaScript修改,后果会非常严重!而同源策略就为了防止这种事情发生.

比如说,浏览器的两个tab页中分别打开了http://www.baidu.com/index.X19Xhtml和http: //www.google.com/index.html,其中,JavaScript1和JavaScript3是属于百度的脚本,而 JavaScript2是属于谷歌的脚本,当浏览器的tab1要运行一个脚本时,便会进行同源检查,只有和www.baidu.com同源的脚本才能被执 行,所谓同源,就是指域名、协议、端口相同。所以,tab1只能执行JavaScript1和JavaScript3脚本,而JavaScript2不能 执行,从而防止其他网页对本网页的非法篡改。

二、什么是JSONP?

JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。

三、为什么使用JSONP?

由于 JSON 只是一种含有简单括号结构的纯文本,因此许多通道都可以交换 JSON 消息。因为同源策略的限制,们不能在与外部服务器进行通信的时候使用 XMLHttpRequest。而JSONP是一种可以绕过同源策略的方法,即通过使用 JSON 与 < script> 标记相结合的方法,从服务端直接返回可执行的JavaScript函数调用或者JavaScript对象。

其实 jsonp 是个很简单的一个东西。主要是利用了 <script/>标签对javascript文档的动态解析来实现。(其实也可以用eval函数)。

<script type="text/javascript">
    function jsonpCallback(result) {
        alert(result.msg);
    }
</script>
<script type="text/javascript" data-original="http://crossdomain.com/jsonServerResponse?jsonp=jsonpCallback"></script>

其中 jsonCallback 是客户端注册的,获取跨域服务器上的json数据后,回调的函数。

http://crossdomain.com/jsonServerResponse?jsonp=jsonpCallback

这个 url 是跨域服务器取 json 数据的接口,参数为回调函数的名字,返回的格式为:

jsonpCallback({ msg:'this  is  json  data'})

Jsonp原理:

首先在客户端注册一个callback, 然后把callback的名字传给服务器。此时,服务器先生成 json 数据。然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp.

最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。

客户端浏览器,解析script标签,并执行返回的javascript文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数) .

其实说白了,就是客户端定义一个函数(如a),请求地址后服务器端返回的结果是调用a函数,需要的数据都放在了a函数的参数里面。

demo:

应为它用到的只是所有 HTML 元素中一个简单的 script 元素。看到这是不是觉得越发奇怪了?没关系,继续看下去就会茅厕(塞)顿开的,嘿嘿~来看个例子吧:
demo.html:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Demo</title>
</head>
<body>
<script type="text/javascript">
    function say(words) {
       alert(words);
    }
</script>
<script type="text/javascript" data-original="demo.js"></script>
</body>
</html>

demo.js:

say("Hello, everyone!");

运行 demo.html 文件后,是不是看到写着“Hello, everyone!”的警告框了?你可能会觉得这个例子很简单,没什么了不起的,甚至会在想:这和 JSONP 有关系吗?那么,我可以很肯定的告诉你:有关系!而且,这个例子实际上就是 JSONP 的原型!你也许会想到,JSONP 不是访问远程数据的吗?对,试想一下,如果 demo.js 文件在其它域的服务器上呢?结果会不会出现问题?我也可以很负责的告诉你:不会!你可以将上面例子中的 demo.js 更改为:http://demo.hpyer.cn/php/jsonp.php?callback=say 再试一下。
现在,聪明的你应该已经明白 JSONP 到底是怎么回事了,那么,再来解释一下本节开头第一句话吧。看过 demo.js 文件的内容,应该知道,其只是对一个函数(通常称之为:回调函数)的调用,而需要交互的数据则通过参数形势进行返回。所以通过 JSONP 访问的服务器需要提供一个可以设置回调函数名的接口,就像 http://demo.hpyer.cn/php/jsonp.php?callback=say 中的 callback,所以,综上所述 JSONP 是需要服务器端的支持的。附上 jsonp.php 的源码:

<?php
$type = isset($_GET['type']) ? $_GET['type'] : '';
$callback = isset($_GET['callback']) ? $_GET['callback'] : '';
$json = '';
if ($type == 'json') {
   $json = '{
   "Image": {
   "Width": 800,
   "Height": 600,
   "Title": "View from 15th Floor",
   "Thumbnail": {
   "Url": "http://www.example.com/image/481989943",
   "Height": 125,
   "Width": "100"
   },
   "IDs": [116, 943, 234, 38793]
   }
   }';
} else {
   $json = '"Hello, everyone!"';
}
if (!empty($callback)) {
   $json = $callback . '(' . $json . ')';
}
echo $json;

jquery 中的应用:
自 1.2 版本起,jQuery 加入了对 JSONP 的支持。我们可以很容易的利用 $.getJSON() 方法(或者其它基于 $.ajax() 的方法),来跨域加载 JSON 数据。来个例子吧:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Demo</title>
<script type="text/javascript" data-original="jquery.js"></script>
<script type="text/javascript">
function do_jsonp() {
   $.getJSON("http://demo.hpyer.cn/php/jsonp.php?type=json&callback=?",
   function(data) {
   $('#result').val('data.Image.IDs: ' + data.Image.IDs);
   });
}
</script>
</head>
<body>
<a href="javascript:do_jsonp();">Click me</a><br />
<textarea id="result" cols="50" rows="5"></textarea>
</body>
</html>

你可能注意到上面的例子中,url 被写成了 http://demo.hpyer.cn/php/jsonp.php?type=json&callback=?,需要说明的是,这个问号会被 jQuery 自动替换为回调函数的函数名(如果是一个匿名函数,jQuery 会自动生成一个带时间戳的函数名)。

看我在项目中的一个例子:

//定义Ajax函数
function ajaxFun() {
    var timeStamp = Math.floor(new Date().getTime() / 1000);
    var url = "http://apiso.alidemo.3gpp.cn/httpserver/cp/yisou/ali_feedback_interface.php?callback=jsonpCallback&feedbacktype=add&type=" + feedbackNumber + "&book=" + me.mixedInfo.title + "&author=" + me.mixedInfo.author + "&chapter=" + me.mixedInfo.cname + "&chapterid=" + me.mixedInfo.cid + "&questiondesc=" + text + "&platform=1&t=" + timeStamp + "&sn=" + md5("d30fcd1a9f1900fa049b4766e0a275e1" + timeStamp);
    var scriptObj = document.createElement("script");
    scriptObj.src = url;
    scriptObj.id = "jsonpScript";
    document.body.appendChild(scriptObj);
    //jsonp回调函数,jsonpCallback必须为全局函数,因为jsonp返回的是在全局环境中执行函数的语句,即jsonpCallback(data)
    window.jsonpCallback = function(data) {
        switch (data.code) {
            case "1":
                novel.readerPrompt('提交成功,即将返回……', 1, function() {
                    window.history.go(-1);
                });
                break;
            case "0":
                novel.readerPrompt('提交失败。', 2);
                break;
            case "900":
                novel.readerPrompt('提交失败,验证失败。', 2);
                break;
        }
        //成功后删除scriptObj,后面的setTimeout就不会执行了
        if (document.getElementById("jsonpScript")) {
            document.body.removeChild(scriptObj);
        }
    }
    //设置超时,超时的话直接显示提交成功
    setTimeout(function() {
        if (document.getElementById("jsonpScript")) {
            document.body.removeChild(scriptObj);
            novel.readerPrompt('提交成功,即将返回……', 1, function() {
                window.history.go(-1);
            });
        }
    }, 2000);
}
ajaxFun();

via WEB前端开发

查看原文

诚挚先生 收藏了文章 · 9月1日

跨域总结(jquery,php)

引子

项目原因,前后端跨域了,第一次涉及到跨域的内容,踩了蛮多坑的,总结一下,避免下次再遇到~

一、图片发送请求

因为图片是不会去判断是否跨域的,但是也只能发送get请求,并且获取不到返回值,可以用来监听页面访问数量或者广告点击数量

var img=new Image();
img.data-original='http://www.baidu.com';
img.onerror=function(){
 alert('error');
}
img.onload=function(){
 alert('success');
}

二、jsonp

jsonp只能用于get请求,设置dataType:'jsonp'

使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数。
$.ajax({
  url: "test.html",
  dataType:'jsonp',
  success: function(html){
      //
  }
});

其实实现就下面的效果,如果直接这样写,就是页面直接执行,请求成功后执行页面的call函数

<script type="text/javascript" data-original='http://www.aaa.com?callback=call'></script>

三、CORS,服务器端设置

1.服务器端设置允许请求的地址

 header( "Access-Control-Allow-Origin:*" );

2.设置可请求的方式

 header( "Access-Control-Allow-Methods:POST,GET" );

3.可以设置header头部内容允许添加的头部信息

header('Access-Control-Allow-Headers:value');
  $.ajax({
            type: "GET",
            url: '#',
            header:{//添加头部信息
                value:'123456'
            },
            crossDomain: true,
            success: function (data) {});

4.发送cookie

需要注意的是,如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名

    response.setHeader("Access-Control-Allow-Credentials","true");
  $.ajax({
            type: "GET",
            url: '#',
            crossDomain: true,
            xhrFields: {withCredentials: true},//发送cookie
            success: function (data) {});

结束

参考:跨域资源共享 CORS 详解

查看原文

诚挚先生 发布了文章 · 6月25日

整理给大家看的php7语法总结

php5.6~7.0

标量类型声明

类型声明允许函数在调用时要求参数为特定类型。 如果给出的值类型不对,那么将会产生一个错误: 在PHP 5中,这将是一个可恢复的致命错误,而在PHP 7中将会抛出一个TypeError异常。

为了指定一个类型声明,类型应该加到参数名前。这个声明可以通过将参数的默认值设为NULL来实现允许传递NULL

PHP7增加了以下几种类型声明

TypeDescriptionMinimum PHP version
boolbool类型PHP 7.0.0
floatfloat类型PHP 7.0.0
intint类型PHP 7.0.0
stringstring类型PHP 7.0.0
iterableiterable类型PHP 7.1.0
objectobject类型PHP 7.2.0

返回值类型声明

PHP 7 增加了对返回值类型声明的支持。 就如 [类型声明]一样, 返回值类型声明将指定该函数返回值的类型。同样,返回值类型声明也与 [有效类型] 中可用的参数类型声明一致。
[严格类型] 也会影响返回值类型声明。在默认的弱模式中,如果返回值与返回值的类型不一致,则会被强制转换为返回值声明的类型。在强模式中,返回值的类型必须正确,否则将会抛出一个TypeError异常.
//严格类型声明
declare(strict_types=1);
function sum($a, $b): float {  
    return $a + $b;  
}

null合并运算符

由于日常使用中存在大量同时使用三元表达式和 [isset()]的情况, 我们添加了null合并运算符 (_??_) 这个语法糖。如果变量存在且值不为NULL, 它就会返回自身的值,否则返回它的第二个操作数。
$username = $_GET['user'] ?? 'nobody';  
// This is equivalent to:  
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

太空船操作符(组合比较符)

太空船操作符用于比较两个表达式。当$a小于、等于或大于$b时它分别返回-1、0或1。 比较的原则是沿用 PHP 的常规比较规则进行的

// 整数  
echo 1 <=> 1; // 0  
echo 1 <=> 2; // -1  
echo 2 <=> 1; // 1  
  
// 浮点数  
echo 1.5 <=> 1.5; // 0  
echo 1.5 <=> 2.5; // -1  
echo 2.5 <=> 1.5; // 1  
   
// 字符串  
echo "a" <=> "a"; // 0  
echo "a" <=> "b"; // -1  
echo "b" <=> "a"; // 1

通过 define() 定义常量数组

Array 类型的常量现在可以通过 define() 来定义。在 PHP5.6 中仅能通过 const 定义。

tips:

和使用 define() 来定义常量相反的是,使用 const 关键字定义常量必须处于最顶端的作用区域,因为用此方法是在编译时定义的。这就意味着不能在函数内,循环内以及 if 语句之内用 const 来定义常量。
define('ANIMALS', [ 'dog', 'cat', 'bird'  
]);  
  
echo ANIMALS[1]; // 输出 "cat"

匿名类

现在支持通过_new class_ 来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。
interface Logger {  
    public function log(string $msg);  
}  
  
class Application {  
    private $logger;  
  
    public function getLogger(): Logger {  
         return $this->logger;  
    }  
  
    public function setLogger(Logger $logger) { $this->logger = $logger;  
    }  
}  
  
$app = new Application;  
$app->setLogger(new class implements Logger {  
    public function log(string $msg) {  
        echo $msg;  
    }  
});  
  
var_dump($app->getLogger());
object(class@anonymous)#2 (0) {
}

Closure::call()

Closure::call() 现在有着更好的性能,简短干练的暂时绑定一个方法到对象上闭包并调用它。
class A {private $x = 1;}  
  
// PHP 7 之前版本的代码  
$getXCB = function() {return $this->x;};  
$getX = $getXCB\->bindTo(new A, 'A'); // 中间层闭包  
echo $getX();  
  
// PHP 7+ 及更高版本的代码  
$getX = function() {return $this->x;};  
echo $getX->call(new A);
1
1

预期

预期是向后兼用并增强之前的 assert() 的方法。 它使得在生产环境中启用断言为零成本,并且提供当断言失败时抛出特定异常的能力。

老版本的API出于兼容目的将继续被维护,assert()现在是一个语言结构,它允许第一个参数是一个表达式,而不仅仅是一个待计算的 string或一个待测试的boolean

ini_set('assert.exception', 1);  
  
class CustomError extends AssertionError {}  
  
assert(false, new CustomError('Some error message'));
Fatal error: Uncaught CustomError: Some error message

Group use declarations

从同一 namespace 导入的类、函数和常量现在可以通过单个 use 语句 一次性导入了。
// PHP 7 之前的代码  
use some\\namespace\\ClassA;  
use some\\namespace\\ClassB;  
use some\\namespace\\ClassC as C;  
  
use function some\\namespace\\fn\_a;  
use function some\\namespace\\fn\_b;  
use function some\\namespace\\fn\_c;  
  
use const some\\namespace\\ConstA;  
use const some\\namespace\\ConstB;  
use const some\\namespace\\ConstC;  
  
// PHP 7+ 及更高版本的代码  
use some\\namespace\\{ClassA, ClassB, ClassC as C};  
use function some\\namespace\\{fn\_a, fn\_b, fn\_c};  
use const some\\namespace\\{ConstA, ConstB, ConstC};

会话选项

session_start() 可以接受一个 array 作为参数, 用来覆盖 php.ini 文件中设置的 会话配置选项

在调用 session_start() 的时候, 传入的选项参数中也支持 session.lazy_write 行为, 默认情况下这个配置项是打开的。它的作用是控制 PHP 只有在会话中的数据发生变化的时候才 写入会话存储文件,如果会话中的数据没有发生改变,那么 PHP 会在读取完会话数据之后, 立即关闭会话存储文件,不做任何修改,可以通过设置 read_and_close 来实现。

例如,下列代码设置 session.cache_limiter 为 _private_,并且在读取完毕会话数据之后马上关闭会话存储文件。

session_start([ 'cache_limiter'=> 'private', 'read_and_close' => true,  
]);

preg_replace_callback_array()

在 PHP 7 之前,当使用 preg_replace_callback() 函数的时候, 由于针对每个正则表达式都要执行回调函数,可能导致过多的分支代码。 而使用新加的 preg_replace_callback_array() 函数, 可以使得代码更加简洁。

现在,可以使用一个关联数组来对每个正则表达式注册回调函数, 正则表达式本身作为关联数组的键, 而对应的回调函数就是关联数组的值。

新加入两个跨平台的函数: random_bytes()random_int() 用来产生高安全级别的随机字符串和随机整数。

可以使用 list() 函数来展开实现了 ArrayAccess 接口的对象

允许在克隆表达式上访问对象成员,例如: _(clone $foo)->bar()_。


持续更新。。。。

查看原文

赞 0 收藏 0 评论 0

诚挚先生 收藏了文章 · 6月2日

thinkphp 5.1框架解析(三):容器和依赖注入

在上一篇文章中我们讲到了 ThinkPHP 如何实现自动加载,如果想看的话可以看
ThinkPHP5.1 源码浅析(二)自动加载机制

在阅读本篇文章 之前,我希望你掌握了 IOC 、DI 、Facade的基本知识,如果不了解,请先查看着几篇文章。

深入理解控制反转(IoC)和依赖注入(DI)

那么步入正题。

服务调用

基于分析框架的 入口脚本文件index.php

// 加载基础文件
require __DIR__ . '/../thinkphp/base.php';

// 支持事先使用静态方法设置Request对象和Config对象

// 执行应用并响应
Container::get('app')->run()->send();

上面 base.php 中的作用是载入自动加载机制,和异常处理,以及开启日志功能。

// 执行应用并响应
Container::get('app')->run()->send();

在这里才是使用了 IOC 容器功能,获取 app 这个容器1

进入 Container 中之后我们先介绍他的类属性

protected static $instance; // 定义我们的容器类实例,采用单例模式,只实例化一次
protected $instances = [];    // 容器中的对象实例
protected $bind = [];        // 容器绑定标识
protected $name = [];        // 容器标识别名

$instances 是实现了 注册树模式2,存储值

array (
  'think\\App' => App实例,
  'think\\Env' => Env实例,
  'think\\Config' => Config实例,
   ...
)

bind 在初始化时,会载入一堆初始数据,记录一堆类别名和 类名的映射关系。

protected $bind = [
      'app' => 'think\\App',
      'build' => 'think\\Build',
      'cache' => 'think\\Cache',
      'config' => 'think\\Config',
      'cookie' => 'think\\Cookie',
        ...
    ]

namebind 属性记录的值都是很类似的,都是 类别名和 类名的映射关系。区别是,name 记录的是 已经实例化后的 映射关系。

进入get方法

public static function get($abstract, $vars = [], $newInstance = false)
{
    return static::getInstance()->make($abstract, $vars, $newInstance);
}

这一段代码没什么好讲的,就是先获取当前容器的实例(单例),并实例化。

进入 make 方法

public function make($abstract, $vars = [], $newInstance = false)
{
    if (true === $vars) {
        // 总是创建新的实例化对象
        $newInstance = true;
        $vars        = [];
    }
    // 如果已经存在并且实例化的类,就用别名拿到他的类
    $abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;
    // 如果已经实例化,并且不用每次创建新的实例的话,就直接返回注册树上的实例
    if (isset($this->instances[$abstract]) && !$newInstance) {
        return $this->instances[$abstract];
    }
    // 如果我们绑定过这个类,例如 'app' => 'think\\App',
    if (isset($this->bind[$abstract])) {
        $concrete = $this->bind[$abstract];
        // 因为ThinkPHP 实现可以绑定一个闭包或者匿名函数进入,这里是对闭包的处理
        if ($concrete instanceof Closure) {
            $object = $this->invokeFunction($concrete, $vars);
        } else {
            // 记录 映射关系,并按照 类名来实例化,如 think\\App
            $this->name[$abstract] = $concrete;
            return $this->make($concrete, $vars, $newInstance);
        }
    } else {
        // 按照类名调用该类
        $object = $this->invokeClass($abstract, $vars);
    }

    if (!$newInstance) {
        $this->instances[$abstract] = $object;
    }
    // 返回制作出来的该类
    return $object;
}

我们拆分一下,

if (true === $vars) {
        // 总是创建新的实例化对象
        $newInstance = true;
        $vars        = [];
}

这段代码是 让我们函数可以 使用 make($abstract, true)的方式调用此函数,使我们每次得到的都是新的实例。(我觉得这种方式不是很好,每个变量的造成含义不明确)

// 如果已经存在并且实例化的类,就用别名拿到他的类
    $abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;
    // 如果已经实例化,并且不用每次创建新的实例的话,就直接返回注册树上的实例
    if (isset($this->instances[$abstract]) && !$newInstance) {
        return $this->instances[$abstract];
    }

前面说过,name 中存放的是已经实例化的 别名=> 类名 的映射关系,我们在这里尝试取出 类名,如果该类实例化,就直接返回。

// 如果我们绑定过这个类,例如 'app' => 'think\\App',
    if (isset($this->bind[$abstract])) {
        $concrete = $this->bind[$abstract];
        // 因为ThinkPHP 实现可以绑定一个闭包或者匿名函数进入,这里是对闭包的处理
        if ($concrete instanceof Closure) {
            $object = $this->invokeFunction($concrete, $vars);
        } else {
            // 记录 映射关系,并按照 类名来实例化,如 think\\App
            $this->name[$abstract] = $concrete;
            return $this->make($concrete, $vars, $newInstance);
        }
    } else {
        // 按照类名调用该类
        $object = $this->invokeClass($abstract, $vars);
    }

这里是看我们需要容器加载的类是否以前绑定过别名(我们也可以直接 bind('classNickName') 来设置一个)

  1. 如果绑定过,那么就来实例化它。
  2. 如果没有,那么就认定他是一个类名,直接调用。3

门面模式

在上面的 IOC 容器中,我们需要 $ioc->get('test'); 才能拿到 test 类,才能使用我们的 $user->hello()方法进行打招呼,有了门面之后,我们可以直接 用 Test::hello() 进行静态调用,下面我们就来介绍一下这个

在我们编写代码时经常会用到 facade包下的类来接口的静态调用,我们在这里举一下官网的例子

假如我们定义了一个app\common\Test类,里面有一个hello动态方法。

<?php
namespace app\common;

class Test
{
    public function hello($name)
    {
        return 'hello,' . $name;
    }
}

调用hello方法的代码应该类似于:

$test = new \app\common\Test;
echo $test->hello('thinkphp'); // 输出 hello,thinkphp

接下来,我们给这个类定义一个静态代理类app\facade\Test(这个类名不一定要和Test类一致,但通常为了便于管理,建议保持名称统一)。

<?php
namespace app\facade;

use think\Facade;

class Test extends Facade
{
    protected static function getFacadeClass()
    {
        return 'app\common\Test';
    }
}

只要这个类库继承think\Facade,就可以使用静态方式调用动态类app\common\Test的动态方法,例如上面的代码就可以改成:

// 无需进行实例化 直接以静态方法方式调用hello
echo \app\facade\Test::hello('thinkphp');

结果也会输出 hello,thinkphp

说的直白一点,Facade功能可以让类无需实例化而直接进行静态方式调用。

Facade工作原理

  1. Facede 核心实现原理就是在 Facade 提前注入IoC容器。
  2. 定义一个服务提供者的外观类,在该类定义一个类的变量,跟ioc容器绑定的key一样,
  3. 通过静态魔术方法__callStatic可以得到当前想要调用的 hello 方法
  4. 使用static::$ioc->make('Test');

为什么要使用 Facade

使用Facades其实最主要的就是它提供了简单,易记的语法,从而无需手动注入或配置长长的类名。此外,由于他们对 PHP 静态方法的独特调用,使得测试起来非常容易。


  1. 在这里系统找不到 Container 类的位置,所以会执行自动加载机制去寻找 Container 的位置,并加载它
  2. 把一堆实例挂在树上,需要的时候在拿来用。
  3. 直接调用是使用了反射后的结果,关于反射的知识点在自行查看
查看原文

诚挚先生 关注了用户 · 5月30日

什么都只会一点点 @xspdebug

非著名的CURD程序员。

csdn博客: https://blog.csdn.net/qq_3617...

关注 9

诚挚先生 收藏了文章 · 5月30日

PHP / Laravel API 开发推荐阅读清单

clipboard.png

社区优秀文章

开发 API 必读文章

现成 API 例子

调试工具

Laravel API 课程

社区有一门实战课程 《Laravel 教程实战高级 - 构架 API 服务器》 ,主要专注于 App 和 SPA 后端 API 服务器实战开发。手把手带你构建一个设计合理的 RESTful API 服务器。本课程涉及的技术话题有:

  • RESTFul 的概念及 Github Api 设计分解;
  • DingoApi 的介绍及安装;
  • PostMan 的介绍及使用;
  • 用户认证 —— 手机注册、登录、退出;
  • 第三方认证 —— 微信登录、JWT的使用;
  • 用户信息 —— 获取个人信息、上传图片接口、修改个人信息;
  • 话题接口 —— 发布、修改、删除、列表;
  • 话题回复接口 —— 发布、修改、删除、列表;
  • 权限控制 —— 权限列表,角色列表;
  • 资源推荐接口、活跃用户接口;
  • 接口本地化处理;
  • API 接口错误代码机制;
  • APNS 消息推送服务器端介绍及实现;
  • API 测试 —— 单元测试、集成测试、黑盒测试;
  • 快速完成 API 文档;
  • Passport / OAuth 2.0 认证。
原文见:https://laravel-china.org/doc...
查看原文

诚挚先生 收藏了文章 · 5月30日

收藏了8年的PHP优秀资源,都给你整理好了

最后更新于 2020.02.06

以下是我整理好的 PHP 资源,各位看官拿去用,不用再自己找了。

GitHub 上稳定更新,觉得不错请点个 Star ❤️

如转载分享,请保留出处,谢谢 😆

原文地址: https://shockerli.net/post/ph...

GitHub: https://github.com/shockerli/...

资源站点

项目框架

  • laravel-admin - 快速构建后台管理的开发工具
  • Voyager - Laravel 后台管理框架
  • FastAdmin - 基于 ThinkPHP5 + Bootstrap 的极速后台开发框架
  • YFCMF - 后台内容管理框架,基于 ThinkPHP5.1
  • ThinkCMF - 后台内容管理框架,基于 ThinkPHP5
  • RhaPHP - 微信开发、小程序开发、微信公众号管理系统
  • OneBase - 基于 ThinkPHP5 的后台开发框架

成品软件

未归类

CMS

  • Grav - 基于文件的 CMS
  • October - 基于 Laravel 开发的 CMS

社区

  • Flarum - 基于 PHP 和 Mithril.js 开发的轻社区
  • PHPDish - 基于 Symfony 框架开发的内容社区系统
  • Koel - 音乐社区🎵

文件管理

微信相关

项目管理

构建/部署

  • Phabricator - 用于敏捷开发的项目管理软件, 含代码托管、Code Review、任务管理、文档管理、问题跟踪、构建与持续集成、博客、内部聊天等

  • Walle - Web系统部署工具
  • Piplin - 持续集成系统
  • Phing - PHP项目构建工具
  • Deployer - PHP项目部署工具
  • PHPCI - 持续集成工具

基础框架

类库

未归类

路由

异步/协程

  • Amp - 非阻塞协程并发框架
  • Recoil - 异步协程框架
  • Promise - Promises/A implementation for PHP
  • Guzzle Promises - Promises/A+ library for PHP with synchronous support

前端相关

  • PHP-CSS-Parser - PHP 实现的 CSS 解析器
  • Minify - JS 和 CSS 压缩工具
  • Munee - 一个集图片尺寸调整、CSS-JS 合并/压缩、缓存等功能于一身的PHP库

聊天/短信

文本处理

算法

语法解析

代码检查/静态分析

CLI

错误/异常

调试工具

API

  • phprs - 一款轻量、类 jax-rs、实用的 PHP 框架
  • graphql-php - GraphQL 参考实现的 PHP 移植版本
  • Dingo API - A RESTful API package for the Laravel and Lumen frameworks

安全

加密/解密

时间/日期

  • Chinese calendar - 中国农历(阴历)与阳历(公历)转换与查询工具
  • Carbon - 时间日期处理类

微信

网页抓取/代理

URL/Domain

OAuth

Auth

  • jwt-auth - JSON Web Token Authentication for Laravel & Lumen

API文档

数据库

队列/任务

  • RoboTask - 面向对象的 PHP 任务运行器
  • PHP-Queue - 管理队列后端的应用
  • RoboTask - PHP 后台任务组件
  • Task - 一个灵感来源于 Grunt 和 Gulp 的纯 PHP 任务运行器
  • php-resque - PHP 版Resque
  • taskPHP - 基于原生态 PHP 开发的定时计划任务框架
  • SimpleFork - 精简的 PHP 多进程控制库

缓存

Markdown

邮件

Office

PDF/条形码

  • Barcode - Barcode 生成工具
  • Snappy - 根据 URL 或 HTML 页面生成图片或 PDF 格式的缩略图
  • TCPDF - 使用官方 PDF 类生成 PDF 文档和条形码生成工具
  • FPDF - 利用纯 PHP 代码生成 PDF 文件
  • PDFParser - PDF 文档解析库
  • Dompdf
  • Browsershot - 将 HTML 转换为图像、PDF 或字符串

HTTP/网络通信

表单校验

测试框架

模板引擎

图像处理

Composer

最好用的 PHP 包管理器,没有之一

PHP 扩展

  • pickle - PHP 扩展安装工具
  • PHPTrace - 跟踪和分析 PHP 脚本的工具
  • Zephir - 编写 PHP 扩展的编程语言
  • Yaconf - 高性能的配置管理扩展
  • php-beast - PHP 源码加密模块

PHP相关软件/工具


感谢您的阅读,觉得内容不错,点个赞吧 😆

原文地址: https://shockerli.net/post/ph...
查看原文

诚挚先生 关注了专栏 · 5月30日

徐小鹏的学习笔记

关于我为学习中的一些新的感受

关注 27

诚挚先生 关注了专栏 · 5月30日

格物

无善无恶心之体,有善有恶意之动。知善知恶是良知,为善去恶是格物。 https://shockerli.net

关注 1263

认证与成就

  • 获得 0 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2018-05-04
个人主页被 80 人浏览