# PhpNote **Repository Path**: yanpingdong/php-note ## Basic Information - **Project Name**: PhpNote - **Description**: php使用笔记,不包括一些基础语法 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-08-05 - **Last Updated**: 2021-09-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PHP简介 PHP(全称:PHP:Hypertext Preprocessor,即"PHP:超文本预处理器")是一种通用开源脚本语言。 - PHP 文件可包含文本、HTML、JavaScript代码和 PHP 代码 - PHP 代码在服务器上执行,结果以纯 HTML 形式返回给浏览器,也可以返回JSON、String、Xml等格式数据。 - PHP 没有声明变量的命令。是一门弱类型语言,会根据变量的值,自动把变量转换为正确的数据类型。 - PHP 不支持多继承可以实现多个接口。接口、抽象类、类的声明比较像java, static与finnal关键字也基本一致 - 类只能有一个构造方法! *由于PHP是弱类型语言,因此函数的输入参数类型无法确定(可以使用类型暗示,但是类型暗示无法用在诸如整型,字符串之类的标量类型上),并且对于一个函数,比如只定义了3个输入参数,PHP却运行调用的时候输入4个或者更多的参数。因此基于这2点,注定了PHP中无法重载函数,(类似Javascript语言),也无法有构造函数的重载。* - 基本数据类型:String(字符串), Integer(整型), Float(浮点型), Boolean(布尔型), Array(数组), Object(对象), NULL(空值)。 - 全局常量是通过函数定义的:bool define ( string $name , mixed $value [, bool $case_insensitive = false ] ) - 关联数组可以当Map来用:$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43"); $age['Peter'] - PHP超级全局变量,是PHP系统中自带的变量,在一个脚本的全部作用域中都可用。$GLOBALS $_SERVER $_REQUEST $_POST $_GET $_FILES $_ENV $_COOKIE $_SESSION - PHP魔术常量,PHP的预定义常量。八个魔术常量它们的值随着它们在代码中的位置改变而改变:`__LINE__` `__FILE__` `__DIR__` `__FUNCTION__` `__CLASS__` `__TRAIT__` `__METHOD__` `__NAMESPACE__` ``` PHP 将所有全局变量存储在一个名为 $GLOBALS[index] 的数组中。 index 保存变量的名称 ``` # [Composer](./composer/README.md) Composer安装(依赖理器,当成maven/gradle的依赖管理部分): ``` php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" php composer-setup.php php -r "unlink('composer-setup.php');" 上述 3 条命令的作用依次是: 下载安装脚本 - composer-setup.php - 到当前目录。 执行安装过程。 删除安装脚本。 ref:https://pkg.phpcomposer.com/#how-to-install-composer ``` # VScode环境搭建 目前只使用的下面两个插件 ![](./pic/vscode-php-plugin.png) 安装好后,需要ctrl+shifi+p查询settings.json,配置如下参数 ```json { "php.executablePath": "/usr/bin/php", "phpcs.executablePath":"/usr/bin/php", "php.validate.executablePath": "/usr/bin/php", "explorer.confirmDelete": false, "tabnine.experimentalAutoImports": true, "php.suggest.basic": false, "php.validate.enable": false, "emmet.excludeLanguages": [ "markdown", "php" ] } ``` # PHP debug 通过xdebug 安装完成后,在php配置目录配置,Ubuntu下在/etc/php/7.4/mods-available,有个独立的xdebug.ini文件可以配置。 Xdebug v2.x.x ``` /etc/php/7.4/mods-available$ more xdebug.ini zend_extension=xdebug.so xdebug.remote_port=9080 xdebug.show_error_trace = 1 ;指定Xdebug扩展文件的绝对路径 ;启用性能检测分析 xdebug.profiler_enable=On ;启用代码自动跟踪 xdebug.auto_trace=on ;允许收集传递给函数的参数变量 xdebug.collect_params=On ;允许收集函数调用的返回值 xdebug.collect_return=On xdebug.remote_enable = On xdebug.remote_handler = dbgp xdebug.remote_host = localhost ;这句一定不能少,要不让不会启动断点调试 xdebug.remote_autostart= 1 ``` Xdebug v3.x.x ``` xdebug.mode = debug xdebug.start_with_request = yes ``` 配置完成后你可以理解成服务端已经就绪,现在你的代码通过apache2启动后会在localhost:9080开启一个调试服务器,你现在需要一个客户端连接上去,获取到代码运行数据。以VScode为例,我们需要在VSCode上安装xcode debug的客户端。如下图所示 ![](./pic/php-debug.png) 然后快捷键ctrl+shift+p,搜索launch.json ```json { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Listen for Xdebug", "type": "php", "request": "launch", //这儿要和你的php xdebug配置一致 "port": 9080 }, { "name": "Launch currently open script", "type": "php", "request": "launch", "program": "${file}", "cwd": "${fileDirname}", "port": 9001, "runtimeArgs": [ "-dxdebug.start_with_request=yes" ], "env": { "XDEBUG_MODE": "debug,develop", "XDEBUG_CONFIG": "client_port=${port}" } }, { "name": "Launch Built-in web server", "type": "php", "request": "launch", "runtimeArgs": [ "-dxdebug.mode=debug", "-dxdebug.start_with_request=yes", "-S", "localhost:0" ], "program": "", "cwd": "${workspaceRoot}", "port": 9003, "serverReadyAction": { "pattern": "Development Server \\(http://localhost:([0-9]+)\\) started", "uriFormat": "http://localhost:%s", "action": "openExternally" } } ] } ``` 然后给代码打断点,启动xdebug断点调试,浏览器调用。 ![](./pic/xdebug-demo.png) 浏览器调用也可以使用命令行调用替换。比如你有个test.php,可以直接使用php test.php。如下图所示 ![](./pic/xdebug-cml-demo.png) # PHP 包含文件 可以在服务器执行 PHP 文件之前在该文件中插入另一个文件的内容。 include 和 require 除了处理错误的方式不同之外,在其他方面都是相同的: - require 生成一个致命错误(E_COMPILE_ERROR),在错误发生后脚本会停止执行。 - include 生成一个警告(E_WARNING),在错误发生后脚本会继续执行。 因此,如果您希望继续执行,并向用户输出结果,即使包含文件已丢失,那么请使用 include。否则,在框架、CMS 或者复杂的 PHP 应用程序编程中,请始终使用 require 向执行流引用关键文件。 假设我们有一个定义变量的包含文件("vars.php"): ```php ```php 这些变量可用在调用文件中: ```php ``` # [为什么有的php脚本没有?>](./withoutEndFlag/README.md) 加与不加,视情况而定。先定义一下两者的区别。 加结尾的:之后的内容视为 纯文本直接输出,直到再次碰到 wang(); echo "in rock \n"; } static public function demo($a, $b) { echo "in static demo \n"; echo $a + $b . "\n"; } public function show($a, $b) { echo $a + $b . "\n"; } } $dog = new Dog; $dog->rock(); //类方法调用,一般用前三种方式 call_user_func([$dog,"wang"]); //用call_user_func调用类里面的方法 call_user_func([new Dog, 'wang']); call_user_func_array([new Dog, 'wang'], []); call_user_func(["Dog", 'wang']); call_user_func_array(["Dog", 'wang'], []); // 类静态方法调用 ,一般不用后面两个 call_user_func('Dog::demo', 1, 2); // 3 call_user_func_array('Dog::demo', [1, 2]); // 3 call_user_func([new Dog, 'demo'], 1, 2); call_user_func_array([new Dog, 'demo'], [1, 2]); // 调用匿名函数 call_user_func(function($a, $b){ echo $a + $b . "\n";}, 1, 2); // 3 call_user_func_array(function($a, $b){ echo $a + $b . "\n";}, [1, 2]); // 3 ``` 二者皆可调用自定义函数、匿名函数、系统函数以及类中的静态动态方法。如在thinkPHP中运用Facade门面类作为静态代理类,使用静态方式调用动态类中的动态方法,即让类无需实例化而直接进行静态方式的调用。 ```php //think\Facade类的最后有具体体现: public static function __callStatic($method, $params) { //static::createFacade()示例化对象;$method对象种的方法;$params给方法传递的参数 return call_user_func_array([static::createFacade(), $method], $params); } ``` # [reflection closure](./reflection/README.md) php反射和闭包的用法 # [ThinkPHP](./ThinkPHP/README.md) 免费开源、轻量级、简单快速搭建WEB应用的PHP框架,并且可以商用。 # 如何处理配置信息 单独的一个文件种以关联数组的方式设置配置,然后在使用的地方使用include/require应用。如下方式: ```php //config.php 'SomeRandomString', 'app_secret' => 'SomeRandomString', ]; // other-file.php "; echo '$name为'.$name."
"; print_r ($arguments); } } (new A)->test("test","argument"); ?> ``` 因此只需要利用该魔术方法既可以实现函数重载。比如有个f方法,我们不实现,调用的时候触发__call方法来间接实现 ```php "; } function f2($a1,$a2) { echo "2个参数".$a1.",".$a2."
"; } function f3($a1,$a2,$a3) { echo "3个参数".$a1.",".$a2.",".$a3."
"; } } (new A)->f('a'); (new A)->f('a','b'); (new A)->f('a','b','c'); ?> ``` 同样的在PHP中,实现构造函数的重载,也只能变通的实现。实现的关键要素是获取输入参数,并且根据输入参数判断调用哪个方法。下面是一个示例代码: ```php "; $a = func_get_args(); //获取构造函数中的参数 $i = count($a); if (method_exists($this,$f='__construct'.$i)) { call_user_func_array(array($this,$f),$a); } } function __construct1($a1) { echo "1个参数".$a1."
"; } function __construct2($a1,$a2) { echo "2个参数".$a1.",".$a2."
"; } function __construct3($a1,$a2,$a3) { echo "3个参数".$a1.",".$a2.",".$a3."
"; } } $o = new A('a'); $o = new A('a','b'); $o = new A('a','b','c'); ?> ```