下载安装

  1. download php
  2. 解压后,复制一份 php.ini-development 并改名为 php.ini
  3. 修改 php.ini 文件 extension_dir = "xxx\php\ext"
  4. 配置环境变量
  5. php --version

包管理器

Composer

  1. https://docs.phpcomposer.com/00-intro.html#Installation-Windows 下载安装
  2. composer --version

常见命令:
composer init 类似于 npm init
composer install
composer update

语言特点

  • 新建 test.php 文件
  • php test.php ```php <?php // 变量以 $ 符开头 // 常量需要使用 define 定义 define(“MIN_VALUE”, -99);

    // 数组 $collect = array(“Python”, “Golang”, “Java”); // 数组长度 echo count($collect) foreach($collect as $v) {

    1. echo $v . PHP_EOF;

    } // push pop array_pop($collect); array_push($collect, “Scala”);

  1. // hash table
  2. $dict = array("Gou" => "Dog", "Mao" => "Cat");
  3. // 新增
  4. $dict["Yu"] = "Fish";
  5. // 判断 key 是否存在
  6. echo array_key_exists("Yu", $dict) . PHP_EOL

foreach ($dict as $k => $v) { printf(“%s == %s\n”, $k, $v); }

  1. function __main() {
  2. print("Hello php")

} __main(); ?>

  1. 注: `$collect = array();`
  2. 1. 数组添加元素的方式 `$collect[] = "item"` 这种方式在其他语言中还没有见过
  3. <a name="qACJM"></a>
  4. ### Composer 自动加载
  5. 通过自动加载避免频繁的使用 includerequire
  6. 如何通过 namespace use 的方法进行引包?
  7. - 配置 composer.json `autoload` 参数
  8. - `composer dump-autoload` 生成对应的文件,打开 vendor 目录查看
  9. autoload 有几种不同的配置方式,如:files classmap psr-4<br />**推荐使用 psr-4 的方式**<br />**psr 类名必须与文件名一致**
  10. 配置方式:
  11. 1. 配置 composer.json
  12. ```json
  13. {
  14. "autoload": {
  15. "psr-4": {
  16. "App\\": "app/"
  17. }
  18. }
  19. }
  1. 配置完成执行 composer dump-autoload
  2. index.php 入口文件引入 autoload.php ```php <?php require_once “vendor/autoload.php”

function main() { echo “main task is running…” . PHP_EOL; }

main();

  1. 注:vendor 目录和 node_moudles 很相像
  2. <a name="pQjr1"></a>
  3. ### OOP
  4. 面向对象 demo
  5. ```php
  6. <?php
  7. class Animal {
  8. var $name;
  9. var $age;
  10. // 构造函数
  11. function __construct($name, $age) {
  12. $this->name = $name;
  13. $this->age = $age;
  14. }
  15. function showAnimalInfo() {
  16. echo "Name: " . $this->name . ", " . "Age: " . $this->age;
  17. }
  18. }

访问修饰

public 可以在任何地方被访问
protected 自身、子类、父类被访问
private 只能被定义的类类部被访问

注:这些修饰符可以同时修饰成员变量和方法。public 是默认的

接口

  1. <?php
  2. interface Animal {
  3. function run();
  4. function eat();
  5. }
  6. class Dog implements Animal {
  7. var $name;
  8. function run() {
  9. echo $name . "is running\n";
  10. }
  11. function eat() {
  12. echo $name . "is eating...\n";
  13. }
  14. }

常量(注意常量访问的方式)

  1. <?php
  2. class Settings {
  3. const IP = 127.0.0.1;
  4. const name = "node1";
  5. }
  6. // 注意常量的访问方式
  7. echo Settings::IP . PHP_EOL;

抽象类(只要有一个方法是抽象方法都要定义为抽象类)

  1. <?php
  2. abstract class AbstractClass
  3. {
  4. // 强制要求子类定义这些方法
  5. abstract protected function getValue();
  6. abstract protected function prefixValue($prefix);
  7. // 普通方法(非抽象方法)
  8. public function printOut() {
  9. print $this->getValue() . PHP_EOL;
  10. }
  11. }
  12. class ConcreteClass1 extends AbstractClass
  13. {
  14. protected function getValue() {
  15. return "ConcreteClass1";
  16. }
  17. public function prefixValue($prefix) {
  18. return "{$prefix}ConcreteClass1";
  19. }
  20. }

static final 关键字

