PHP Q&A

PHP 有哪些作用域?

  • 函数作用域
  • 类作用域

PHP 函数作用域是什么?

  • 函数体是一个局部作用域
  • 函数体中无法直接访问外部全局变量,必须通过global/$GLOBALS才能访问外部全局变量
$var = 'aa';
function showVar(){
    echo $var; //无法访问
}
showVar(); //Notice通知错误

//正确访问外部全局变量
$var = 'aa';
function showVar(){
    echo $GLOBALS['var']; //无法访问
}
showVar();
  • 函数体中可以直接访问常量
define('BBO','wutao');
function showVar(){
    echo BBO;
}
showVar();//输出‘wutao’
  • 函数体中可以直接访问(静态属性、静态方法)和对象(属性、方法)
function showVar(){
    $person = new Person();
    $person->getName();
    Person::getAge();
}

class Person{
    private $name = '不懂撒的';
    public static $age = 200;
        
    public function getName(){
        echo $this->name;
    }
        
    public static function getAge(){
        echo self::$age;
    }
}
    
showVar();

类作用域是什么?有什么注意事项?

  • 类其实就是一个完整且独立的个体,外部(变量与函数)可以直接使用它
//定义一个Person类
class Person{

};
外部变量直接访问类中静态方法/属性与实例化
$var = new Person();
$var1 = Person::test();
//函数内部也是直接访问类中静态方法/属性并使用
function demo(){
    $var1 = Person::test();
    $var = new Person();
}
  • 在类中,方法可以直接调用外部函数或其他类,但不可以直接访问外部变量,外部常量(超全局常量)可以任何地方访问
  • 在类中,属性可以直接访问外部常量(超全局常量),但外部函数、外部变量,其他类就无法访问
$var = '121';
function fn(){}
class Student{}
define('CONF','121');

class Person{
    public $one = new Student(); //不正确,无法访问
    public $two = fn(); //不正确,无法访问
    public $three = $var; //不正确,无法访问
    public $four = CONF; //正确,可以访问
}

PHP 常量有哪些?各自有什么特点?常量取值类型有哪几种?

  • 超全局常量系统内置超全局变量/常量用法一样
//定义超全局常量,无论在函数,方法,还是外部定义,只要定义,此常量都是超全局常量,哪都可以直接使用
define('BOSS','wt'); 

function showVar(){    
    echo BOSS;
    $person = new Person();
    $person->getName();
    Person::getAge();
}

class Person{
    private $name = BOSS;   //wt
    public static $age = BOSS;   //wt
        
    public function getName(){
        echo BOSS;   //wt
        echo $this->name;  //wt
    }
        
    public static function getAge(){
        echo self::$age;  //wt
        echo BOSS;        //wt
    }
}
    
showVar();
  • 类中常量
function showVar(){
    $person = new Person();
    $person->getName();
    Person::getAge();
    echo Person::BMM;   //外部调用类常量
}

class Person{
    const BMM = 'xiaomi';
    private $name = self::BMM;  //输出xiaomi
    public static $age = self::BMM;  //输出xiaomi
        
    public function getName(){
        echo $this->name;  //输出xiaomi
    }
        
    public static function getAge(){
        echo self::BMM;  //内部调用类常量
        echo self::$age;  //输出xiaomi
    }
}
    
showVar();
  • 常量类型
    boolean/integer/float/string 四种类型之一,不能是其他类型

PHP 变量种类有哪些?各自有什么特点

  • 外部全局变量 $var = 'string'; 除4种基本类型,还可以数组/对象/null数据类型;
    外部全局变量的特点:函数中要用过global/$GLOBALS才能访问到外部全局变量(一般不推荐这样使用),类中(方法和属性)都无法直接访问外部全局变量
  • 静态变量 在函数中定义的一种变量; static $a = 0;
    静态变量的特点:在一次请求响应中,无论函数调用多少次,静态变量的初始化只会执行一次
  • 局部变量 在函数中定义的一种变量; $a = 0;
    局部变量的特点:只在定义的函数中有效,函数执行完,局部变量就会释放,所以外部无法访问局部变量

