PHP基础
文章目录
变量
声明方式:
$varname
不注重类型,直接$varname=varvalue
就可以赋值,注意变量自始至终都要带着前面的美元符号
变量赋值时
$var=011;//以0开头的数字视为八进制数
$var=0x11;//以0x开头的数字视为十六进制数
数字字符串比较时转化为数进行比较
变量只有一个作用域(函数除外)
数组
PHP的数组也是不注重类型的
同一个数组的内容可以是不同的类型
空数组转化为null,空数组= =null返回true,空数组= = =null返回false,即空数组值为null但是类型和null不同
使用方式:
$arr=array(value0,value1,value2,...,valuen);
或者
$arr=[value0,value1,value2,...,valuen];
或者
$arr[0]=value0;
$arr[1]=value1;
$arr[2]=value2;
$arr[3]=value3;
这两种方法效果完全相同
注意,在使用第三种方法的时候,$arr[2]=NULL
如果因为其值为空而忽略不写,直接写$arr[3]=5
,
那么$arr[3]=5
相当于没写
<meta charset="utf-8">
<?php
$arr[0]="123";
$arr[1]="";
$arr[3]=5;
for($i=0;$i<count($arr);$i++){
echo $arr[$i];
echo "<br>";
}
?>
运行结果:
123
遍历
for循环遍历:
for($i=0;$i<count($arr);$i++){
echo $arr[$i];
}
其中count($arrayname)
函数可以获取参数数组的长度
foreach循环遍历数组
<meta charset="utf-8">
<?php
$arr=array(1,5,2,4,6,8,9,7,3);
foreach($arr as $i){
echo $i;
}
?>
运行结果:
152468973
关联数组(map)
使用方法:
法1:
$arr=array("key1"=>value1,"key2"=>value2,...,"keyn"=>valuen);
法2:
$arr=["key1"=>value1,"key2"=>value2,...,"keyn"=>valuen];
法3:
$arr["key1"]=value1;
$arr["key2"]=value2;
...
$arr["keyn"]=valuen;
遍历方法:
注意不能使用for循环企图用0,1,2,…count(arrayname)-1下标遍历关联数组
一个错误的例子:
<meta charset="utf-8">
<?php
$arr=array("Vader"=>40,"Anakin"=>20,"Sidious"=>250);
for($i=0;$i<count($arr);$i++){
echo $arr[$i]."<br>";
}
?>
这样编译不会报错,但是运行没有结果,因为下标为一些字符串类型的键,不是从0开始的整数
应该用foreach循环遍历:
<meta charset="utf-8">
<?php
$arr=array("Vader"=>40,"Anakin"=>20,"Sidious"=>250);
foreach ($arr as $key=>$value) {
echo "[".$key.",".$value."]"."<br>";
}
?>
运行结果:
[Vader,40]
[Anakin,20]
[Sidious,250]
foreach循环的格式
foreach($arrname as <pattern>){
...
}
其中arrname
表示数组名
<pattern>
表示数组元素的格式,
如果是数值数组则pattren
就是一个变量$x
,
如果是关联数组则pattern是$x=>$y
的样式
排序
<<肥城市小实验家>>
- sort() - 对数组进行升序排列
- rsort() - 对数组进行降序排列
- asort() - 根据关联数组的值,对数组进行升序排列
- ksort() - 根据关联数组的键,对数组进行升序排列
- arsort() - 根据关联数组的值,对数组进行降序排列
- krsort() - 根据关联数组的键,对数组进行降序排列
关于排序,通常能想到的几个问题:
1.按照什么顺序排序?字典序?
<meta charset="utf-8">
<?php
$arr=array(8,7,4,5,6,1,2,5,3,10);
sort($arr);
foreach($arr as $x){
echo "$x ";
}
?>
结果:
1 2 3 4 5 5 6 7 8 10
2.默认升序还是降序?
3.字符串和数字还有NULL等乱炖的数组能不能排序,规则是什么?
4.10和2是按照字典序排的10<2还是按照数字大小10>2?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EozdhClg-1644389789096)(http://a1.qpic.cn/psc?/V53hVOfF145yqb4g88U231xyUY174Wph/2P1sA1wi35ZIt3YPmnTQEtDeN8.MEISwsXBX4yWpgVplLSBteag6G6NQMI5ILnrdEQH02m7dMyNRuxobndNC9k75XGve1GX1HLPlBV8!/b&ek=1&kp=1&pt=0&bo=oAWADAAAAAAAAA8!&tl=3&vuin=212154162&tm=1644332400&sce=60-2-2&rf=viewer_311)]
5.关联数组怎么排序,能否规定按照键排还是按照值排?
6.能否重载排序规则?
7.对关联数组排序的方法能否用到数值数组上,会怎样报错?
8.sort函数能否缺省参数?
下面实验验证之
1.对纯整数数组应用各种排序函数
function printValueArray($arr){
foreach ($arr as $item) {
echo "$item ";
}
echo "<br>";
}
$arr=array(8,7,4,5,6,1,2,5,3,10);
printValueArray($arr);
sort($arr);
printValueArray($arr);
rsort($arr);
printValueArray($arr);
asort($arr);
printValueArray($arr);
ksort($arr);
printValueArray($arr);
运行结果:
8 7 4 5 6 1 2 5 3 10
1 2 3 4 5 5 6 7 8 10
10 8 7 6 5 5 4 3 2 1
1 2 3 4 5 5 6 7 8 10
10 8 7 6 5 5 4 3 2 1
该运行结果说明,
1.sort函数默认升序排列
2.对关联数组的排序方法也可以对数值数组排序,
asort对数值数组升序排列,相当于sort,
ksort对数值数组降序排列,相当于rsort
2.对有整数,字符串,NULL值的数组排序:
<meta charset="utf-8">
<?php
function printValueArray($arr){
foreach ($arr as $item) {
if($item ==NULL)echo "NULL";
else echo "$item ";
}
echo "<br>";
}
$arr=array(0,"0",-2,"-2",8,"7",4,5,"6",1,2,5,NULL,3,"2a5","str","atr","a",10,"100","101","110","80");
printValueArray($arr);
sort($arr);
printValueArray($arr);
rsort($arr);
printValueArray($arr);
asort($arr);
printValueArray($arr);
ksort($arr);
printValueArray($arr);
?>
运行结果:
NULL0 -2 -2 8 7 4 5 6 1 2 5 NULL3 2a5 str atr a 10 100 101 110 80
NULL-2 -2 NULL0 1 2 2a5 3 4 5 5 6 7 8 10 80 100 101 110 a atr str
str atr a 110 101 100 80 10 8 7 6 5 5 4 3 2a5 2 1 NULL0 -2 -2 NULL
NULL-2 -2 NULL0 1 2 2a5 3 4 5 5 6 7 8 10 80 100 101 110 a atr str
str atr a 110 101 100 80 10 8 7 6 5 5 4 3 2a5 2 1 NULL0 -2 -2 NULL
该运行结果表明:
1.NULL值永远最小
2.整数也转换成字符串按照字典序进行排序
3.任意数字的字典序小于任意字母
function printAssociatedArray($arr){
foreach($arr as $key=>$value){
echo "[$key,$value]";
}
echo "<br>";
}
$arr=["a"=>10,"2"=>9,"汉字"=>5,"3"=>9,"1"=>9];
printAssociatedArray($arr);
ksort($arr);
printAssociatedArray($arr);
asort($arr);
printAssociatedArray($arr);
sort($arr);
printAssociatedArray($arr);
运行结果:
[a,10][2,9][汉字,5][3,9][1,9]
[a,10][汉字,5][1,9][2,9][3,9]
[汉字,5][1,9][2,9][3,9][a,10]
[0,5][1,9][2,9][3,9][4,10]
该运行结果证明,
1.ksort将关联数组按照键字典序排序
2.asort将关联数组按照值字典序排序
3.sort应用于关联数组不会报错,会按照值字典序排序,并且将键重新用0,1,2…下表赋值
超级全局变量
superglobals
不用声明,就可以在php脚本文件的任何一个地方用
全局变量列表:
- $GLOBALS
- $_SERVER
- $_REQUEST
- $_POST
- $_GET
- $_FILES
- $_ENV
- $_COOKIE
- $_SESSION
$GLOBALS[] 全局变量数组
$x=1;
$y=2;
$GLOBALS["x"]=10;
$GLOBALS["y"]=50;
echo "$x,$y<br>";
$a=10;
$b=20;
function func1(){
$GLOBALS["a"]=100;
$b=200;
}
func1();
echo "$a,$b,$GLOBALS[a],$GLOBALS[b]<br>";
运行结果:
10,50
100,20,100,20
该实验结果说明:
1.全局位置的普通变量$var
就是$GLOBALS[var]
2.在某作用域(比如函数域)内,通过$GLOBALS[var]
可以修改全局变量,但是通过$var
相当于在函数下声明的新的局部变量,会遮盖原来已有的全局变量,函数下使用全局变量一定要用GLOBALS
3.在$GLOBALS[]
变量第一次使用时,中括号里要写字符串形式,即$GLOBALS["var"]
,此后使用时就不能写字符串了,直接写键$GLOBALS[var]
_SERVER[] HTTP请求头信息数组
例如:
<meta charset="utf-8">
<?php
echo $_SERVER['PHP_SELF'];//当前执行脚本文件名
echo "<br>";
echo $_SERVER['SERVER_NAME'];//运行当前脚本的服务器主机名
echo "<br>";
echo $_SERVER['HTTP_HOST'];//请求头中的HOST内容
echo "<br>";
echo $_SERVER['HTTP_REFERER'];
echo "<br>";
echo $_SERVER['HTTP_USER_AGENT'];//用户代理(客户端浏览器版本信息)
echo "<br>";
echo $_SERVER['SCRIPT_NAME'];
echo "<br>";
echo $_SERVER['SERVER_ADDR'];//服务器ip地址
echo "<br>";
echo $_SERVER['REQUEST_TIME'];
echo "<br>";
echo $_SERVER['REMOTE_ADDR'];//客户端ip地址
?>
/index.php/index.php
PhpStorm 2021.3.1
localhost:63342
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36
/index.php/index.php
127.0.0.1
1644369242
127.0.0.1
函数
注意php中用户自定义函数和语言关键字对大小写不敏感
function <函数名>(参数1,参数2,...,参数n){
...函数体...
//return <可能的返回值>
}
与C++的函数不同的是,不用声明返回值类型,如果有返回值就在最后直接return,void函数就不写return
与php变量不同的是,函数名不需要美元符号$开头
例如一个没有返回值的函数用来遍历打印数值数组:
function printValueArray($arr){
foreach ($arr as $item) {
echo "$item ";
}
echo "<br>";
}
一个有返回值的求两数和的函数:
function add($a,$b){
return $a+$b;
}
魔术常量
预定义常量
__LINE__
当前行号
<meta charset="utf-8">
<?php
echo __LINE__;
?>
运行结果:
8
__FILE__
当前文件的完整路径
<meta charset="utf-8">
<?php
echo __FILE__;
?>
运行结果:
C:\Users\86135\Desktop\login\index.php
__FUNCTION__
当前函数名
<meta charset="utf-8">
<?php
echo __FUNCTION__;
echo "<br>................<br>";
function myFunction(){
echo __FUNCTION__;
}
myFunction();
?>
运行结果:
................
myFunction
不在函数作用域时使用__FUNCTION__
不起作用
面向对象
class <classname> {
var $var1;//成员变量使用var声明,可以拥有初始化值
var $var2;
...
function <methodname> ($arg1, $arg2,...) {
[..]
}
[..]
}
类
构造函数
访问限制 __construct($参数1,$参数2,...,$参数n){
...
//构造函数不能有返回值
}
例如一个链表的结点类
class LinkedNode{
var $value;
var $next;
public function __construct($value=0,$next=NULL){//节点类构造函数(可以缺省参数)
$this->value=$value;
$this->next=$next;
}
function setNext($node){//设置后继节点方法
$this->next=$node;
}
function setValue($value){
$this->value=$value;
}
function getNext(){
return $this->next;
//注意此处不能写return $next;会编译报错没有声明过$next,
//即成员必须用$this->var指代
}
function getValud(){
return $this->value;
}
function println(){
echo "$this->value<br>";
}
}
$node1=new LinkedNode(50);//new关键字调用构造函数,这一点与C++相同
$node1->println();
$node1->setValue(100);
$node2=new LinkedNode(20,$node1);
$node2->getNext()->println();
运行结果:
50
100
运行结果表明setter方法为引用传递
析构函数
function __destruct(){//析构函数没有参数
...
//析构函数没有返回值
}
例如:
class A{
public function __construct(){
echo "ctor called<br>";
}
public function __destruct(){
echo "dtor called<br>";
// TODO: Implement __destruct() method.
}
}
$a=new A;
//此处也可以写为$a=new A();构造函数没有参数时可以省略括号
echo "in global domain<br>";
运行结果:
ctor called
in global domain
dtor called
析构函数会自动调用,在本例中析构函数在程序即将结束前调用
继承
继承关键字extends
class <子类名> extends <父类名>{
子类...
}
子类调用父类成员
php只允许单继承,因此类似于java的super,php也有一个父类引用parent,这个引用只可以在类内部使用,比如函数定义中调用
parent::成员
比如调用父类构造函数:
parent::__construct(参数...);
class Father{
var $only;
function setOnly($only){
$this->only=$only;
}
function getOnly(){
return $this->only;
}
function __construct($only=0){
$this->setOnly($only);
echo "father ctor called<br>";
}
function __destruct(){
echo "father dtor called<br>";
}
}
class Son extends Father{
public function __construct($only=0){
parent::__construct($only);//注意子类调用父类构造函数的写法,如果不写则不调用父类构造函数
//总是在子类的构造函数首行先调用父类的构造函数
echo "son ctor called<br>";
}
public function __destruct(){
echo "son dtor called<br>";
}
}
$s=new Son();
$s->setOnly(20);
echo $s->getOnly()."<br>";
运行结果:
father ctor called
son ctor called
20
son dtor called
该运行结果说明父类析构函数没有隐式调用,这点与C++不同
方法重写
子类重写父类同名函数
<?php
class Father{
var $only;
function setOnly($only){
$this->only=$only;
}
function getOnly(){
return $this->only;
}
function __construct($only=0){
$this->setOnly($only);
echo "father ctor called<br>";
}
function __destruct(){
echo "father dtor called<br>";
}
}
class Son extends Father{
public function __construct($only=0){
// $this->setOnly($only);
parent::__construct($only);
echo "son ctor called<br>";
}
public function __destruct(){
echo "son dtor called<br>";
}
function getOnly(){
return -$this->only;
}
function oldGetOnly(){
return parent::getOnly();
}
}
$s=new Son();
$s->setOnly(20);
echo $s->getOnly()."<br>";
echo $s->oldGetOnly()."<br>";
?>
运行结果:
father ctor called
son ctor called
-20
20
son dtor called
说明 echo $s->getOnly()."<br>";
调用的是子类重写之后的getOnly方法
访问控制
类似于C++的访问控制
关键字 | 作用 |
---|---|
public(var) | 公有成员,任意位置访问 |
protected | 保护成员,类属内访问 |
private | 私有成员,类内访问 |
类成员属性必须为三者之一,
var声明的成员变量默认为public属性
没有访问控制关键字修饰的函数默认为public属性
接口
接口指定类必须实现哪些方法,但是不需要规定如何实现
接口声明关键字interface
interface growable{
// var $only; //接口不允许有成员变量
// private function grow();//接口函数只能声明为public或者忽略声明
public function grow();//注意接口方法也可以有形参
// function grow(){
// echo "in function grow";//接口函数不允许有函数体
// }
}
接口实现关键字implements
interface myInterface{
function test($var1);//接口函数允许有参数
}
class myClass implements myInterface{
//接口函数要么为public函数,要么忽略访问修饰符
function test($para1){//允许形参改名var1->para1
}
// function test($para1,$para2){ //参数表参数个数和类型必须完全与接口相同
//
// }
}
常量
const修饰,不需要加美元符号
早期版本(PHP 5.3.0以前)中const只能在类中使用,后来类外也可以声明const常量,使用时也不需要加美元符号
class A{
const MAXN=1e6;
function func(){
echo self::MAXN;//类内使用const成员时要用self::指代当前类
}
}
$a=new A;
$a->func();
与define声明常量的区别:
define(常量名,常量值);
const 常量名=常量值;
静态关键字static
类属性或者类方法使用static修饰,static成员不为对象所有,为类所有
静态方法可以使用类名::方法
调用,也可以使用对象->方法
调用
但是静态成员变量只允许通过类名::成员
调用,对象无法访问类的成员
final关键字
final修饰的类无法被继承
final修饰的方法无法被重写
抽象类
抽象方法:只有函数名和形参表,没有函数体的函数
有抽象方法的类一定是抽象类,必须在类名前加上abstract修饰
无抽象方法的类也可以加上abstract修饰
抽象类无法实例化
继承抽象类的子类如果不完全实现抽象父类的抽象方法则仍为抽象类
子类实现父类的抽象方法时访问修饰只能相同或者更宽
子类方法中可以有父类抽象方法中不存在的可选参数
<?php
abstract class Father{
abstract function func($var1);
}
class Son extends Father{
// protected function func($var1){}//不允许访问修饰降级
// function func(){}//不允许参数个数不匹配
// function func($var1,$var2){}//多余参数应为 可 选 参数
function func($var1,$var2=0){}//多余参数为可选参数
}
名字空间
类似于C++的namespace
<?php
namespace ns1{
$a=10;
echo "$a,$GLOBALS[a]<br>";
}
namespace ns2{
echo "$GLOBALS[a],";
$a=20;
echo "$a,$GLOBALS[a]<br>";
}
?>
运行结果:
10,10
10,20,20
运行结果表明:
1.GLOBALS
变量可以穿透名字空间
2.如果在ns2中直接打印$a
则会报错说其不存在,说明普通变量无法穿透名字空间
显式与隐式全局名字空间
在没有显式namespace时,所有代码都在全局命名空间中,当有至少一个显式命名空间时,就不允许有不在命名空间中的代码了,即使是全局的也要写在显式全局命名空间中.即要么一个namespace也没有,要么都在namespace里
比如:
<?php
namespace ns1{}
$a=10;
?>
会编译报错:
全局代码应包含在全局命名空间声明中:3
应当这样写:
<?php
namespace ns1{}
namespace {//没有名字的名字空间即为全局名字空间
$a=10;
}
?>