PHP基础

Eecho
Eecho
发布于 2024-12-24 / 473 阅读
29
0

PHP基础

php语法

基础语法

php代码标记

  1. ASP标记:<% PHP代码%>

  2. 短标记:<? PHP代码?>

  3. 脚本标记:<script language='php'>php代码</script>

  4. 标准标记:<?php PHP代码?>

包含文件

正则

面向对象

创建类和对象

类:使用class关键字创建

对象:使用new关键字

<?php
class Test
{
​
}
​
$a = new Test();

属性

属性必须要有修饰符(public,protected,private),不然会报错

如果默认没有赋值则为NUll

使用:对象->属性名 来调用属性

<?php
class Test
{
    public $name;
    public $age;
}
​
$a = new Test();
var_dump($a->name);    
var_dump($a->age);
/*
NULL
int(1)
*/

方法

使用function来定义方法,对象->方法 来调用方法

方法如果不写修饰符,则默认为public。

<?php
class Test
{
    public $name;
    public $age=1;
    function hello()    //默认为public
    {
        echo "你好".$this->name;
    }
    public function say(){}    //公有
    protected function smile(){}    //保护
    private function laugh(){}    //私有
    
}
​
$a = new Test();
$a->name = "Eecho";
$a->hello();
​
/*
你好Eecho
*/

构造方法

和python里面的init差不多

  • 一个类只能有一个构造方法

  • 没有返回值,即使写了也没有意义

  • 在创建类的新对象时,系统会自动的调用类的构造方法完成对象的初始化。

  • 如果没有重写默认构造函数,那么系统会默认帮我们创建一个没有参数的构造函数,public function __construct(){},如果我们重写了构造函数,那么我们自定义的构造函数就会覆盖系统默认的构造函数。

  • 如果自定义的构造函数里面有形参,那么当创建对象的时候必须传入对应的实参。

class Test
{
    function __construct()
    {
        return "111";    //没有返回值,即使写了也没有意义
    }
}
​
$t = new Test(1);
var_dump($t);
/*
class Test#1 (0) {
}
*/

析构方法

和python里面的del差不多

  • 当一个对象没有被任何变量应用时会自动销毁,并在销毁前自动调用析构函数,无论程序有没有结束,只要一个对象没有被任何变量应用就会被销毁。

  • 当PHP程序运行结束后,所有的对象都会自动销毁,对象在被销毁前,会自动调用构造函数。

  • 默认情况下,析构函数销毁对象的顺序和创建对象的顺序正好相反。最先创建的对象最后被销毁,强调默认情况下是因为,我们可以手动销毁对象,这样的话对象销毁的顺序就和默认情况不一样了,当PHP程序执行完后,那时候销毁对象的方法就是采用的默认方法。

  • 如果我们定义的一个类里专门有个属性是用来连接数据库的,当我们创建了该类的实例对象,并且用该成员属性连接数据库后,如果该类型的实例对象占用资源较大,我们往往会在使用后就立即销毁,虽然该对象能被销毁,但是该对象的成员属性所连接的资源却不会被自动销毁,需要我们自己手动销毁,这时,我们可以在析构函数里添加一句关闭数据库连接的语句就好了(mysql_close(要关闭的资源))。

class Test {
​
    public function __construct() {
        echo 'hello, world<br>';
    }
​
    public function __destruct()
    {
        echo '执行一些回收资源的操作<br>';
    }
}
​
$testObj = new Test();
​
/*
hello, world
执行一些回收资源的操作
*/

垃圾回收机制

  • 在PHP中,当一个对象没有任何引用指向它的时候,就会成为一个垃圾对象,PHP将启用垃圾回收器将对象销毁。

  • 在PHP程序退出前,PHP也将启用垃圾回收器,销毁对象。