static 静态变量可以不实例化被访问到。 self::static_var 注意静态变量的访问方式。实例化后可以通过静态方法去访问静态变量。 $this->static_var 是错误的写法…

  1. <?php
  2. class Foo {
  3. public static $my_static = 'foo';
  4. public function staticValue() {
  5. return self::$my_static;
  6. }
  7. }
  8. print Foo::$my_static . PHP_EOL;
  9. $foo = new Foo();
  10. print $foo->staticValue() . PHP_EOL

final 被 final 修饰的类无法被继承,被 final 修饰的方法无法被重写

调用父类的构造方法

  1. <?php
  2. class BaseClass {
  3. function __construct() {
  4. print "BaseClass 类中构造方法" . PHP_EOL;
  5. }
  6. }
  7. class SubClass extends BaseClass {
  8. function __construct() {
  9. parent::__construct(); // 子类构造方法不能自动调用父类的构造方法
  10. print "SubClass 类中构造方法" . PHP_EOL;
  11. }
  12. }
  13. class OtherSubClass extends BaseClass {
  14. // 继承 BaseClass 的构造方法
  15. }
  16. // 调用 BaseClass 构造方法
  17. $obj = new BaseClass();
  18. // 调用 BaseClass、SubClass 构造方法
  19. $obj = new SubClass();
  20. // 调用 BaseClass 构造方法
  21. $obj = new OtherSubClass();

Trait

阅读 参考资料
继承属于高耦合操作,带来的复杂度很高。trait 是一种低耦合的操作。
在 class 中 use 了某个 trait 就可以使用 trait 中的方法了

  1. <?php
  2. trait Log {
  3. function startLog() {
  4. echo "logging start...\n";
  5. }
  6. function endLog() {
  7. echo "logging end...\n";
  8. }
  9. }
  10. class Publish {
  11. use Log;
  12. function pub() {
  13. $this->startLog();
  14. echo "publishing something\n";
  15. $this->endLog();
  16. }
  17. }

注:

  1. 入 trait 也是为了 don’t repeat yourself。在继承的场景下可以考虑使用 trait。
  2. use 关键字可以理解为将 trait 实现的代码拷贝一份到引用该 trait 的类

trait 优先级: 如果在有 trait 又有继承的情况下,会出现方法覆盖的情况。
当前类 > trait > 父类
trait 的优先级是要高于父类的

注:尽量不要这样搞,让代码保持单一性

insteadof as
就是字面意思不要做过度解读

  1. <?php
  2. trait Log
  3. {
  4. public function parameterCheck($parameters)
  5. {
  6. echo __METHOD__ . ' parameter check' . $parameters . PHP_EOL;
  7. }
  8. public function startLog()
  9. {
  10. echo __METHOD__ . ' public function' . PHP_EOL;
  11. }
  12. }
  13. trait Check
  14. {
  15. public function parameterCheck($parameters)
  16. {
  17. echo __METHOD__ . ' parameter check' . $parameters . PHP_EOL;
  18. }
  19. public function startLog()
  20. {
  21. echo __METHOD__ . ' public function' . PHP_EOL;
  22. }
  23. }
  24. class Publish
  25. {
  26. use Check, Log {
  27. Check::parameterCheck insteadof Log;
  28. Log::startLog insteadof Check;
  29. Check::startLog as csl;
  30. }
  31. public function doPublish()
  32. {
  33. $this->startLog();
  34. $this->parameterCheck('params');
  35. $this->csl();
  36. }
  37. }
  38. $publish = new Publish();
  39. $publish->doPublish();

输出

  1. Log::startLog public function
  2. Check::parameterCheck parameter checkparams
  3. Check::startLog public function

生成器

与迭代器相比生成器最大的特点就是 lazy
php 生成器与 python 生成器差别不大

  1. <?php
  2. function myGenerator() {
  3. for ($i = 0; $i < 19; $i++) {
  4. yield $i;
  5. }
  6. }
  7. foreach (myGenerator() as $v) {
  8. echo $v . PHP_EOL;
  9. }

闭包

闭包提供了一个封闭的词法作用域。可以用闭包(写函数的方式)来模拟类
类其实也提供了一个封闭此法作用域

  1. <?php
  2. // php map 数组的方式
  3. // php 匿名函数的写法
  4. $ret = array_map(function($x) {
  5. return $x ** 2;
  6. }, [5, 6, 7]);
  7. print_r($ret);

