1. 程式人生 > >php編程 之 php基礎三

php編程 之 php基礎三

php eol 參數 int() 規則 any 編程 art html

1,php裏的while循環

循環執行代碼塊指定的次數,或者當指定的條件為真時循環執行代碼塊。

while實例:

<html>
<body>

<?php
$i=1;
while($i<=5)    //註意,此處不支持簡寫。
{
    echo "The number is " . $i . "<br>";
    $i++;
}
?>

</body>
</html>

do ...while...實例:

do
{
    要執行的代碼;
}
while (條件);

2,for循環

語法:

for (初始值; 條件; 增量)
{
    要執行的代碼;
}

只循環數字:

<?php
for ($i=1; $i<=5; $i++)
{
    echo "The number is " . $i . "<br>";
}
?>

循環數組:

<?php
$x=array("one","two","three");
foreach ($x as $value)    //鍵值對的鍵是$x,值是$value
{
    echo $value . "<br>";
}
?>

3,函數

PHP 的真正威力源自於它的函數。在 PHP 中,提供了超過 1000 個內建的函數。

php內建函數手冊:http://www.runoob.com/php/php-ref-array.html

創建:

<?php
function functionName()    //名字最好具有提示性,函數名不能以數字開頭
{
    // 要執行的代碼
}
?>

帶參數:

<?php
function writeName($fname)
{
    echo $fname . “how are u?”;
}
 
writeName("Kai Jim");    //返回Kai Jim how are u?
?>

帶返回值的函數:

<?php
function add($x,$y)
{
    $total=$x+$y;
    return $total;   //return
}
 
echo "1 + 16 = " . add(1,16); ?>

4 魔術常量

PHP 向它運行的任何腳本提供了大量的預定義常量。不大好解釋,但是它們的數據類型是常量,但是具體值要看情況而定。

__LINE__:當前行的行號

<?php
echo ‘這是第 " ‘  . __LINE__ . ‘ " 行‘;    //返回2
?>

__FILE__:文件的完整路徑和文件名。如果用在被包含文件中,則返回被包含的文件名。

<?php
echo ‘該文件位於 " ‘  . __FILE__ . ‘ " ‘;
?>

__DIR__:文件所在的目錄。如果用在被包括文件中,則返回被包括的文件所在的目錄。等於dirname(__FILE__)

<?php
echo ‘該文件位於 " ‘  . __DIR__ . ‘ " ‘;    //返回"E:\wamp\www\test"
?>

__FUNCTION__:本常量返回該函數被定義時的名字(區分大小寫)

<?php
function test() {
    echo  ‘函數名為:‘ . __FUNCTION__ ;
}
test();
?>    //返回test

__CLASS__:返回該類再被定義時候的名字

<?php
class test {
    function _print() {
        echo ‘類名為:‘  . __CLASS__ . "<br>";    //返回test
        echo  ‘函數名為:‘ . __FUNCTION__ ;    //返回_print
    }
}
$t = new test();
$t->_print();
?>

__NAMESPACE__

當前命名空間的名稱(區分大小寫)。

<?php
namespace MyProject;
 
echo ‘命名空間為:"‘, __NAMESPACE__, ‘"‘; // 輸出 "MyProject"
?>

__METHOD__:類的方法名,返回該方法被定義時候的名字。

<?php
function test() {
    echo  ‘函數名為:‘ . __METHOD__ ;
}
test();
?>

__TRAIT__:Trait是為類似PHP的單繼承語言而準備的一種代碼復用機制。

php從以前到現在一直都是單繼承的語言,無法同時從兩個基類中繼承屬性和方法,為了解決這個問題,php出了Trait這個特性

用法:通過在類中使用use 關鍵字,聲明要組合的Trait名稱,具體的Trait的聲明使用Trait關鍵詞,Trait不能實例化

<?php
trait Dog{    //定義一個trait類,方法和class差不多,但是它不能被實例化
    public $name="dog";    //公有屬性是name
    public function bark(){    //公有方法
        echo "This is dog";
    }
}
class Animal{
    public function eat(){
        echo "This is animal eat";
    }
}
class Cat extends Animal{    //class 子類 extends 父類
    use Dog;    //trait類繼承的寫法,這樣Cat類也會繼承Dog類
    public function drive(){
        echo "This is cat drive";
    }
}
$cat = new Cat();    //實例化cat
$cat->drive();    //返回this is cat drive
echo "<br/>";
$cat->eat();    //返回this is animal eat
echo "<br/>";
$cat->bark();    //返回this is dog
?>