访问修饰符

  • public(公有)

    如果没有为方法指定访问修饰符,就会默认public。公有属性或方法可以在类的内部或外部以及子类中进行访问。

    class Test
    {
        public $name="Eecho";
        function A()
        {
            echo $this->name;
        }
    }
    ​
    class Test2 extends Test    //extends代表继承哪个类,这里Test2继承了Test
    {
        function B()
        {
            echo $this->name;
        }
    }
    ​
    ​
    $t = new Test();
    echo $t->name;    //可以在类外部访问
    $t->A();    //可以在类内部访问
    $t2 = new Test2();
    echo $t2->name;    //可以在子类中访问
    ​
    /*
    EechoEechoEecho
    */
  • protected(受保护的)

    如果一个属性或方法指定修饰符为protected,那么被标记的属性或方法只能在类内部和子类中访问,被修饰的属性和方法能被子类继承。

    class Test
    {
        protected $name="Eecho";
        function A()
        {
            echo $this->name;
        }
    }
    ​
    class Test2 extends Test
    {
        function B()
        {
            echo $this->name;
        }
    }
    ​
    $t = new Test();
    //echo $t->name;    //报错,不能通过对象访问,只能在本类和子类中访问
    $t->A();
    $t2 = new Test2();
    //echo $t2->name;    //报错,不能通过对象访问,只能在本类和子类中访问
    $t2->B();    
    /*
    EechoEecho
    */
  • private(私有的)

    如果一个属性或方法指定访问修饰符为private,那么被标记的属性或方法只能在类内部访问,私有的属性和方法将不会被继承

    class Test
    {
        private $name="Eecho";
        function A()
        {
            echo $this->name;
        }
    }
    ​
    class Test2 extends Test
    {
        function B()
        {
            echo $this->name;    // 报错,因为private修饰符,只能在本类中访问
        }
    }
    ​
    $t = new Test();
    //echo $t->name;    // 报错,因为private修饰符,只能在本类中访问
    $t->A();
    $t2 = new Test2();
    $t2->B();    //报错
    //echo $t2->name;    // 报错,因为private修饰符,只能在本类中访问
    ​
    /*
    Eecho
    */

魔法方法

  1. 魔法方法都是在满足某个条件时,由系统自动调用

  2. 魔法方法的名字都是以两个下划线__ 开头的,因此定义函数的时候,函数名不要用以两个下划线开头。

1. __construct

构造方法,当创建对象的时候自动调用__construct方法

class Person
{
    function __construct($name, $age)
    {
        echo "这是构造函数";
        $this->name = $name;
        $this->age = $age;
    }
}

$p1 = new Person('Eecho',20);


/*
这是构造函数
*/

2. __destruct

析构方法,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。

class Person
{
    function __construct($name, $age)
    {
        echo "这是构造函数";
        $this->name = $name;
        $this->age = $age;
    }

    function __destruct()
    {
        echo "这是析构函数";
    }
}

$p1 = new Person('Eecho',20);

/*
这是构造函数这是析构函数
*/

对象比较

==

比较两个对象,如果两个对象的属性和值都想灯光,而且两个对象是同一个类对象的实列,那么就相等.

class Test
{
    public $name = 'itbs1';
    public $age = 25;

}


$testObj = new Test();
$testObj2 = new Test();

if($testObj == $testObj2){
    echo "相等";
}

$testObj2->name = 'jack';

if($testObj == $testObj2){
    echo "相等";
}
else{
    echo "不相等";
}

/*
相等不相等
*/
class Test
{
    public $name = 'itbs1';
    public $age = 25;

}

class Test2
{
    public $name = 'itbs1';
    public $age = 25;
}

$testObj = new Test();
$testObj3 = new Test2();

if($testObj == $testObj3){
    echo "相等";
}
else{
    echo "不相等";
}


/*
不相等 
*/
// 因为两个对象不属于同一个类

===

继承

当扩展一个子类的时候,子类会继承父类所有的public和protected的方法,属性和常量.除非子类覆盖了父类的方法,被继承的方法都会保留其原有的功能.

如果在子类中访问父类的方法(public,protected)可以使用父类::方法名(或者parent::方法名)

调用父类的普通方法直接用this->方法名即可

