下载安装
- download php
- 解压后,复制一份 php.ini-development 并改名为 php.ini
- 修改 php.ini 文件
extension_dir = "xxx\php\ext" - 配置环境变量
php --version
包管理器
Composer
- https://docs.phpcomposer.com/00-intro.html#Installation-Windows 下载安装
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) {
echo $v . PHP_EOF;
} // push pop array_pop($collect); array_push($collect, “Scala”);
// hash table$dict = array("Gou" => "Dog", "Mao" => "Cat");// 新增$dict["Yu"] = "Fish";// 判断 key 是否存在echo array_key_exists("Yu", $dict) . PHP_EOL
foreach ($dict as $k => $v) { printf(“%s == %s\n”, $k, $v); }
function __main() {print("Hello php")
} __main(); ?>
注: `$collect = array();`1. 数组添加元素的方式 `$collect[] = "item"` 这种方式在其他语言中还没有见过<a name="qACJM"></a>### Composer 自动加载通过自动加载避免频繁的使用 include、require如何通过 namespace 与 use 的方法进行引包?- 配置 composer.json `autoload` 参数- `composer dump-autoload` 生成对应的文件,打开 vendor 目录查看autoload 有几种不同的配置方式,如:files classmap psr-4<br />**推荐使用 psr-4 的方式**<br />**psr 类名必须与文件名一致**配置方式:1. 配置 composer.json```json{"autoload": {"psr-4": {"App\\": "app/"}}}
- 配置完成执行
composer dump-autoload - index.php 入口文件引入 autoload.php ```php <?php require_once “vendor/autoload.php”
function main() { echo “main task is running…” . PHP_EOL; }
main();
注:vendor 目录和 node_moudles 很相像<a name="pQjr1"></a>### OOP面向对象 demo```php<?phpclass Animal {var $name;var $age;// 构造函数function __construct($name, $age) {$this->name = $name;$this->age = $age;}function showAnimalInfo() {echo "Name: " . $this->name . ", " . "Age: " . $this->age;}}
访问修饰
| public | 可以在任何地方被访问 |
|---|---|
| protected | 自身、子类、父类被访问 |
| private | 只能被定义的类类部被访问 |
注:这些修饰符可以同时修饰成员变量和方法。public 是默认的
接口
<?phpinterface Animal {function run();function eat();}class Dog implements Animal {var $name;function run() {echo $name . "is running\n";}function eat() {echo $name . "is eating...\n";}}
常量(注意常量访问的方式)
<?phpclass Settings {const IP = 127.0.0.1;const name = "node1";}// 注意常量的访问方式echo Settings::IP . PHP_EOL;
抽象类(只要有一个方法是抽象方法都要定义为抽象类)
<?phpabstract class AbstractClass{// 强制要求子类定义这些方法abstract protected function getValue();abstract protected function prefixValue($prefix);// 普通方法(非抽象方法)public function printOut() {print $this->getValue() . PHP_EOL;}}class ConcreteClass1 extends AbstractClass{protected function getValue() {return "ConcreteClass1";}public function prefixValue($prefix) {return "{$prefix}ConcreteClass1";}}
static final 关键字
static 静态变量可以不实例化被访问到。 self::static_var 注意静态变量的访问方式。实例化后可以通过静态方法去访问静态变量。 $this->static_var 是错误的写法…
<?phpclass Foo {public static $my_static = 'foo';public function staticValue() {return self::$my_static;}}print Foo::$my_static . PHP_EOL;$foo = new Foo();print $foo->staticValue() . PHP_EOL
final 被 final 修饰的类无法被继承,被 final 修饰的方法无法被重写
调用父类的构造方法
<?phpclass BaseClass {function __construct() {print "BaseClass 类中构造方法" . PHP_EOL;}}class SubClass extends BaseClass {function __construct() {parent::__construct(); // 子类构造方法不能自动调用父类的构造方法print "SubClass 类中构造方法" . PHP_EOL;}}class OtherSubClass extends BaseClass {// 继承 BaseClass 的构造方法}// 调用 BaseClass 构造方法$obj = new BaseClass();// 调用 BaseClass、SubClass 构造方法$obj = new SubClass();// 调用 BaseClass 构造方法$obj = new OtherSubClass();
Trait
阅读 参考资料
继承属于高耦合操作,带来的复杂度很高。trait 是一种低耦合的操作。
在 class 中 use 了某个 trait 就可以使用 trait 中的方法了
<?phptrait Log {function startLog() {echo "logging start...\n";}function endLog() {echo "logging end...\n";}}class Publish {use Log;function pub() {$this->startLog();echo "publishing something\n";$this->endLog();}}
注:
- 入 trait 也是为了 don’t repeat yourself。在继承的场景下可以考虑使用 trait。
- use 关键字可以理解为将 trait 实现的代码拷贝一份到引用该 trait 的类
trait 优先级: 如果在有 trait 又有继承的情况下,会出现方法覆盖的情况。当前类 > trait > 父类
trait 的优先级是要高于父类的
注:尽量不要这样搞,让代码保持单一性
insteadof as
就是字面意思不要做过度解读
<?phptrait Log{public function parameterCheck($parameters){echo __METHOD__ . ' parameter check' . $parameters . PHP_EOL;}public function startLog(){echo __METHOD__ . ' public function' . PHP_EOL;}}trait Check{public function parameterCheck($parameters){echo __METHOD__ . ' parameter check' . $parameters . PHP_EOL;}public function startLog(){echo __METHOD__ . ' public function' . PHP_EOL;}}class Publish{use Check, Log {Check::parameterCheck insteadof Log;Log::startLog insteadof Check;Check::startLog as csl;}public function doPublish(){$this->startLog();$this->parameterCheck('params');$this->csl();}}$publish = new Publish();$publish->doPublish();
输出
Log::startLog public functionCheck::parameterCheck parameter checkparamsCheck::startLog public function
生成器
与迭代器相比生成器最大的特点就是 lazy
php 生成器与 python 生成器差别不大
<?phpfunction myGenerator() {for ($i = 0; $i < 19; $i++) {yield $i;}}foreach (myGenerator() as $v) {echo $v . PHP_EOL;}
闭包
闭包提供了一个封闭的词法作用域。可以用闭包(写函数的方式)来模拟类
类其实也提供了一个封闭此法作用域
<?php// php map 数组的方式// php 匿名函数的写法$ret = array_map(function($x) {return $x ** 2;}, [5, 6, 7]);print_r($ret);
use 关键字附加来自外部作用域的状态,这与 javascript,python 不同
<?php// 这个闭包看起来比较怪异,注意 use 的使用function add($x) {return function($y) use ($x) {return $x + $y;};}echo add(1)(2);
闭包函数本质上是一个对象,具有 __invoke() bindTo() 方法
注: bindTo 暂时不知道有什么作用,先挖个坑
错误与异常
die() die("error exit") 推出程序
类似于 exit()
错误触发 trigger_error("异常退出")
类似于 raise Exception("xxx")
编写自己的错误处理函数,使其按格式输出错误信息
<?phpfunction handleError($errno, $errstr) {echo "Error: [$errno] $errstr \n";die();}// 设置错误处理函数set_error_handler("handleError",E_USER_WARNING);// 触发错误trigger_error("this is an error", E_USER_WARNING);
异常处理
<?php// 直接抛异常// throw new Exception("");function checkNumber($age) {if ($age < 18) {throw new Exception("age must be greater than 18");}echo "you have done a great job" . PHP_EOL;}// 捕获异常的方式try {checkNumber(19);checkNumber(17)} catch (Exception $e) {echo "Fatal Exception: " . $e->getMessage() . " line: " . __LINE__ . PHP_EOL;}
异常处理很简单可以参考一下下面的参考资料
参考资料
魔术变量与魔术方法
魔术变量的值是预定义的,尝试打印出来观察一下
<?phpprintln(__LINE__);println(__DIR__);println(__FUNCTION__);println(__METHOD__);// println(__CLASS__);
魔术方法是类中的一些钩子函数(hook)
这里的魔术方法与 python 中的魔术方法类似
__construct(),类的构造函数__destruct(),类的析构函数__call(),在对象中调用一个不可访问方法时调用__callStatic(),用静态方式中调用一个不可访问方法时调用__get(),获得一个类的成员变量时调用__set(),设置一个类的成员变量时调用__isset(),当对不可访问属性调用isset()或empty()时调用__unset(),当对不可访问属性调用unset()时被调用。__sleep(),执行serialize()时,先会调用这个函数__wakeup(),执行unserialize()时,先会调用这个函数__toString(),类被当成字符串时的回应方法__invoke(),调用函数的方式调用一个对象时的回应方法__set_state(),调用var_export()导出类时,此静态方法会被调用。__clone(),当对象复制完成时调用__autoload(),尝试加载未定义的类__debugInfo(),打印所需调试信息
阅读参考资料 参考资料
反射
instanceof 判断一个变量是否属于某个类
<?phpclass MyClass {}class NotMyClass {}$a = new MyClass;var_dump($a instanceof MyClass);var_dump($a instanceof NotMyClass);
gettype($x) 获取一个变量的类型,类似 python type()
is_array():检查变量是否是数组。is_double()、is_float()、is_real() (所有都是相同的函数):检查变量是否是浮点数。is_long()、is_int()、is_integer() (所有都是相同的函数):检查变量是否是整数。is_string():检查变量是否是字符串。is_bool():检查变量是否是布尔值。is_object():检查变量是否是一个对象。is_resource():检查变量是否是一个资源。is_null():检查变量是否是null。is_scalar():检查该变量是否是标量,即,一个整数、布尔值、字符串或浮点数。is_numeric():检查该变量是否是任何类型的数字或数字字符串。is_callable():检查该变量是否是有效的函数名称。
反射获取类的信息
函数传参的问题
参考资料
php 这个传参还是需要在阅读一下,在函数传参的时候可以声明类型,这个在动态语言中比较少见function Foo(Log FileLog); 前面是类型
在动态语言中一般会是 Duck Type 类型,但是这种声明了类型的还是要按照设计模式那一套规则来。依赖倒置,面向抽象不面向具体