由於trait和class的多繼承有可能會造成父類子類屬性和方法的沖突,所以我們再來個例子看一下覆蓋問題:

<?php
class Base {    //基類,擁有sayHello方法
    public function sayHello() {
        echo ‘Hello ‘;
    }
}
 
trait SayWorld {    //trait類,也擁有sayhello方法
    public function sayHello() {
        parent::sayHello();    //parent::    的意思是調用父類但是不僅限於父類的方法,也就是會繼承上一個sayHello的方法,也就是print hello
        echo ‘World!‘;
    }
}
 
class MyHelloWorld extends Base {
    use SayWorld;    //繼承的是trait SayWorld
}
 
$o = new MyHelloWorld();
$o->sayHello();    //返回hello world !
?>

5 命名空間:

https://blog.csdn.net/ss22_xiha/article/details/52694279這個教程還不錯

感覺有點想python中的全局變量和局部變量。只不過明確地寫出來了而已。

PHP 命名空間可以解決以下兩類問題:

  1. 用戶編寫的代碼與PHP內部的類/函數/常量或第三方類/函數/常量之間的名字沖突。
  2. 為很長的標識符名稱(通常是為了緩解第一類問題而定義的)創建一個別名(或簡短)的名稱,提高源代碼的可讀性。

如何定義命名空間:

命名空間通過關鍵字namespace 來聲明。如果你想使用命名空間,它必須在其它所有代碼之前聲明命名空間。語法格式如下;

<?php    
//一個文件中擁有多個命名空間
//不加大括號也行,不過加上比較嚴謹

declare(encoding=‘UTF-8‘);

//在聲明命名空間之前唯一合法的代碼是用於定義源文件編碼方式的 declare 語句。所有非 PHP 代碼包括空白符都不能出現在命名空間的聲明之前。即使是<html>也不行。好霸道啊,不過對這一點還是感覺不是特別理解
namespace MyProject {
    //一堆代碼
}

namespace AnotherProject {
    //一堆代碼
}
?>
<?php
//全局代碼和命名空間的代碼寫在一塊
namespace MyProject {    //這個是命名空間
    //一堆代碼
}

namespace { // 這個是全局代碼,註意全局代碼的寫法,namespace關鍵字後面不加任何東西,然後大括號括起來
    //一堆代碼
}
?>

子命名空間:

與目錄和文件的關系很像,PHP 命名空間也允許指定層次化的命名空間的名稱。因此,命名空間的名字可以使用分層次的方式定義。

<?php
namespace MyProject\Sub\Level;  //聲明分層次的單個命名空間,是反斜杠哦:
//一堆代碼

?>

如何使用命名空間:

PHP 命名空間中的元素使用同樣的原理。例如,類名可以通過三種方式引用:
  1. 非限定名稱,或不包含前綴的類名稱,例如 $a=new foo();foo::staticmethod();。如果當前命名空間是currentnamespace,foo 將被解析為 currentnamespace\foo。如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,則 foo 會被解析為foo。 警告:如果命名空間中的函數或常量未定義,則該非限定的函數名稱或常量名稱會被解析為全局函數名稱或常量名稱。詳情參見 使用命名空間:後備全局函數名稱/常量名稱。
  2. 限定名稱,或包含前綴的名稱,例如 $a = new subnamespace\foo();subnamespace\foo::staticmethod();。如果當前的命名空間是 currentnamespace,則 foo 會被解析為 currentnamespace\subnamespace\foo。如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,foo 會被解析為subnamespace\foo
  3. 完全限定名稱,或包含了全局前綴操作符的名稱,例如, $a = new \currentnamespace\foo();\currentnamespace\foo::staticmethod();。在這種情況下,foo 總是被解析為代碼中的文字名(literal name)currentnamespace\foo

基本意思就是,如果你沒指定命名空間那就默認為當前的命名空間,全局的也是這樣的。為了防止和別的名稱空間裏的變量重名,你也可以指定命名空間的“相對路徑”或者“絕對路徑”