继承并不是直接把父类的属性和方法直接拷贝到子类里面来。而是建立了一种关联。当在子类里调用父类的方法时,父类输出自己的属性时输出结果都和初始化不一样了(private属性除外,因为是私有的,子类无法看见,所以子类也无法重写父类的私有属性),如果是直接拷贝的话,那么当调用父类的方法时应该输出100,200,300才对,所以说继承不是直接拷贝。

class A
{
public $num1 = 100;
protected $num2 = 200;
private $num3 = 300;

public function show1()
{
    echo 'num1 = '.$this->num1.PHP_EOL;
}

public function show2(){
    echo 'num2 = '.$this->num2.PHP_EOL;
}

public function show3(){
    echo 'num3 = '.$this->num3.PHP_EOL;
}
}


class B extends A
{
    public $num1 = 1;
    protected $num2 = 2;
    private $num3 = 3;

    public function show1(){
        echo 'num1 = '.$this->num1.PHP_EOL;
        parent::show1();
    }

    public function show2(){
        echo 'num2 = '.$this->num2.PHP_EOL;
        parent::show2();
    }

    public function show3(){
        echo 'num3 = '.$this->num3.PHP_EOL;
        parent::show3();
    }
}

$bobj = new B();
$bobj->show1();
$bobj->show2();
$bobj->show3();

/*
num1 = 1
num1 = 1
num2 = 2
num2 = 2
num3 = 3
num3 = 300
*/

重载

指动态地"创建"类属性和方法。通过魔法方法实现.

属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。所以这些方法都不能被声明为 static。从 PHP5.3.0 起, 将这些魔术方法定义为 static 会产生一个警告。

所有重载方法都必须被声明为public。

属性重载

当访问一个不可访问的属性或者不存在的属性时,就会调用魔法方法 __get()

__set() 如果我们不重写这两个方法,当我们给不存在的属性赋值时,系统会自动帮我们创建一个public的属性,

class Obj {

    protected $name = 'itbsl';



}

$obj = new Obj();
$obj->name = "jack"; //此处会报致命错误

var_dump($obj);

/*
Fatal error: Uncaught Error: Cannot access protected property Obj::$name
*/

重写__set()方法就没有问题了

class Obj {

    protected $str = 'itbsl';

    public function __set($name, $value)
    {
        $this->$name = $value;
    }

}

$obj = new Obj();
$obj->str = "jack";

var_dump($obj);

方法重写

在子类中重写父类的方法时要,重写的方法的访问控制符不能比父类的方法的访问控制符的级别小 重写属性也要遵守上面的规则

属性重写

如果子类有和父类相同的属性,如果属性是public或者protected则会重写父类的属性,如果是private则创建一个同名的新私有属性,同时仍然会继承父类的同名私有属性。

静态属性

  1. 静态属性不属于某个对象,而是所有对象共享的属性,每个对象都可以访问它.

  2. 静态属性属于类的范畴,而不是某个对象的独有特性

  3. 在类中,使用和访问静态变量的方法是 self::$静态属性

  4. 在类外,使用和访问静态变量的方法是 类名::$静态属性 (访问修饰符为public)

class Person
{
    public static $name = 'Eecho';
    function getname()
    {
        echo self::$name;
    }

}


$p = new Person();
$p->getname();
echo Person::$name;

/*
EechoEecho
*/

静态方法

  1. 静态方法的访问方式为 类名::静态方法名(); 同时也可以用对象名->静态方法名();和对象名::静态方法名(),但是后两种不推荐,尽量只用第一种。

  2. 在类的外部调用静态方法,要求静态方法的访问修饰符必须是public的。

  3. 在类内部调用静态方法: self::静态方法 或者 类名::静态方法 通过$this也可以。只推荐第一种方式。在类的内部访问静态方法,无论是什么修饰符都可以访问静态方法。

  4. 静态方法中不可以访问非静态属性和非静态方法。

  5. 普通的成员方法,可以访问静态属性。

class Person
{
    public static function Hello()
    {
        echo "Hello World!";
    }
}


$p = new Person();
$p->Hello();
$p->Hello();
Person::Hello();


/*
Hello World!Hello World!Hello World!
*/

多态

类型约束

抽象类

