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種方法
一、從新安裝PHP (不推薦)
二、使用PHP官方提供的工具phpize來添加 (添加)
  • 使用phpize來生成其餘擴展.so文件
phpize工具所在位置:php安裝目錄/bin/phpize
所需依賴:autoconf工具 yum install autoconf
步驟:
一、cd /php源碼目錄/ext
二、找到所需安裝擴展庫,而後cd進入  //例如: cd curl
三、php安裝目錄/bin/phpize   //生成configure文件
四、./configure --with-php-config=/usr/local/php/bin/php-config  //生成Makefile
五、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種
一、 引用返回方式(定義函數時, 前面需加&,不然函數調用時只會 普通返回
<?php
    function &test(){
        static $b = 0;  //聲明一個靜態變量
        $b = $b+1;
        return $b;
    }
    
    $a = test();   //輸出 $b 的值爲:1
    $a = 5;
    $a = test();     //輸出 $b 的值爲:2
   
    $a = &test();  //輸出 $b 的值爲:3  **注意**
    $a = 5;           //$b的值變爲了5
    $a = test();    //輸出 $b 的值爲:6  **注意**
?>
二、 普通返回方式(在調用函數前不能使用 &符號,不然會報錯)
<?php
    function test(){
        static $b = 0;  //聲明一個靜態變量
        $b = $b+1;
        return $b;
    }
    
    $a = test();   //輸出 $b 的值爲:1
    $a = 5;
    $a = test();     //輸出 $b 的值爲:2
   
    $a = &test();  //輸出 $b 的值爲:3  **報錯,不能這樣使用**
?>
  • 注意事項
一、若是定義函數時,前面加&的話,函數調用可使用 引用返回普通返回
二、若是定義函數時,前面不加&的話,函數調用能夠只可以使用 普通返回

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
  • 遠程調試
一、要檢查防火牆是否已經關閉
二、若是你的項目所在環境是外網,就是IDE所在PC與項目部署環境不能經過IP直接訪問,則遠程斷點方式不能使用。(必須使用域名)

面向對象中 static與self的區別

  • self非動態的,在哪一個類中存在,self就表明哪一個類
  • static是動態的,根據具體哪一個類調用,static指向那個類

static與self的區別php

PHP 自動加載機制是什麼?

在作項目時,咱們常常遇到要用到不少類(有些是本身寫的,有些是第三方類庫的),
使用前必須先加載(include/require),但若是所有本身手動加載,那麼將很吃力不討好:

一、代碼量巨大,很差維護,浪費時間
二、沒法作到按需加載,運行性能低下
三、還有可能形成重複加載統一類

因此,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()函數html

## 一、註冊函數
function my_autoloader($class) {
    include 'classes/' . $class . '.class.php';
}
spl_autoload_register('my_autoloader');

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

## 三、註冊類靜態方法 -- 自 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');

## 四、在類方法中調用,註冊類靜態方法
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 自動加載機制chrome

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'));
相關文章
相關標籤/搜索