/* 非限定名稱 */
foo(); // 解析為函數 Foo\Bar\foo
foo::staticmethod(); // 解析為類 Foo\Bar\foo ,方法為 staticmethod,雙冒號表示調用某類下的方法
echo FOO; // 解析為常量 Foo\Bar\FOO

/* 限定名稱 */
subnamespace\foo(); // 解析為函數 Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // 解析為類 Foo\Bar\subnamespace\foo,
                                  // 以及類的方法 staticmethod
echo subnamespace\FOO; // 解析為常量 Foo\Bar\subnamespace\FOO
                                  
/* 完全限定名稱 */
\Foo\Bar\foo(); // 解析為函數 Foo\Bar\foo
\Foo\Bar\foo::staticmethod(); // 解析為類 Foo\Bar\foo, 以及類的方法 staticmethod
echo \Foo\Bar\FOO; // 解析為常量 Foo\Bar\FOO
命名空間的導入 允許通過別名引用或導入外部的完全限定名稱,是命名空間的一個重要特征。這有點類似於在類 unix 文件系統中可以創建對其它的文件或目錄的符號連接。 所有支持命名空間的PHP版本支持三種別名或導入方式:為類名稱使用別名、為接口使用別名或為命名空間名稱使用別名。PHP 5.6開始允許導入函數或常量或者為它們設置別名 __NAMESPACE__
常量__NAMESPACE__的值是包含當前命名空間名稱的字符串。在全局的,不包括在任何命名空間中的代碼,它包含一個空的字符串。
<?php
namespace MyProject;
echo ‘"‘, __NAMESPACE__, ‘"‘; // 輸出 "MyProject"
?>

關鍵字 namespace 可用來顯式訪問當前命名空間或子命名空間中的元素。

不是很懂,留後

使用名稱空間:

PHP 命名空間支持 有兩種使用別名或導入方式:為類名稱使用別名,或為命名空間名稱使用別名。

在PHP中,別名是通過操作符 use 來實現的. 下面是一個使用所有可能的三種導入方式的例子:

//使用use關鍵字導入,並且為這個名稱空間取個別名:
<?php
namespace foo;
use My\Full\Classname as Another;    //我要用xxx命名空間,別名是another

// 下面的例子與 use My\Full\NSname as NSname 相同
use My\Full\NSname;

// 導入一個全局類
use \ArrayObject;

$obj = new namespace\Another; // 實例化 foo\Another 對象
$obj = new Another; // 實例化 My\Full\Classname 對象
NSname\subns\func(); // 調用函數 My\Full\NSname\subns\func
$a = new ArrayObject(array(1)); // 實例化 ArrayObject 對象
// 如果不使用 "use \ArrayObject" ,則實例化一個 foo\ArrayObject 對象
?>

//一行多個use語句並列
<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 實例化 My\Full\Classname 對象
NSname\subns\func(); // 調用函數 My\Full\NSname\subns\func
?>

//用另一個動態名稱代替:
<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 實例化一個 My\Full\Classname 對象
$a = ‘Another‘;
$obj = new $a;      // 實際化一個 Another 對象
?>

使用命名空間的註意事項:

在訪問系統內部或不包含在命名空間中的類名稱時,必須使用完全限定名稱;

對於函數和常量來說,如果當前命名空間中不存在該函數或常量,PHP 會退而使用全局空間中的函數或常量;

全局空間:

如果沒有定義任何命名空間,所有的類與函數的定義都是在全局空間,我們在名稱前加上前綴 \ 表示該名稱是全局空間中的名稱

<?php
namespace A\B\C;
$f = \fopen(...); // 調用全局的fopen函數
     return $f;
?>

命名空間的順序:

//不說了,直接上實例
<?php
namespace A;
use B\D, C\E as F;

// 函數調用

foo();      // 首先嘗試調用定義在命名空間"A"中的函數foo()
            // 再嘗試調用全局函數 "foo"

\foo();     // 調用全局空間函數 "foo" 

my\foo();   // 調用定義在命名空間"A\my"中函數 "foo" 

F();        // 首先嘗試調用定義在命名空間"A"中的函數 "F" 
            // 再嘗試調用全局函數 "F"

// 類引用

new B();    // 創建命名空間 "A" 中定義的類 "B" 的一個對象
            // 如果未找到,則嘗試自動裝載類 "A\B"