use 关键字附加来自外部作用域的状态,这与 javascript,python 不同

  1. <?php
  2. // 这个闭包看起来比较怪异,注意 use 的使用
  3. function add($x) {
  4. return function($y) use ($x) {
  5. return $x + $y;
  6. };
  7. }
  8. echo add(1)(2);

闭包函数本质上是一个对象,具有 __invoke() bindTo() 方法

注: bindTo 暂时不知道有什么作用,先挖个坑

错误与异常

die() die("error exit") 推出程序
类似于 exit()

错误触发 trigger_error("异常退出")
类似于 raise Exception("xxx")

编写自己的错误处理函数,使其按格式输出错误信息

  1. <?php
  2. function handleError($errno, $errstr) {
  3. echo "Error: [$errno] $errstr \n";
  4. die();
  5. }
  6. // 设置错误处理函数
  7. set_error_handler("handleError",E_USER_WARNING);
  8. // 触发错误
  9. trigger_error("this is an error", E_USER_WARNING);

异常处理

  1. <?php
  2. // 直接抛异常
  3. // throw new Exception("");
  4. function checkNumber($age) {
  5. if ($age < 18) {
  6. throw new Exception("age must be greater than 18");
  7. }
  8. echo "you have done a great job" . PHP_EOL;
  9. }
  10. // 捕获异常的方式
  11. try {
  12. checkNumber(19);
  13. checkNumber(17)
  14. } catch (Exception $e) {
  15. echo "Fatal Exception: " . $e->getMessage() . " line: " . __LINE__ . PHP_EOL;
  16. }

异常处理很简单可以参考一下下面的参考资料
参考资料

魔术变量与魔术方法

魔术变量的值是预定义的,尝试打印出来观察一下

  1. <?php
  2. println(__LINE__);
  3. println(__DIR__);
  4. println(__FUNCTION__);
  5. println(__METHOD__);
  6. // println(__CLASS__);

魔术方法是类中的一些钩子函数(hook)
这里的魔术方法与 python 中的魔术方法类似

  1. __construct(),类的构造函数
  2. __destruct(),类的析构函数
  3. __call(),在对象中调用一个不可访问方法时调用
  4. __callStatic(),用静态方式中调用一个不可访问方法时调用
  5. __get(),获得一个类的成员变量时调用
  6. __set(),设置一个类的成员变量时调用
  7. __isset(),当对不可访问属性调用isset()或empty()时调用
  8. __unset(),当对不可访问属性调用unset()时被调用。
  9. __sleep(),执行serialize()时,先会调用这个函数
  10. __wakeup(),执行unserialize()时,先会调用这个函数
  11. __toString(),类被当成字符串时的回应方法
  12. __invoke(),调用函数的方式调用一个对象时的回应方法
  13. __set_state(),调用var_export()导出类时,此静态方法会被调用。
  14. __clone(),当对象复制完成时调用
  15. __autoload(),尝试加载未定义的类
  16. __debugInfo(),打印所需调试信息

阅读参考资料 参考资料

反射

instanceof 判断一个变量是否属于某个类

  1. <?php
  2. class MyClass {}
  3. class NotMyClass {}
  4. $a = new MyClass;
  5. var_dump($a instanceof MyClass);
  6. var_dump($a instanceof NotMyClass);

gettype($x) 获取一个变量的类型,类似 python type()

  1. is_array():检查变量是否是数组。
  2. is_double()、is_float()、is_real() (所有都是相同的函数):检查变量是否是浮点数。
  3. is_long()、is_int()、is_integer() (所有都是相同的函数):检查变量是否是整数。
  4. is_string():检查变量是否是字符串。
  5. is_bool():检查变量是否是布尔值。
  6. is_object():检查变量是否是一个对象。
  7. is_resource():检查变量是否是一个资源。
  8. is_null():检查变量是否是null
  9. is_scalar():检查该变量是否是标量,即,一个整数、布尔值、字符串或浮点数。
  10. is_numeric():检查该变量是否是任何类型的数字或数字字符串。
  11. is_callable():检查该变量是否是有效的函数名称。

反射获取类的信息

函数传参的问题

参考资料
php 这个传参还是需要在阅读一下,在函数传参的时候可以声明类型,这个在动态语言中比较少见
function Foo(Log FileLog); 前面是类型
在动态语言中一般会是 Duck Type 类型,但是这种声明了类型的还是要按照设计模式那一套规则来。依赖倒置,面向抽象不面向具体