纯净手工编译版PHP如何增加其他扩展类库?

  • 由于PHP是手工编译最简化安装,所以只包含一些基本扩展,其他大部分扩展都没有,后期才按需添加
  • 加入其他扩展,有2种方法
1、重新安装PHP (不推荐)
2、使用PHP官方提供的工具phpize来添加 (添加)
  • 使用phpize来生成其他扩展.so文件
phpize工具所在位置:php安装目录/bin/phpize
所需依赖:autoconf工具 yum install autoconf
步骤:
1、cd /php源码目录/ext
2、找到所需安装扩展库,然后cd进入  //例如: cd curl
3、php安装目录/bin/phpize   //生成configure文件
4、./configure --with-php-config=/usr/local/php/bin/php-config  //生成Makefile
5、make && make install

## 最终.so安装位置在php/bin/php-config中已经指定
  • php.ini配置文件中加入extension=curl.so
注意:如果想按上面配置,必须在php.ini中配置 extension_dir="/usr/local/php/ext"

PHP 如何使用函数更健壮呢?

function_exists('ini_set') && ini_set('memory_limit', '1024M');

PHP 如何定义常量更健壮呢?

defined("GREETING") || define("GREETING","Hello world!");

函数定义时,前面加&代表什么?加与不加&有什么区别?

  • 前置知识
$a = 55;
$b = &$a; //引用变量 $b为55
$b = 100; //$b为100 $a为100
  • 函数的返回方式有2种