new D();    // 使用導入規則,創建命名空間 "B" 中定義的類 "D" 的一個對象
            // 如果未找到,則嘗試自動裝載類 "B\D"

new F();    // 使用導入規則,創建命名空間 "C" 中定義的類 "E" 的一個對象
            // 如果未找到,則嘗試自動裝載類 "C\E"

new \B();   // 創建定義在全局空間中的類 "B" 的一個對象
            // 如果未發現,則嘗試自動裝載類 "B"

new \D();   // 創建定義在全局空間中的類 "D" 的一個對象
            // 如果未發現,則嘗試自動裝載類 "D"

new \F();   // 創建定義在全局空間中的類 "F" 的一個對象
            // 如果未發現,則嘗試自動裝載類 "F"

// 調用另一個命名空間中的靜態方法或命名空間函數

B\foo();    // 調用命名空間 "A\B" 中函數 "foo"

B::foo();   // 調用命名空間 "A" 中定義的類 "B" 的 "foo" 方法
            // 如果未找到類 "A\B" ,則嘗試自動裝載類 "A\B"

D::foo();   // 使用導入規則,調用命名空間 "B" 中定義的類 "D" 的 "foo" 方法
            // 如果類 "B\D" 未找到,則嘗試自動裝載類 "B\D"

\B\foo();   // 調用命名空間 "B" 中的函數 "foo" 

\B::foo();  // 調用全局空間中的類 "B" 的 "foo" 方法
            // 如果類 "B" 未找到,則嘗試自動裝載類 "B"

// 當前命名空間中的靜態方法或函數

A\B::foo();   // 調用命名空間 "A\A" 中定義的類 "B" 的 "foo" 方法
              // 如果類 "A\A\B" 未找到,則嘗試自動裝載類 "A\A\B"

\A\B::foo();  // 調用命名空間 "A" 中定義的類 "B" 的 "foo" 方法
              // 如果類 "A\B" 未找到,則嘗試自動裝載類 "A\B"
?>

6,面向對象

面向對象內容

  • ? 定義了一件事物的抽象特點。類的定義包含了數據的形式以及對數據的操作。

  • 對象 ? 是類的實例。

  • 成員變量 ? 定義在類內部的變量。該變量的值對外是不可見的,但是可以通過成員函數訪問,在類被實例化為對象後,該變量即可稱為對象的屬性。

  • 成員函數 ? 定義在類的內部,可用於訪問對象的數據。

  • 繼承 ? 繼承性是子類自動共享父類數據結構和方法的機制,這是類之間的一種關系。在定義和實現一個類的時候,可以在一個已經存在的類的基礎之上來進行,把這個已經存在的類所定義的內容作為自己的內容,並加入若幹新的內容。

  • 父類 ? 一個類被其他類繼承,可將該類稱為父類,或基類,或超類。

  • 子類 ? 一個類繼承其他類稱為子類,也可稱為派生類。

  • 多態 ? 多態性是指相同的函數或方法可作用於多種類型的對象上並獲得不同的結果。不同的對象,收到同一消息可以產生不同的結果,這種現象稱為多態性。

  • 重載 ? 簡單說,就是函數或者方法有同樣的名稱,但是參數列表不相同的情形,這樣的同名不同參數的函數或者方法之間,互相稱之為重載函數或者方法。

  • 抽象性 ? 抽象性是指將具有一致的數據結構(屬性)和行為(操作)的對象抽象成類。一個類就是這樣一種抽象,它反映了與應用有關的重要性質,而忽略其他一些無關內容。任何類的劃分都是主觀的,但必須與具體的應用有關。

  • 封裝 ? 封裝是指將現實世界中存在的某個客體的屬性與行為綁定在一起,並放置在一個邏輯單元內。

  • 構造函數 ? 主要用來在創建對象時初始化對象, 即為對象成員變量賦初始值,總與new運算符一起使用在創建對象的語句中。

  • 析構函數 ? 析構函數(destructor) 與構造函數相反,當對象結束其生命周期時(例如對象所在的函數已調用完畢),系統自動執行析構函數。析構函數往往用來做"清理善後" 的工作(例如在建立對象時用new開辟了一片內存空間,應在退出前在析構函數中用delete釋放)。

定義類的語法:

<?php
class phpClass {
  var $var1;    //類的變量使用 var 來聲明, 變量也可以初始化值。
  var $var2 = "constant string";
  
  function myfunc ($arg1, $arg2) {    //函數定義類似 PHP 函數的定義,但函數只能通過該類及其實例化的對象訪問。


     [..]
  }
  [..]
}
?>

實例:

<?php
class Site {
  /* 成員變量 */
  var $url;
  var $title;
  
  /* 成員函數 */
  function setUrl($par){
     $this->url = $par;
  }
  
  function getUrl(){
     echo $this->url . PHP_EOL;    //PHP_EOL表示換行
  }
  
  function setTitle($par){
     $this->title = $par;
  }
  
  function getTitle(){
     echo $this->title . PHP_EOL;
  }
}
?>

php使用new來創建實例:

如何調用呢?記住php類中調用實例的屬性或者方法的時候,用“->”

$google = new Site; 

// 調用成員函數,設置標題和URL 
$google->setTitle( "Google 搜索" ); 

$google->setUrl( ‘www.google.com‘ ); 

// 調用成員函數,獲取標題和URL 
$google->getTitle(); 

$google->getUrl()

php構造函數:(這個比較重要了)

<?php
class Site {
  /* 成員變量 */
  var $url;
  var $title;

  function __construct( $par1, $par2 ) {    //這個是構造函數,感覺還是和js不一樣,php是在class裏面用構造函數,純粹為了初始化的時候格式比較省事把,個人覺得,總覺得php的類是pytho向js的過度形式
    $this->url = $par1;
    $this->title = $par2;
  }
  /* 成員函數 */
  function setUrl($par){
     $this->url = $par;
  }
  
  function getUrl(){
     echo $this->url . PHP_EOL;
  }
  
  function setTitle($par){
     $this->title = $par;
  }
  
  function getTitle(){
     echo $this->title . PHP_EOL;
  }
}

$runoob = new Site(‘www.runoob.com‘, ‘菜鳥教程‘);

// 調用成員函數,獲取標題和URL
$runoob->getTitle();

?>
析構函數

析構函數(destructor) 與構造函數相反,當對象結束其生命周期時(例如對象所在的函數已調用完畢),系統自動執行析構函數。

<?php
class MyDestructableClass {
   function __construct() {
       print "構造函數\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "銷毀 " . $this->name . "\n";    //這個是析構函數,很想python中的魔法方法,__del__這種的
   }
}

$obj = new MyDestructableClass();
?>

繼承

class Child extends Parent {    //class子類extends父類
//代碼
}

如果父類的屬性和方法不能滿足子類的需求,那子類可以選擇重寫這個方法。

訪問控制

PHP 對屬性或方法的訪問控制,是通過在前面添加關鍵字 public(公有),protected(受保護)或 private(私有)來實現的。

  • public(公有):公有的類成員可以在任何地方被訪問。var定義的類屬性會被當成公有
  • protected(受保護):受保護的類成員則可以被其自身以及其子類和父類訪問。
  • private(私有):私有的類成員則只能被其定義所在的類訪問。

實例,我們來具體看一下訪問是如何被控制的:

class MyClass
{
    public $public = ‘Public‘;
    protected $protected = ‘Protected‘;
    private $private = ‘Private‘;

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new MyClass();
echo $obj->public; // 這行能被正常執行
echo $obj->protected; // 這行會產生一個致命錯誤,說明實例不能訪問類的protected屬性
echo $obj->private; // 這行也會產生一個致命錯誤,說明實例不能訪問類的private屬性
$obj->printHello(); // 輸出 Public、Protected 和 Private,說明類的方法本身可以訪問自己的各種屬性

接上一個程序

class MyClass2 extends MyClass    //新建一個子類
{
    // 子類中可以對 public 和 protected 進行重定義,但 private 而不能
    protected $protected = ‘Protected2‘;

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj2 = new MyClass2();
echo $obj2->public; // 這行能被正常執行
echo $obj2->private; // 未定義 private,說明private屬性不但不能被實例訪問,還不能被繼承
echo $obj2->protected; // 這行會產生一個致命錯誤,雖然產生了錯誤,但是並不能說明沒有繼承或者重寫,實際上它就是已經被繼承了而且被重寫了,只是不能被實例訪問而已
$obj2->printHello(); // 輸出 Public、Protected2 和 Undefined

備註方法的訪問控制和屬性的訪問控制是基本一樣的,

實例都不可以訪問受保護的或者私有的方法,私有方法不可以被子類繼承。

接口:

使用接口(interface),可以指定某個類必須實現哪些方法,但不需要定義這些方法的具體內容。

接口是通過 interface 關鍵字來定義的,就像定義一個標準的類一樣,但其中定義所有的方法都是空的。

接口中定義的所有方法都必須是公有,這是接口的特性。

要實現一個接口,使用 implements 操作符。類中必須實現接口中定義的所有方法,否則會報一個致命錯誤。類可以實現多個接口,用逗號來分隔多個接口的名稱。

<?php

// 聲明一個‘iTemplate‘接口
interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}


// 實現接口
class Template implements iTemplate
{
    private $vars = array();
  
    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }
  
