0%

PHP各种学习

真正的高贵,从来不是要比别人优秀,而是要跨越曾经的自己。

foreach问题

一、基础

  1. php4中引入了foreach结构,这是一种遍历数组的简单方式。相比传统的for循环,foreach能够更加便捷的获取键/值对。在php5之前,foreach仅能用于数组;php5之后,利用foreach还能遍历对象。
    • foreach开始执行时,数组内部的指针会自动指向第一个单元,这意味着不需要在foreach循环之前调用reset()
    • 由于foreach依赖内部数组指针,在循环中修改其值将可能导致意外的行为(可以很容易地通过在$value之前加上&来修改数组的元素)。
    • 数组最后一个元素的$value引用在foreach循环之后仍会保留,建议使用unset()来将其销毁(unset只会取消引用,不会销毁值)。(问题就出在这里)

二、demo

  1. 例子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $arr = [1, 2, 3];
    foreach($arr as &$val);
    foreach($arr as $val);
    print_r($arr);
    期望结果:
    Array
    (
    [0] => 1
    [1] => 2
    [2] => 3
    )
    实际结果:
    Array
    (
    [0] => 1
    [1] => 2
    [2] => 2
    )
  2. 分析

    其实,我们可以认为foreach($arr as $k => $v)结构隐含了如下两个赋值操作,分别将数组当前的’键’和当前的’值’赋给变量$k和$v,具体展开形如:

1
2
3
4
5
6
foreach($arr as $k => $v){
$v = currentVal();
$k = currentKey();
//TODO code
……
}

根据上述理论,现在我们重新来分析下第一个foreach:

  • 第1遍循环,$v是一个引用,即$v = &$arr[0],此时$arr变成[1,2,3]

  • 第2遍循环,同理可得:$v = &$arr[1],$arr变成[1,2,3]

  • 第3遍循环,同理可得:$v = &$arr[2],$arr变成[1,2,3]

  • 此时并未执行unset($v)操作,$v现在是数组最后一个元素的引用*

    随后代码进入了第二个foreach:

  • 第1遍循环,隐含操作$v=$arr[0]被触发,$v仍然是$arr[2]的引用,相当于$arr[2]=$arr[0],$arr变成[1,2,1]

  • 第2遍循环,$v=$arr[1],同理($v仍然是$arr[2]的引用)可得:$arr[2]=$arr[1],$arr变成[1,2,2]

  • 第3遍循环,$v=$arr[2],同理($v仍然是$arr[2]的引用)可得:$arr[2]=$arr[2],$arr变成[1,2,2]

    三、参考

  1. 参考一
  2. 参考二

Guzzle

一、定义

  1. Guzzle是一个PHP的HTTP客户端,用来轻而易举地发送请求,并集成到我们的WEB服务上。
    • 接口简单:构建查询语句、POST请求、分流上传下载大文件、使用HTTP cookies、上传JSON数据等等。
    • 发送同步或异步的请求均使用相同的接口。
    • 使用PSR-7接口来请求、响应、分流,允许你使用其他兼容的PSR-7类库与Guzzle共同开发。
    • 抽象了底层的HTTP传输,允许你改变环境以及其他的代码,如:对cURL与PHP的流或socket并非重度依赖,非阻塞事件循环。
    • 中间件系统允许你创建构成客户端行为。

二、使用

  1. 依赖

    • >=PHP 5.5.0
    • php.ini文件设置allow_url_fopen = On
    • cURL >= 7.19.4(可选)
    • openssl和zlib扩展(没有此扩展,使用composer安装guzzle的时候也会报错)
  2. 安装 composer require guzzlehttp/guzzle:~6.0,6.0版本要求php7.1以上

  3. 使用


PHPUnit

一、概念

      PHPUnit是用于PHP编程语言的单元测试框架。它是xUnit体系结构的一个实例,用于单元测试框架,该框架起源于SUnit并在JUnit中流行。PHPUnit由Sebastian Bergmann创建,其开发托管在GitHub上。

作用

  • 通过命令操控测试脚本
  • 测试性能
  • 测试代码覆盖率
  • 自动化的更新测试用例的参数数据
  • 各种格式的日志

使用规则

  • 一般被测试类的后面加上”Test”,比如要测试的类为Array,则测试用例的命名为ArrayTest。
  • 测试类ArrayTest继承于PHPUnit_Framework_TestCase
  • 测试方法必须为public权限,都是test开头,或者你也可以选择给其加注释@test来表明该函数为测试函数
  • 通过断言方法来对实际值和预期值进行断言,断言方法可以参照手册

二、使用

  1. 通过归档文件安装

    • 下载归档文件 wget http://phar.phpunit.cn/phpunit.phar
    • 增加可执行权限 chmod +x phpunit.phar
    • 全局可执行 sudo mv phpunit.phar /usr/local/bin/phpunit
      • 若安装两个php版本,则修改/usr/local/bin/phpunit,修改可执行文件php路径 #!/usr/local/bin/php5.6
    • 测试安装是否成功 phpunit --version
      • 本地源码安装了两个版本的php,5.6和7.3,执行完以上步骤不顶球用,一执行就报错
    1
    2
    3
    4
    5
    PHP Fatal error:  Uncaught PharException: phar "/usr/local/bin/phpunit" has a broken signature in /usr/local/bin/phpunit:27
    Stack trace:
    #0 /usr/local/bin/phpunit(27): Phar::mapPhar('phpunit-6.5.3.p...')
    #1 {main}
    thrown in /usr/local/bin/phpunit on line 27
  2. 通过composer安装

    • 全局安装 composer global require phpunit/phpunit
    • 创建项目 mkdir test
    • 切换目录 cd test
    • 初始化 composer init
    • 引入文件 composer require --dev phpunit/phpunit
    • 新建测试文件夹 mkdir tests
    • 新建phpunit.xml为了引入autoload.php
1
2
3
4
5
6
7
<phpunit bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="service">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
  • 新建测试脚本EqualsTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

use PHPUnit\Framework\TestCase;

class EqualsTest extends TestCase {
public function testFailure()
{
$this->assertEquals(1, 0);
}

public function testFailure2()
{
$this->assertEquals('bar', 'baz');
}

public function testFailure3()
{
$this->assertEquals("foo\nbar\nbaz\n", "foo\nbah\nbaz\n");
}
}
  • 执行 ../vendor/bin/phpunit EqualsTest.php
    • 通过归档文件安装时phpunit已建好,默认使用

三、参考

  1. 参考一
  2. 参考二
  3. 参考三

Workerman

一、概念

  1. Workerman是纯PHP开发框架,需要依赖很多额外的第三方PHP扩展来实现。它是一款开源高性能异步PHP socket即时通讯框架。支持高并发,超高稳定性,被广泛的用于手机app、移动通讯,微信小程序,手游服务端、网络游戏、PHP聊天室、硬件通讯、智能家居、车联网、物联网等领域的开发。支持TCP长连接,支持Websocket、HTTP等协议,支持自定义协议。拥有异步Mysql、异步Redis、异步Http、MQTT物联网客户端、异步消息队列等众多高性能组件。

二、使用

三、参考

  1. 参考一