1、 引用返回方式(定义函数时, 前面需加&,否则函数调用时只会 普通返回
2、 普通返回方式(在调用函数前不能使用 &符号,否则会报错)
  • 注意事项
1、如果定义函数时,前面加&的话,函数调用可以使用 引用返回普通返回
2、如果定义函数时,前面不加&的话,函数调用可以只可使用 普通返回

URL 如何变得更加优美?

  • 原始URL ———— 查询字符串
http://www.test.com/index.php?key=val
参数可以使用 $_GET['key'] 获取,但这样的 URL 很不美观
  • 初步优化 ———— 使用PATHINFO模式
http://www.test.com/index.php/key/val
使用 PATHINFO 模式的 URL ,参数的获取就不可以使用 $_GET['key'] 获取了。

必须使用 $_SERVER['PATH_INFO'] 获取
  • 进一步优化 ———— 隐藏入口文件index.php
http://www.test.com/key/val
要使用到服务器Apache/Nginx的URL重写功能
  • 最终优化 ———— 开发路由层(伪静态)
http://www.test.com/val.html
很多框架都有路由层,此路由优化后的 URL ,对 SEO 最为友好

如何使用 Xdebug 来调试 PHP 代码

  • 在 php.ini 进入如下配置
xdebug.profiler_output_dir="H:\install\phpStudy\tmp\xdebug"
xdebug.trace_output_dir="H:\install\phpStudy\tmp\xdebug"
zend_extension="H:\install\phpStudy\php\php-5.6.27-nts\ext\php_xdebug.dll"

xdebug.profiler_enable = 1
xdebug.auto_trace = 1
xdebug.show_exception_trace = 1
;这里必须设置为0,为了能使用浏览器插件 xdebug helper配合调试
xdebug.remote_autostart = 0
xdebug.remote_enable = 1
;这里是开启远程调试
xdebug.remote_handler = "dbgp"
;远程调试的host
xdebug.remote_host = "127.0.0.1"
;远程调试的端口号
xdebug.remote_port = 9000
;远程调试的对应 key
xdebug.idekey="PHPSTORM" 
  • 浏览器要安装对应的调试插件
chrome => xdebug helper
火狐 => Xdebug Helper
  • 远程调试
1、要检查防火墙是否已经关闭
2、如果你的项目所在环境是外网,就是IDE所在PC与项目部署环境不能通过IP直接访问,则远程断点方式不能使用。(必须使用域名)

面向对象中 static与self的区别

  • self非动态的,在哪个类中存在,self就代表哪个类
  • static是动态的,根据具体哪个类调用,static指向那个类

static与self的区别

PHP 自动加载机制是什么?

在做项目时,我们经常遇到要用到很多类(有些是自己写的,有些是第三方类库的),
使用前必须先加载(include/require),但如果全部自己手动加载,那么将很吃力不讨好:

1、代码量巨大,不好维护,浪费时间
2、无法做到按需加载,运行性能低下
3、还有可能造成重复加载统一类

所以,PHP5提出解决这一问题方法:自动加载机制
  • 第一代自动加载机制 autoload
function __autoload($classname) {
    require_once ($classname . “class.php”);
}

$person = new Person(”Altair”, 6);
var_dump ($person);
看出autoload至少要做三件事情,
第一件事是 根据类名确定类文件名
第二件事是 确定类文件所在的磁盘路径(在我们的例子是最简单的情况,类与调用它们的PHP程序文件在同一个文件夹下)
第三件事是 将类从磁盘文件中加载到系统中(第三步最简单,只需要使用include/require即可)
缺点就是:一般项目都是用到第三方类库,很多时候这种类名与与类文件所在的磁盘路径的映射规则与我们订的不同,如果全部写在一个__autoload()函数里会很臃肿,难维护,性能低等问题
  • 第二代自动加载机制 SPL autoload
PHP5提供的一个SPL扩展,其中提供的 自动加载机制用于 取代上面第一代自动加载机制

spl_autoload是SPL实现的默认的自动加载函数,它的功能比较简单。我们不能扩展spl_autoload()函数,
怎样让spl_autoload自动起作用呢?在PHP脚本中第一次调用spl_autoload_register()函数,无需传入任何参数,一般不会使用SPL扩展预先定义好的spl_autoload()函数

## 1、注册函数
function my_autoloader($class) {
    include 'classes/' . $class . '.class.php';
}
spl_autoload_register('my_autoloader');

## 2、自PHP 5.3.0起可以使用一个匿名函数
spl_autoload_register(function ($class) {
    include 'classes/' . $class . '.class.php';
});

## 3、注册类静态方法 -- 自 PHP 5.3.0 起
namespace Foobar;
class Foo {
    static public function test($className) {
        $className = str_replace("\\", DIRECTORY_SEPARATOR, $className);
    }
}
spl_autoload_register(__NAMESPACE__ .'\Foo::test');

## 4、在类方法中调用,注册类静态方法
namespace Foobar;
class Framework{
    public static function init() {
         require_once (__DIR__ . '/functions.php');
         // 自动加载设置
         spl_autoload_register('self::loadClass');
    }
    
    public static function loadClass($className) {
        $className = str_replace("\\", DIRECTORY_SEPARATOR, $className);
    }
}
如果 加载的类 是在某 命名空间内的话,自动加载函数接受到的$class变量将是 think\lib\Person
必须带上命名空间
  • 注意
如果同时定义__autoload()函数和spl_autoload_register()函数,那到底会怎样?
先spl_autoload_register()起效果,如果没有这个函数的话,那么再找__autoload()函数
同时注册多个autoload函数,该如何执行呢?
按顺序执行多个注册的autoload()函数,但只要执行了require/include之后,后面注册的函数就不会执行下去了

autoload()函数内返回return true/false都没有效果

PHP 自动加载机制

4种PHP回调函数风格是什么?

匿名函数回调
$server->on('Request', function ($req, $resp) {
    echo "hello world";
});
类静态方法回调
class A
{
    static function test($req, $resp)
    {
        echo "hello world";
    }
}
$server->on('Request', 'A::Test');
$server->on('Request', array('A', 'Test'));
函数回调
function my_onRequest($req, $resp)
{
    echo "hello world";
}
$server->on('Request', 'my_onRequest');
对象方法
class A
{
    function test($req, $resp)
    {
        echo "hello world";
    }
}

$object = new A();
$server->on('Request', array($object, 'test'));

你可能感兴趣的:(php)