    public function getHtml($template)
    {
        foreach($this->vars as $name => $value) {
            $template = str_replace(‘{‘ . $name . ‘}‘, $value, $template);
        }
 
        return $template;
    }
}

按照我的理解,接口更像是一個硬性規定,規定你類裏必須有接口規定的內容,少一個不行,至於你某個接口內容的算法,你隨意,我不care。

常量:

可以把在類中始終保持不變的值定義為常量。在定義和使用常量的時候不需要使用 $ 符號。

常量的值必須是一個定值,不能是變量,類屬性,數學運算的結果或函數調用。

class MyClass
{
    const constant = ‘常量值‘;    //這樣寫

    function showConstant() {
        echo  self::constant . PHP_EOL;
    }
}

抽象類:

和接口有點像,

任何一個類,如果它裏面至少有一個方法是被聲明為抽象的,那麽這個類就必須被聲明為抽象的。

定義為抽象的類不能被實例化。

被定義為抽象的方法只是聲明了其調用方式(參數),不能定義其具體的功能實現。

繼承一個抽象類的時候,子類必須定義父類中的所有抽象方法;另外,這些方法的訪問控制必須和父類中一樣(或者更為寬松,更加寬松也可以)。例如某個抽象方法被聲明為受保護的,那麽子類中實現的方法就應該聲明為受保護的或者公有的,而不能定義為私有的。

子類方法可以包含父類抽象方法中不存在的可選參數。

<?php
abstract 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";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue(‘FOO_‘) . PHP_EOL;

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue(‘FOO_‘) . PHP_EOL;
?>
//返回
ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

Static 關鍵字

聲明類屬性或方法為 static(靜態),就可以不實例化類而直接訪問。

靜態屬性不能被實例訪問,但是靜態方法可以。

由於靜態方法不需要通過對象即可調用,所以偽變量 $this 在靜態方法中不可用。

靜態屬性不可以由對象通過 -> 操作符來訪問。

<?php
class Foo {
  public static $my_static = ‘foo‘;
  
  public function staticValue() {
     return self::$my_static;
  }
}

print Foo::$my_static . PHP_EOL;    //返回foo不用實例化可以直接訪問
$foo = new Foo();

print $foo->staticValue() . PHP_EOL;    //返回foo,因為實例化以後不可以訪問static的屬性
?> 

final關鍵字


PHP 5 新增了一個 final 關鍵字。如果父類中的方法被聲明為 final,則子類無法覆蓋該方法。如果一個類被聲明為 final,則不能被繼承。

<?php
class BaseClass {
   public function test() {
       echo "BaseClass::test() called" . PHP_EOL;
   }
   
   final public function moreTesting() {    //final在public前
       echo "BaseClass::moreTesting() called"  . PHP_EOL;
   }
}

class ChildClass extends BaseClass {
   public function moreTesting() {    //子類無法覆蓋該方法,繼承還是可以的
       echo "ChildClass::moreTesting() called"  . PHP_EOL;
   }
}
// 報錯信息 Fatal error: Cannot override final method BaseClass::moreTesting()
?>

調用父類構造方法:

class 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 類中構造方法

// 調用 BaseClass、SubClass 構造方法  
$obj = new SubClass();
//返回BaseClass 類中構造方法
//返回SubClass 類中構造方法

// 調用 BaseClass 構造方法
$obj = new OtherSubClass();
//返回BaseClass 類中構造方法

php編程 之 php基礎三