当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法[抽象方法],用abstract来修饰该类[抽象类]

  1. 把某个方法做成抽象方法,则在前面加上 abstract

  2. 如果一个类中有抽象方法,那么该类必须声明为抽象类

  3. 抽象类最主要的作用在于设计,它的目的是让其它的类继承它,并实现其中的抽象方法。如果子类继承了该抽象类,除非继承该抽象类的子类也被声明为抽象类,否则必须实现抽象类中所有的抽象方法,如果不实现就会报错。

  4. 抽象类不能被实例化

  5. 抽象类不能有函数体

语法:

abstract class 类名 { abstract 修饰符 function 函数名(参数列表); }

abstract class Superman
{
    public $name;
    public $age;
    public function __construct($name, $age){
        $this->name = $name;
        $this->age = $age;
    }
    abstract public function run();
    abstract public function fly();
    abstract public function attach();

}


class Spiderman extends Superman
{
    public function run(){
        echo "Spiderman is running on the net.";
    }

    public function fly(){
        echo "Spiderman can hang in the sky through net.";
    }

    public function attach(){
        echo "spider attach.";
    }
      
}


/*
Spiderman is running on the net.Spiderman can hang in the sky through net.spider attach.
*/

接口

  1. 接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来。

  2. 语法

    interface 接口名 { //方法[不含方法体] }

  3. 接口中所有的方法都不能有主体

  4. 一个类可以实现多个接口,接口名之间用逗号隔开

  5. 接口中可以有属性,但只能是常量,并且是公开可访问的。默认是public,但不能用public显式修饰

  6. 接口中的方法都必须是public的,默认就是public

  7. 个接口不能继承其它的类,但是可以继承别的接口,而且一个接口可以继承多个接口

    interface 接口名 extends 接口1, 接口2 { //方法[不含方法体] }

  8. 接口不能实例化

final关键字

  1. 类的某个方法不允许子类通过重写来修改,不希望某个类被其它的类继承

    final class Person
    {
        final function name()
        {
            echo "Eecho";
        }
    }
    
    
    class Person2 extends Person    //报错因为不希望某个类被其它的类继承
    {
        function name()    // 会报错因为,不允许通过子类重写
        {
            echo "Eecho2";
        }
    }
    
    
    $p2 = new Person2();
    $p2->name();
  2. final方法不能被重写,但可以被继承。即使是被声明为final的方法也依然能够被继承并被使用,只是不能重写(修改)罢了。

    class Person
    {
        final function name()
        {
            echo "Eecho";
        }
    }
    
    
    class Person2 extends Person
    {
    
    }
    
    
    $p2 = new Person2();
    $p2->name(); 
    /*
    Eecho
    */
  3. final类是可以被实例化的

    final class Person
    {
        final function name()
        {
            echo "Eecho";
        }
    }
    ​
    $p = new Person();
    $p->name();
    ​
    /*
    Eecho
    */

    类常量

    在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号。

    常量的值必须是一个定值,不能是变量、类属性、数学运算的结果或函数调用。

    (1) 常量名一般字母全部大写:TAX_RATE,中间可以有下划线

    (2) 在定义常量的同时,必须赋初值,比如 const TAX_RATE = 1.1

    (3) const关键字前不能用public/protected/private修饰。默认是public

    (4) 访问常量

    在类的外部 类名::常量名 接口名::常量名

    在类的内部 类名::常量名 self::常量名

    (5) 常量的值在定义的时候就初始化,以后就不能修改

    (6) 常量可以被子类继承

    (7) 一个常量是属于一个类的,而不是某个对象的。

    (8) 常量是全局性的,可以在任何地方访问。

    (9) 在类里面不能用define定义常量。

    (10) 常量的值可以是基本类型数据和数组。不可以是对象。

    class Person
    {
        const NAME = "Eecho";
        function get_name()
        {
            echo self::NAME;
            echo  Person::NAME;
        }
    }
    ​
    $p1 = new Person();
    echo Person::NAME;
    $p1->get_name();
    ​
    ​
    /*
    EechoEechoEecho
    */


评论