[TOC]

基础

1.注意点:
  1. 文件名扩展名: php
  2. 文件名 和 文件夹名 一律不准使用 中文
  3. PHP文件 必须存放在www目录
2.PHP介绍

专业名词: 超文本预处理器
描述: 一种用来开发动态网站的服务器脚本语言

3.定界符, 声明

<?php PHP代码 ?>

4.注释

​ # 单行注释

/ / 多行注释

5.echo

通过语法结构 : echo
格式: echo 内容 内容: 只有纯数字可以不加引用, 其余都加上引号
作用: 将 内容 交给浏览器
echo ‘老娘们’;
echo 250;
echo ‘ 老爷们 ‘;

6.编码
  1. 编码

    header(‘内容类型: xxx; 编码设置=编码’);

header(‘content-type: text/html; charset=utf-8’);
一般会把这个编码声明 放在代码的最前面

中国: 早期 gb2312 因为空间浪费问题, 所以产生了后期 GBK
全球通用: utf-8

变量

变量 variable 简写: var

1. 定义
         未知数

​ 2. 格式
​ \$变量名 = 值
​ 每生成一个变量, 就会占用一定的内存
​ \$a = 100;
​ echo \$a;

​ 3. 未定义变量
​ 没有值的变量, 都叫做未定义变量
​ echo \$b;

​ 4. 变量命名
​ 由数字, 字母和下划线组成, 但不能由数字开头
​ \$2b = ‘熊二’;
​ \$_3B = ‘熊大’;
​ echo \$_3B;

​ \$A_a4 = ‘胸大’;
​ echo \$A_a4;

​ \$呆萌伐木工 = ‘光头强’; # 支持中文, 但不推荐
​ echo \$呆萌伐木工;

  1. 大小写: 严格区分大小写

    \$x = '亚瑟';
    echo \$x;
    echo \$X;
    

    变量技巧

    变量技巧

1. 可变变量

将一个变量的值 的、、87作为另一个变量的名字去使用

​ \$山鸡哥 = ‘陈小春’;
​ \$陈小春 = ‘应采儿’;
​ \$应采儿 = ‘何文豪’;

echo \$陈小春;
​ echo \$\$\$山鸡哥;
​ echo ‘


‘;

2.引用变量

传值: 将一个变量A的值 赋给另一个变量B, 变量B会生成一个 新的内存
传址: 将一个变量A的内存地址 赋给另一个变量B, 变量A 和 B 公用同一个内存

传值:
\$a = 100;
\$b = \$a; # 相当于 \$b = 100, 仅仅是将\$a的值 给了\$b
\$b = 500;
echo \$a, \$b;

echo ‘


‘;

传址: 引用变量

\$a = 100;
\$ b = & \$ a; 在变量前加个&;
\$b = 800;
echo \$a, \$b;

八种类型

值: 有8种数据类型
标量
整型 int
浮点型 float
布尔型 bool
字符串 string

​ 复合
数组 array
对象 object

​ 特殊
资源 resource
空 null

整型(int)

整型 int
定义: 整数

  1. 最大整型

    echo PHP_INT_MAX;

     var_dump( PHP_INT_MAX  );
     echo '  ';
    
  2. 如果超过了最大整型?

      将自动转为 浮点型float
     \$a = PHP_INT_MAX;
     \$a = \$a + 1;
     echo \$a;
     var_dump( \$a );
     echo '<hr>';
    
  1. 判断是否为整型: is_int() 返回值: true 是整型 | false 不是整型
    var_dump( is_int(100) );

    var_dump(  is_int(100.5)   );
    echo '<hr>';
    

    进制

                    基数     前缀
    

    二进制 0-1 0b
    八进制 0-7 0
    十进制 0-9
    十六进制 0-9 a-f 0x

任意进制 =>十进制

基数*进制^位数 从后向前, 个位: 0次方 十位: 1次方 百位: 2次方 …

例:

a = 0b110; # 0*2^0 + 1*2^1 + 1*2^2 = 6
\$a = 0b0101;
$a = 0b1110;
echo \$a;
echo ‘ ‘;

a = 012; # 1*8^1 + 2*8^0 = 8 + 2 = 10
\$a = 0306;
echo \$a;
echo ‘ ‘;

a=10 b=11 c=12 d=13 e=14 f=15
\$a = 0x2b;
\$a = 0x10f;
echo \$a;

十进制 => 任意进制

将 十进制 除以 进制数 取余, 最后将所有余数 倒取余
\$a = 10; # 二进制: 1010
\$a = 25; # 二进制: 11001

​ \$a = 10; # 八进制: 12
​ \$a = 25; # 八进制: 31

​ \$a = 10; # 十六进制: a
​ \$a = 25; # 十六进制: 19

浮点型(float)

浮点型 float 小数

  1. 科学计数法

       XeY = X * 10^Y
    

    2e4 = 2*10^4
    var_dump( 2e4 );

  2. 有效位数: 14位 (整数+小数)
    \$a = 0.1234567890123456789;
    echo \$a;
    echo ‘ ‘;

    \$a = 0.001234567890123456789;

    echo \$a;
    echo ‘ ‘;

    \$a = 123.4567890123456789;

    echo \$a;
    echo ‘


    ‘;

  3. 判断是否为 浮点型: is_float()
    var_dump( is_float(10) );
    var_dump( is_float(10.5) );
    var_dump( is_float(10e5) );

  4. 浮点运算
    小数 转为二进制时, 不一定准确

    == 比较两边的值是否相等
    

    if( 1 + 1 == 2 ){

     echo 'Yes';
    

    }else{

     echo 'No';
    

    }

    echo ‘


    ‘;

    0.1 + 0.2 的结果: 0.300000000000000000000000000000000001

    if( 0.1 + 0.2 == 0.3 ){

     echo 'Yes';
    

    }else{

     echo 'No';
    

    }

布尔型(bool)

布尔型 bool

  1. 值: true / false
            代表两种极端的状态

​ 2. 作用: 用于做判断, 比较 …

​ 3. 判断是否为布尔型: is_bool()
var_dump( is_bool(1) );
var_dump( is_bool(0) );
var_dump( is_bool(true) );
var_dump( is_bool(false) );

7种与false直接等价

4. 有7种与false等价值, 除了这7种以外, 都认为与true等价:

   1. false
   2. 0
   3. 0.0
   4. 空 null
   5. 空字符串 '' 或  零字符串'0'
   6. 空数组  array()
   7. 未定义变量

if( false == false ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == 0 ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == 0.0 ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == null ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == ‘’ ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == ‘0’ ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == ‘00’ ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == ‘ ‘ ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == ‘0.0’ ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == array() ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

if( false == \$xxxx ){
echo ‘等价 ‘;
}else{
echo ‘不等价 ‘;
}

字符串(string)

字符串 string

  1. 定义: 能够表达任意字母, 数字, 标点, 汉子 … 描述

  2. 格式:
    单引号

         双引号
         heredoc结构
    

    \$a = ‘我妈曾说我小时候总喜欢把小弟弟往插座里面插 ‘;
    var_dump(\$a);

     \$a = "我妈曾说我小时候总喜欢把小弟弟往插座里面插 ";
    

    var_dump(\$a);

              \$a = <<<自定义开始符号

                  字符串内容

      自定义结束符号;

      注意:
      1) 开始符号 和 结束符号 必须保持一致 (不能含有标点)
      2) 开始符号 那一行的后面不能有任何字符, 包括空格
      3) 结束符号 那一行的前面和后面不能由任何字符, 包括空格

      小结:
      单双引号: 适用于 一行
      heredoc: 适用于 多行


​ \$a = <<<老表
​ 焦了, 叫了
​ 浇了, 教了
​ …









123123123123

老表;
echo \$a;

判断是否为…
  1. 判断是否为字符串: is_string()
    var_dump( is_string(100) );
    var_dump( is_string(‘100’) );
    echo ‘
    ‘;
  1. 判断是否为数字 或 数字字符串: is_numeric()

     var_dump( is_numeric(100) );
    

    var_dump( is_numeric(‘100’) );
    var_dump( is_numeric(‘abc’) );
    var_dump( is_numeric(‘10.5’) );
    var_dump( is_numeric(‘10e5’) );
    echo ‘


    ‘;

  2. 判断是否为标量: is_scalar()

     var_dump( is_scalar(100) );
    

    var_dump( is_scalar(100.5) );
    var_dump( is_scalar(true) );
    var_dump( is_scalar(‘asdf’) );
    var_dump( is_scalar(null) );
    echo ‘


    ‘;

  3. 字符串长度:

       上限: 2G
    

    var_dump(‘123abc’);
    var_dump(‘123abc的’);

    常见面试题: 单双引号的区别
    单:

       不识别变量
       不识别转义字符, 但识别转义 转义字符
    

​ 双:
识别变量
识别转义字符

​ 共性:
单双引号不能自插, 可以互插

​ heredoc结构: 支持变量, 支持转义字符, 支持单双引号

\$name1 = ‘猪’;
\$name2 = ‘熊猫’;
\$desc = ‘猪和熊猫因为脸长得不一样, 命运截然不同, 一个被宠, 一个被桶’;

\$desc = ‘\$name1和\$name2因为脸长得不一样, 命运截然不同, 一个被宠, 一个被桶’;
\$desc = “\$name1 和 \$name2 因为脸长得不一样, 命运截然不同, 一个被宠, 一个被桶”;
\$desc = “{\$name1}和{\$name2}因为脸长得不一样, 命运截然不同, 一个被宠, 一个被桶”;
分析: {} 避免与{}外的文字冲突, 只识别大括号内的变量名
echo \$desc;
echo ‘


‘;

转义字符:
转义符: \
将普通字符 转化为 特殊字符
将特殊字符 转化为 普通字符
常见:
\n 换行
\r 回车
\t 制表符 Tab

转义转义字符

   \'
   \"
   \\$
   \\
   ...

\$desc = ‘猪和熊猫因为脸长得不一样, 命运截然不同. \n 一个被宠, 一个被桶’;
\$desc = “猪和熊猫因为脸长得不一样, 命运截然不同. \n 一个被宠, 一个被桶”;
\$desc = ‘猪和熊猫因为脸长得不一样, 命运截然不同. \’ 一个被宠, 一个被桶’;
echo \$desc;
echo ‘


‘;

\$desc = ‘猪和熊猫因为脸长得不一样, 命运截然不同. ‘ 一个被宠, 一个被桶’;
\$desc = ‘猪和熊猫因为脸长得不一样, 命运截然不同. “ 一个被宠, 一个被桶’;
\$desc = “猪和熊猫因为脸长得不一样, 命运截然不同. “ 一个被宠, 一个被桶”;
\$desc = “猪和熊猫因为脸长得不一样, 命运截然不同. ‘ 一个被宠, 一个被桶”;
echo \$desc;

数组(array)

数组 array

格式:
$数组名[ 键 ] = 值
$数组名 = [ 键1=>值1, 键2=>值2, … ]
$数组名 = array( 键1=>值1, 键2=>值2, … )

  1. 定义: 作为容器, 容纳任何数据. 空间大小 视内存决定, 理论上无上限

  2. 格式:

       格式1: \$变量名[] = 值
    
       格式2: \$变量名 = [值1, 值2, 值3, ...]
    
     形态:
         键 => 值
    
         键的其余称呼: 下标, 索引, 偏移量
      键的类型: int / string,     如果填写的不是int/string, 那么PHP强制转为int/string
         值的类型: 任意类型
    

    格式1:
    \$girl[] = ‘林志玲’;
    \$girl[] = ‘迪丽热巴’;
    \$girl[] = ‘苍井空’;
    \$girl[] = ‘小泽玛利亚’;

     echo \$girl;         # echo 不适合输出数组
    

    var_dump(\$girl);

    格式2:
    \$boy = [‘鄂胜’, ‘何文豪’, ‘黄磊’, ‘刘长建’];
    var_dump(\$boy);

  1. 操作数组

    3.1 访问数组, 通过 键 来访问
    var_dump( \$girl[2] );
    echo \$girl[2];

    3.2 更新数组, 通过 键 来更新

       如果键 已存在, 那就是更新
     \$girl[2] = '赵丽颖';
     var_dump(\$girl);
    
            如果键 不存在, 那就是添加
     \$girl[9] = '范冰冰';
     var_dump(\$girl);
    
     3.3 删除数组, 通过 键 来删除
     unset( \$girl[9] );
     var_dump(\$girl);
    
    1. 判断是否为数组: is_array()

对象(object)

对象 object
一切皆对象

格式:
\$变量名 = new 类名
类名: stdClass 目前只要记住这个就可以了
\$a = new stdClass;
var_dump(\$a);

判断是否为对象: is_object()
var_dump( is_object(\$a) );

资源(resource)

资源 resource
所有的文件 都是资源

获取资源的方式之一:

            打开一个文件, 返回值: 资源

\$变量名 = fopen(‘文件地址’, ‘r’)

\$a = fopen(‘./01-array.php’, ‘r’);
var_dump(\$a);

判断是否为资源
var_dump( is_resource(\$a) );

空(null)

空 null

  1. 定义: 划分一个内存, 但是内存中什么都没有

  2. 作用: 暂时不知道啥用, 都是为了以后准备的

    \$a = null;

    \$b = null;

    \$b = \$b + 10; # 没有\$b = null 声明, 那么此处的\$b就会报错
    echo \$b;
    echo ‘


    ‘;

有3种值 直接为null
   1) 直接赋值 null
    \$a = null;
    var_dump(\$a);

​ 2) 被删除的变量
​ \$b = 100;
​ unset(\$b); # unset() 释放变量, 删除变量
​ var_dump(\$b);

   3) 未定义的变量
    var_dump(\$c);
  1. 判断是否为null: is_null()

##

三个常见函数

一个函数没有返回值时, 强行接收, 则只会接收到 null

unset()

​ 释放变量, 释放内存

​ 内存:每定义一个变量, 系统就会分配一个内存给变量
​ 当内存没有被 任何变量所引用时, 就会自动释放

empty()

​ 判断变量是否为空, 如果为空=>返回true
如果非空=>返回false
且只要与false等价, 那就是空
​ \$a = 0;
​ \$a = 0.0;
​ \$a = false;
​ \$a = true;
​ \$a = ‘’;
​ \$a = ‘0’;
​ \$a = array();
​ \$a = null;
​ var_dump( empty(\$a) );
​ var_dump( empty(\$b) );

isset()

​ 判断变量是否设置, 如果设置=> 返回true
如果未设置=> 返回false
只要值直接为 null, 就是未设置 ,( 只有null 和 未定义变量是没有设置过 )

​ \$a = 0;
​ \$a = null;
​ \$a = ‘’;
​ var_dump( isset(\$a) );
​ var_dump( isset(\$b) );

输出的四种方式

请写出有哪几种输出, 并写出他们的区别

1. echo

支持int, float, string, resource 的输出
​ 属于 语法结构, 不是函数

2. print | print()

支持 int, float, string, resource的输出
​ 可语法结构,

​ 可函数print( )
​ 返回值: int

3. print_r()

除了bool 和 null不能输出, 其余都可以输出
​ 函数
​ 返回值: bool

当具有大批量数据需要打印时, 可以嵌套 pre标签
echo ‘‘;

例:

​ \$arr = [ ];

​ for(\$i=0; \$i<50000;\$i++){

​ \$arr[ ] = \$i;

​ }

​ echo ‘

‘;
​ print_r( \$arr );
​ echo ‘
‘;

4. var_dump

支持任意类型
​ 函数
​ 无返回值

print_r() 和 var_dump()
除了支持类型不一样以外:
print_r 能输出的个数: 任意个
var_dump 能输出的个数: 128个

类型转换

autoType(类型的自动换转)

弱类型: 数据类型可做隐式转换
强类型: 数据类型不可做隐式转换

隐式转换: 偷偷将数据类型 进行转换

类型的自动换转
var_dump( 10 + 10.5 );
echo ‘


‘;

bool -> int

var_dump( true + 10 ); 11 true -> 1
var_dump( false + 10 ); 10 false -> 0

bool -> float

var_dump( true + 10.5 ); 11.5 true -> 1.0
var_dump( false + 10.5 ); 10.5 false -> 0.0
echo ‘


‘;

string -> int/float

从前向后, 碰到第一个非数字时, 保留前面的数字, 后面全部抛弃
var_dump( ‘100’ + 200 ); 300 ‘100’ => 100
var_dump( ‘abc’ + 200 ); 200 ‘abc’ => 0
var_dump( ‘100abc’ + 200 ); 300 ‘100abc’ => 100
var_dump( ‘abc100’ + 200 ); 200 ‘abc100’ => 0
var_dump( ‘1a2b3c’ + 200 ); 201 ‘1a2b3c’ => 1
echo ‘


‘;

string -> float

从前向后, 碰到第一个非数字时(除了第一个. 和 e), 保留前面的数字, 后面全部抛弃
var_dump( ‘10.5’ + 100 ); 110.5 ‘10.5’ => 10.5
var_dump( ‘a.b’ + 100 ); 100 ‘a.b’ => 0
var_dump( ‘1a.b’ + 100 ); 101 ‘1a.b’ => 1
var_dump( ‘1.ab’ + 100 ); 101 ‘1.ab’ => 1.0
var_dump( ‘1eab’ + 100 ); 101 ‘1eab’ => 1
var_dump( ‘1e2ab’ + 100 ); 200 ‘1e2ab’ => 100.0
var_dump( ‘1.2.3’ + 100 ); 101.2 ‘1.2.3’ => 1.2
var_dump( ‘1.2e3’ + 100 ); 1300 ‘1.2e3’ => 1200
var_dump( ‘1e2e3’ + 100 ); 200 ‘1e2e3’ => 100.0
echo ‘


‘;

int -> float

var_dump( 10 + 10.5 ); 20.5 10 => 10.0

dataType( 强制类型转换)

\$str = ‘一见钟情和日久生情有什么区别? 一个靠脸, 一个靠技术’;

1. 临时转换

1.1 通过运算符

​ var_dump( (int)\$str );
​ var_dump( (float)\$str );
​ var_dump( (string)\$str );
​ var_dump( (bool)\$str );
​ var_dump( (array)\$str );
​ var_dump( (object)\$str );
​ var_dump( (resource)\$str );
​ var_dump( (null)\$str );
​ var_dump( \$str );
​ echo ‘


‘;

1.2 通过函数

​ var_dump( intval(\$str) );
​ var_dump( floatval(\$str) );
​ var_dump( boolval(\$str) );
​ var_dump( strval(\$str) ); # 记住这里是 str 而不是 string
​ var_dump( \$str );
​ echo ‘


‘;

2. 永久转换

​ settype( 变量, 类型 )
​ var_dump(\$str);

​ settype(\$str, ‘int’);

​ var_dump(\$str);

​ settype(\$str, ‘string’);

​ var_dump(\$str);

*常量

常量值恒定不变的

格式

格式1: const 常量名 = 常量值
格式2: define(常量名, 常量值, bool)
false : 区分大小写, 默认
true: 不区分大小写

特性:
      **常量不能重新赋值**
      **常量不能重新定义**
      **常量名不能重复**
      **常量区分大小写**, **推荐大写**
预定义常量
      PHP_OS                 当前所在的操作系统
      PHP_VERSION            当前所在的PHP版本
      M_PI                 圆周率
      PHP_INT_MAX            最大整数
魔术常量
      \__FILE__             文件所在的盘符地址
      \__LINE__             当前所在的行数
常量的作用域
      **常量相对于函数, 没有作用域, 外部常量 可以直接在函数内部使用**
      **const不能直接在函数内部定义**
      **define**可以在函数内部定义

运算符

算术运算符(模)

​ 算术运算符
​ + -
​ * 乘法
​ / 除法 第二位数不能为

​ % 余数

​ 要的范围在 结果范围: x ~ y
​ 套用公式: %(y-x+1) + x

​ 求奇偶数,则 %2

​ 结果范围: 0~1

​ 余数为0 即为偶数
​ 余数为1 即为奇数


​ 求任意数字的 个位数 0 ~ 9
​ \$a = 123;
​ var_dump( \$a % 10 ); 10的1次方

​ 求任意数字的 最后两位 00 ~ 99
​ \$a = 123;
​ var_dump( \$a % 100 ); 10的2次方

​ 求任意数字的 最后n为
​ %10的n次方

自增/自减运算符

​ 自增/自减运算符

​ ++ 变量a自己给自己+1
​ a++ 先返回a, 再给a+1
​ ++a 先给a+1, 再返回a

​ – 变量自己给自己-1
​ a– 同上
​ –a 同上

字符串拼接符

拼接符 . 小数点

主要用于:
字符串.变量
变量.字符串
变量.变量

单引号 不解析变量,所以拼接
\$name = ‘老王’;
echo ‘今天晚上’.\$name.’说了, 带大家去见见世面, 走一趟天上人间 ‘;

单引号的速度 比 双引号的快
为了整个项目的运行速度考虑:
如果变量较少, 推荐用单引号, 变量用拼接
如果变量较多, 使用双引号, 变量用{}包起来

赋值运算符

赋值运算符
= 将 = 右边的 赋给 左边的
+= a += b ==> a = a + b
-= 同上
*= 同上
/= 同上
%= 同上
.= a .= b ==> a = a . b

​ \$a = 10;
​ \$b = 5;
​ \$a .= \$b;
​ echo ‘\$$a = ‘.\$$a 请问此时的 \$a 是什么数据类型???
​ echo ‘\$b = ‘.\$b;

​ var_dump( \$a );

​ D:\wamp\www\s84\kejian\0114\09-equal.php:29:string ‘105’ (length=3)

​ 结果: \$a 是 string, 不是int了

比较运算符

​ == 判断两边的值是否相等
​ === 全等: 判断两边的值是否相等 且 数据类型相等
​ != 判断两边的值 是否不等
​ !== 不全等: 只有全等时为false, 其余都是true

​ 注意点: 所有的比较结果: 都是bool值

​ 例子:

​ var_dump( 1 === true );
​ var_dump( 1 === 1 );
​ var_dump( ‘’ === ‘0’ ); no

逻辑运算符

注意点: 所有的比较结果: 都是bool值

​ 逻辑与 && 两边为真即为真, 一边为假即为假

​ 逻辑或 || 一边为真即为真, 两边为假即为假

​ 逻辑非 ! 真即是假, 假即是真

​ var_dump( 1 && 2 );
​ var_dump( 1 || 2 );

​ 高阶逻辑
​ 如果前面的运算已经确定了最终结果, 那么后面的就不再执行了
​ $a = 5;
​ $b = 0;
​ var_dump(\ $a && \$b = 10 );
​ var_dump($a, $b);

​ $a = 0;
​ $b = 5;
​ var_dump( \$a && \$b = 10 ); 因为\$a 已经确定了最终结果, 所以$b=10 根本没运行
​ var_dump($a, $b);

​ \$a = 0;
​ \$b = 5;
​ var_dump( \$a = 10 && \$b = 9 || \$a );
​ var_dump(\$a, \$b);
​ t t t
​ echo ‘


‘;

​ \$a = 0;
​ \$b = 5;
​ var_dump( \$a && \$b = 9 || \$a );
​ var_dump(\$a, \$b);
​ f 0 5

三元运算符

​ 条件表达式? true环境 : false环境;

​ 例子:
​ $lv = 3;
​ $lv = 5.5;
​ $lv = 9.5;
​ echo \$lv < 4? ‘青铜’ : ( \$lv < 5? ‘白银’ : ( \$lv < 6? ‘黄金’ :(\$lv < 7 ?’铂金’:(\$lv < 8 ?’钻石’:(\$lv < 9 ?’大师’:’王者’)))));

​ 三元运算符 仅仅适合 做一些简单判断.

流程控制


  顺序结构: 代码从上往下依次执行
  分支结构: 通过if/switch进行分支选择
  循环结构: 通过while, doWhile, for来循环操作
if

分支写法1:
if( 条件表达式 ) true环境1
分析:
条件 仅仅能影响紧跟在if 后面的一条命令;

​ 例子:

​ if ( false )
​ echo ‘今晚加个鸡腿 ‘;

​ echo ‘今晚搞碗 泪流满面 ‘; #这句话无法被影响

分支写法2:

      if (条件表达式){
          true环境
      }

      分析:
          条件 仅仅能影响后面{} 内的所有代码

​ 例子:

​ if ( false ) {
​ echo ‘给老王加个四喜丸子 ‘;
​ echo ‘给老王送个小飞飞 ‘;
​ echo ‘给老王顺带小柏柏 ‘;
​ }
​ echo ‘送一碗 孟婆汤 ‘;

分支写法3:
if (条件表达式) {
true环境
}else{
false环境
}

      分析:
          条件为真, 则进入true环境, 否则进入 false 环境

​ 例子:
​ if ( false ) {
​ echo ‘让老王给小飞飞按按脚 ‘;
​ }else{
​ echo ‘让小飞飞给老王洗洗脚 ‘;
​ }

分支写法4:

      if( 条件表达式1 ){
           true环境1
      }elseif( 条件表达式2 ){
          true环境2
      }elseif( 条件表达式3 ){
          true环境3
      }...
  分析:
      从 多个条件表达式中, 选择一个满足. (符合先来后到的原则)

​ 例子:

​ $lv = 3;
​ $lv = 5.3;
​ $lv = 80.3;

​ if ( $lv < 3 ) {
​ echo ‘黑铁’;
​ }elseif( $lv < 4 ){
​ echo ‘青铜’;
​ }elseif( $lv < 5 ){
​ echo ‘白银’;
​ }elseif( $lv < 6 ){
​ echo ‘黄金’;
​ }elseif( $lv < 7 ){
​ echo ‘铂金’;
​ }elseif( $lv < 8 ){
​ echo ‘钻石’;
​ }elseif( $lv < 9 ){
​ echo ‘大师’;
​ }else{
​ echo ‘王者’;
​ }

分支写法5:
巢状分支

  if( 条件表达式1 ){
       if ( 条件表达式2 ){
           if ( 条件表达式3 ){
               ...
           }            
       }
  }    

例子:

$sex = ‘女’;
$age = 18;

if ( $sex == ‘男’) {
if ( $age < 30) {
echo ‘处男’;
}else{
echo ‘老司机’;
}
}else{
if ( $age < 30 ) {
echo ‘少妇’;
}else{
echo ‘妇女’;
}
}

switch

​ 例子:

​ $name = ‘盖伦’;
​ $name = ‘剑圣’;

​ switch( $name ){
​ case ‘快乐风男’: echo ‘面对疾风吧 ‘; break;
​ case ‘大司马’: echo ‘回首掏, 走位走位 ‘; break;
​ case ‘盖伦’: echo ‘人在塔在 ‘; break;
​ default: echo ‘404’;
​ }

  swtich($name=标识){
      case '$name=标识1': 代码块;break;
      case '$name=标识2': 代码块;break;
      case '$name标识3': 代码块; break;
      ...
      case '$name标识N': 代码块;break;
  }

​ 无break default
匹配到某一标识, 执行该代码块, 且依次向下执行

 若添加了break
  执行到break时, 立马跳出分支, 后面的代码不再执行

​ 若添加了default

  匹配不到标识时, 默认执行default

循环

while

循环结构

  1. while
  2. doWhile
  3. for

    代码块: 拥有1行 或 多行代码的块. 甚至没有代码

  4. while

    while( 条件表达式 ){

     代码块
    

    }

    分析:

     如果条件为真 -> 则执行1次 代码块 -> 再回到条件表达式 -> 真 -> 再执行1次代码块 ...
     当条件为假 -> 立马结束循环 -> 准备执行循环外的代码
    

    输出 0 - 10
    $i = 0;
    while ($i <= 10) {
    echo $i.’ ‘;
    $i++;
    }
    echo ‘


    ‘;

    输出 0 2 4 6 8 10
    $i = 0;
    while ( $i <= 10 ) {

​ 判断 $i 是否为偶数
if ( $i % 2 == 0) {
echo $i . ‘ ‘;
}

​ $i++;
}
echo ‘


‘;

输出 0~10 之间所有奇数
$i = 0;
while ( $i <= 10 ) {

​ 判断 $i 是否为偶数
if ( $i % 2 != 0) {
echo $i . ‘ ‘;
}

​ $i++;
}
echo ‘


‘;

坑题

$num = 5;
while ( \$i = \$num ){ 当 赋予 false等价值时, 条件认为为 假
echo $i.’ ‘;
$num–;
}
echo ‘


‘;

$x = 5;
$y = 0;
while(\$x && \$y ){
echo $x . ‘ ‘;
$y++;
}
echo ‘


‘;

$x = 5;
while ( $x ) {
echo $x.’ ‘;
$x–;
}
echo ‘


‘;

$x = 5;
while ( –$x ) {
echo $x. ‘ ‘;
$x–;
}
4 2

dowhile

$year = 2019;
echo ‘‘;

for
 for 循环    
 格式for(1初始值;2条件;3 增量){
         执行代码4
     }

执行顺序:
1 243 243 243
2为假时,结束循环

for($i = 0;$i<10; $i++){
echo $i.’ ‘;
}
0~9
echo ‘


‘;

for($i = 0;$i<10;){
echo $i.’ ‘;
$i++;
}
0~9
echo ‘


‘;

初始位置和增量位置可以不写值
$i = 0;
for(;$i<10;){
echo $i;
$i++;

}
0~9;
echo ‘


‘;
条件只是一个变量
for($i=0 ;$i ;$i++){
echo $i++;
}

echo ‘
‘;

for($i = 10;$i -= 2;$i -= 2){
echo $i.’ ‘;
}
8 4
echo ‘


‘;

for($i = 0; $i < 10; $i+2){
echo $i++.’ ‘;
}
0~9

echo ‘


‘;

*多重循环

​ 见ex==>PHP部分

​ for

​ tr

​ td td

​ tr

流程控制符

流程控制符
1.break 立马结束分支/循环,准备执行分支/循环外的代码
2.continue
立马结束当前一轮循环,进入下一轮循环 for 碰到continue,立马进入增量3
while碰到 continue,立马进入条件判断
3.die 立马结束程序
die(内容) 遗言

输出 0~9
for ($i=0; $i < 10; $i++) {
echo $i.' ';
}
echo '<hr>';

输出 0~9, 若碰到5, 则跳过
for ($i=0; $i < 10; $i++) {
if( $i == 5 ){
continue;
echo '123';
}

​ echo $i.’ ‘;
}
echo ‘


‘;

输出 0~9, 若碰到5, 则结束循环
for ($i=0; $i < 10; $i++) {
if( $i == 5 ){
break;
echo ‘123’;
}

.

​ echo $i.’ ‘;
}

echo ‘


‘;

输出 0~9, 若碰到5, 则结束程序
for ($i=0; $i < 10; $i++) {
if( $i == 5 ){
die;
exit;
die(‘我还会回来的’);
exit(‘我还会回来的’);
echo ‘123’;
}

​ echo $i.’ ‘;
}

echo ‘


‘;

function函数

函数作用丶简介

​ 用函数封装一些功能, 重复利用

分类:
系统函数
自定义函数

  格式:
      function 函数名( [参数1, 参数2, ...] )
      {
          函数体
      }

  特性:
      不调用不执行
      函数一旦调用, 那么函数执行之后, 会返回到调用函数的地方

  调用函数:
      函数名()

​ 函数名( 实参 )

函数名规范
  命名规范: 由数字, 字母和下划线组成, 不能以数字开头
  函数名不能重复
  不区分大小写
  命名形式:
      驼峰式命名法: 从第二个单词开始, 首字母大写  
      帕斯卡命名法: 每个单词首字母大写
      下划线命名法: 每个单词用下划线隔开
函数返回值return
  关键字: return
  格式: return 数值
  特性:
      当执行到return时, 立马结束函数, 并返回到调用函数的地方
      可以返回任意类型

  如何一次性返回多个值?           将多个值 包装到数组中, 并返回数组
  强行接收无return的函数?              没有return时, 会接收到null
参数
  形参: parameter    param     定义函数时给的值
  实参: argument     arg         调用函数时给的值

  形参个数 = 实参个数     形参接收实参, 先到的先得
  形参个数 > 实参个数:      多余的形参     1.当成未定义变量     实参加( '' )就不会报错了
                                       2.采用默认值
  形参个数 < 实参个数:      多余的实参, 被抛弃

当 实参个数 不确定时?
func_get_args() 以数组的形式接收全部的实参
func_get_arg(N) 接收下标为N的值
func_num_args() 接收实参 数量总和

变量的作用域 globals

​ 关键词 globals

  全局变量: 在函数外部声明的变量
  局部变量: 在函数内部声明的变量

  全局变量如何在函数内部使用
  通过 \$GLOBALS['变量名']

  局部变量如何在函数外面使用
  在函数里面定义时, 通过global 定义变量

​ 例子:

​ $a = 10; 全局
​ function demo1(){
​ global $b;
​ $b = 20; 局部

通过 $GLOBALS[ 全局变量名 ] 即可在局部环境中使用 全局变量
​ echo $GLOBALS[‘a’];
​ }

​ demo1();

在全局环境中, 可以输出 global修饰的 局部变量
​ echo $b;

静态变量 static
  关键词: static
  作用: 在函数结束时, 不会销毁, 当再次调用此函数时, 会直接使用上一次的静态值
  注意: 对于不同的函数, 相同静态变量名, 互不影响

​ 例子:

​ function demo(){
​ $a = 10;
​ echo $a.’ ‘;
​ $a++;
​ }

​ demo();
​ demo();

​ 10 10

​ echo ‘


‘;

​ function demo2(){
​ static $b = 50;
​ echo $b.’ ‘;
​ $b++;
​ }

​ demo2();
​ demo2();
​ demo2();

​ 50 51 52

变量技巧/函数技巧
// 变量技巧
    // 可变变量: 将一个变量的值 作为另一个变量名 来使用
    // 引用变量     


// 函数技巧
    // 可变函数: 将一个变量的值 作为函数名 来使用
    // 引用函数
    // 可变函数 
    function demo(){
        echo '我是 demo函数';
    }

    // demo();

    $a = 'demo';
    echo $a;
    echo '<br>';
    $a();  //  ===>  demo()
    echo '<hr>';

    function demo2($x){
        $x++;
        echo 'x = '.$x.'<br>';
    }

    $a = 10;
    demo2($a);
    echo 'a = '.$a.'<br>';


    // 可变函数 
    function demo(){
        echo '我是 demo函数';
    }

    // demo();

    $a = 'demo';
    echo $a;
    echo '<br>';
    $a();  //  ===>  demo()
    echo '<hr>';


    function demo2($x){
        $x++;
        echo 'x = '.$x.'<br>';
    }

    $a = 10;
    demo2($a);
    echo 'a = '.$a.'<br>';


数组

基础知识点

分类:
索引数组: 下标为int
关联数组: 下标为string

格式:
\$数组名[ 键 ] = 值

​ \$数组名 = [键=>值, 键=>值, …]

​ \$数组名 = array(键=>值, 键=>值, …)

:

  1. 键的别称: 下标, 索引, 偏移量
  2. 若 下标不是int 或 string , 则会强制转为 int 或 string
    . 下标等价值:

     true = 1 = 1.0 = 1.xxxx
    

    false = 0 = 0.0 = 0.xxxx = ‘0’
    null = ‘ ‘ = 未定义变量
    非法键: 数组 , 资源 , 对象 , 有就报错

  3. 下标若未设置, 默认从0开始
    已存在部分下标, 默认从已有的最大int下标开始 + 1

值:可以为任意类型,如果值也是数组,那么将会形成多维数组


数组操作

        查询数组值: 通过数组下标来查找值  $arr[ 下标 ]
                                     $arr[下标1][下标2]

        修改数组值: 通过已存在的数组下标来修改值  $arr[ 下标 ] = 值
        新增数组值: 通过不存在的数组下标来新增值  $arr[ 下标 ] = 值
            删除数组值: 通过已存在的数组下标来删除值  unset($数组名)
多维数组

​ 在数组中, 值设为数组, 即为多维数组

​ $a = [
​ ‘吴彦组’ => [‘成龙’, ‘李连杰’, ‘甄子丹’, ‘吴京’],
​ ‘佛组’ => [‘释迦牟尼’, ‘象猴得度’, ‘割肉喂鹰’, ‘佛说前身’],
​ ‘达摩老组’ => [‘易筋经’, ‘洗髓经’, ‘童子功’, ‘金钟罩’],
​ ];

​ 删除成龙 unset( \$a[‘吴彦组’][0] );

指针函数:

​ current() 获取当前指针所指向的值
​ key() 获取当前指针所指向的键
​ next() 将指针下移一位
​ prev() 将指针上移一位
​ reset() 将指针重置到第一位
​ end() 将指针重置到最后一位
​ each() 获取当前指针所指向的键和值, 且指针自动下移一位

​ 超出指针范围, 返回值 返回false, 键返回null

字符串数组

​ 当做索引数组来看待
​ 超出指定下标, 返回 空字符串

html和php结合写法

foreach遍历

​ 不需要考虑初始值, 不需要考虑增量, 不需要考虑条件

​ 擅长遍历 非索引,非规律数字的数组
​ foreach( 数组名 as 键 => 值 ){
​ 代码块
​ }

​ 若只需要值, 不需要用键, 可以简化写法
​ foreach( 数组名 as 值 ){
​ 代码块
​ }

​ foreach( \$a as \$x => $y ){
​ echo \$x.’======>’.\$y;
​ echo ‘
‘;
​ }
​ 分析:
​ $x 只能接受当前一轮的键
​ $y 只能接受当前一轮的值

​ 每一次循环, 都只能接收一个键或值

html和php结合写法

​ 不需要拼接html, 只要PHP直接套html
​ foreach 和 html 的混合写法

​ <?php foreach(): ?>

​ html 原生代码 不需要echo的

​ <?php endforeach ?>

​ if 和 html 的混合写法
​ 写法1:
​ <?php if(): ?>
​ html 原生代码 不需要echo的
​ <?php endif ?>

​ 写法2:
​ <?php if(): ?>
​ html 原生代码 true环境
​ <?php else: ?>
​ html 原生代码 false环境
​ <?php endif ?>

​ 写法3:
​ <?php if(): ?>
​ html 原生代码 true环境
​ <?php elseif(): ?>
​ html 原生代码 false环境
​ <?php endif ?>

*/

双foreach例题
     $orders = [
         ['orderNum'=>1,'time'=>'2019-01-21'],    
         ['orderNum'=>2,'time'=>'2019-01-22'],    
     ];
    $ordersgoods = [
        ['orderNum'=>1,'goodsName'=>'小米手机','price'=>666,'num'=>1],    
        ['orderNum'=>2,'goodsName'=>'小米电脑','price'=>999,'num'=>2],    
        ['orderNum'=>2,'goodsName'=>'Mac Pro','price'=>1000,'num'=>2],    
     ];

twoforeach

  <div class="box">
      <div class="line" style="border:1px solid black">
          <?php foreach ($orders as $k => $v): ?>
                  <div class="head">
                      订单号:<?= $v['orderNum']?>时间:<?= $v['time']?>
                  </div>
          <div class="body" style="margin-left:20px;">
                  <?php foreach ($ordersgoods as $key => $value): ?>
                      <?php if ( $value['orderNum'] == $v['orderNum']): ?>

                      <div>
                          商品:<?= $value['goodsName']?>|价格:<?= $value['price']?>|数量:<?= $value['num']?> 
                      </div>
                      <?php endif ?>
                  <?php endforeach ?>
          </div>
      <?php endforeach ?>

      </div>
  </div>

预定义数组


​ \$GLOBALS 存放所有全局可用的变量

​ \$_GET 用于接收所有明文传输的值

​ \$_POST 用于接收所有密文传输的值

​ \$_COOKIE 用于存放客户端的cookie信息

​ \$_SESSION 用于存放服务端的session信息

​ \$_FILES 用于接收上传的文件

​ \$_REQUEST 用于get, post , cookie的值

​ \$_SERVER 用于存放服务器相关的信息

​ HTTP_HOST 主机

​ HTTP_USER_AGENT 获取终端, 浏览器版本

​ HTTP_REFERER 获取上一级来源地址

​ SERVER_ADDR 服务器IP

​ REMOTE_ADDR 客户端IP

​ SERVER_SOFTWARE 服务器环境

​ SERVER_PORT 服务器端口

​ SCRIPT_FILENAME 服务器脚本地址(盘符形式)

​ SCRIPT_NAME 脚本地址(网址形式)

​ REQUEST_URI 请求地址( 带参数 )

​ REQUST_METHOD 请求方法

​ REQUEST_STRING 请求参数

GET丶POST传输冲突

​ 前端: method=get时, action带参数
​ 后端: $_GET 只接收 表单值
​ action的参数 被抛弃

​ 解决方案:
​ action的参数, 设置为 隐藏域(name=”下标”,value=”值” )
​ $_GET 依旧接收 表单值

​ 前端: method=post时, action带参数
​ 后端: $_GET 只接收到 参数
​ $_POST 只接收到 表单值

多上传文件5个条件:

​ 想要$_FILES接收到上传的文件, 必须要满足以下3个条件:

​ form表单 必须要有enctype = multipart/form-data

​ form表单 method = post

​ file表单 name 必须要有值

​ file表单 name 值后面加[]

​ file表单属性:multiple

正则


表达式: 用某种模式去匹配字符串的一个公式

功能: 用于字符串的查找与替换

组成: 由正规字符和一些特殊字符组成

语法规则

定界符: ## {}

​ 原子: 可见原子和不可见原子

元字符:

原子筛选方式:

| 匹配俩个或多个分支选择

[ ] 匹配中括号中的任意一个原子

[ ^ ] 匹配除了中括号的原子之外的其他任意原子

原子的集合:

\d 匹配任意一个十进制数字, 即[ 0-9]

\D 匹配任意一个非十进制数字

\s 匹配不可见原子

​ \S 匹配可见原子

\w 匹配任意一个数字 字母或者下划线

\W 匹配任意一个非数字 字母或者下划线

. 匹配除换行符以外的任意字符

* 匹配0次, 1次或者 多次其前面的原子,即 { 0, }

+ {1, }

? {0, 1}

边界控制符,模式单元和模式选择符

^ 匹配字符串开始的位置

\$ 匹配字符串结尾的位置

() 匹配其中的整体为一个原子

(|) 匹配其中的俩个或更多的选择之一

模式修正符:

U 贪婪懒惰转换

x 忽略空白

i 不区分大小写

u 把中文当做一个原子看待

单次匹配

preg_match(正则 , 对象,匹配结果)

返回值: 成功匹配几个 true flase

​ 成功=1

​ 失败=0

​ 例子:

// 检测是否含有大写字母
$preg = ‘/[A-Z]/‘;

\$total = preg_match(\$preg, \$str, $result);
var_dump($total); => 1或0
var_dump($result);=>过了的值以数组接收,没过就是空

检测字符串中 既有数字, 又有小写字母, 还有大写字母
$str = ‘aaaaaaaa’;
$preg = ‘/[0-9][a-z][A-Z]/‘;

$a = preg_match(‘/\d/‘, \$str);
$b = preg_match(‘/[a-z]/‘, \$str);
\$c = preg_match(‘/[A-Z]/‘, $str);
\$res = $a &&\$b && \$c;
// 若 $res 为 true ,则证明 3个条件都满足了
// 若 $res 为 false,则证明 3个中至少有1个没满足

多次匹配

一般用于统计

​ preg_match_all(正则, 对象, 匹配结果)

返回值: 成功匹配了几个 成功>=1

​ 失败=0

​ 一般用于看有几个符合的值,多少个字母,都少个数字,或者str有多长

​ 例子:

    统计$str 有多长

    $str = 'i love 老母鸡找上了小母鸡';

    $preg = '/./u';  =>.表示匹配str里的任意一个原子,如果加上小写u那么将会将汉子当成一个原子,否则默认就是三个原子

    $total = preg_match_all($preg, $str, $result);

    var_dump($total);

    var_dump($result);

    echo strlen($str);


    只获取字符串中的所有汉字  \x{4e00} ~ \x{9fa5}

    $preg = '/[\x{4e00}-\x{9fa5}]/u';

    $total = preg_match_all($preg, $str, $result );

    echo $total;

    var_dump($result);

正则敏感字替换

​ preg_replace(正则,替换值,对象)

​ 例子:

​ $str = ‘MMP, 你是不是脑残啊, 脑子是不是不好使啊, MMP’;

​ // 敏感词库
​ $keywords = [‘MMP’, ‘脑残’];

​ foreach(\$keywords as $v){
​ // 1. 统计 $v 占几位(匹配所有的原子,并将一个汉子当成一个原子)
​ \$num = preg_match_all(‘/./u’, $v);

​ // 2. 将 重复 num次
​ \$star = str_repeat(‘
‘, $num);

​ // 3.将重复的* 替换成要修改的敏感词
​ \$str = preg_replace(“/{\$v}/“, \$star, $str);
​ }

​ echo $str;

正则过滤

​ preg_grep(正则,数组)

​ 例子:

​ $time =[

​ ‘2019-01-23’,
​ ‘2019/01/23’,
​ ‘2019.01.23’,
​ ‘2019.01/23’,
​ ‘2019-01/23’,
​ ‘2019-01.23’,
​ ‘2019-01?23’,
​ ‘201901?23’,
​ ‘2019
01*23’,

​ ]

​ =>不符合\$preg的将被全部抛弃,只留下符合的

​ $preg = ‘/\d{4} [-\/\.] \d{2} [-\/\.] \d{2}/x’;
​ \$res = preg_grep(\$preg, $time);
​ var_dump($res);

后向引用: \1

​ 后面的引用前面的值:

​ 用()将正则包起来后面用\1,就是代表使用被()包起来的正则.

​ 例如 ‘2019-01-23’ 2019后面时-那么01后面也必须是-,01后面的-就可以用\1代表前面的正则.

模式单元( )

​ 功能1:将()内容当成一个整体,即一个大院子

​ 功能2:()内的内容将被送进子模式组

​ 取消模式单元:

​ 正则后面加?: 例如(?:正则内容)

项目验证

邮箱正则
$e = '11111@xx.com';        

$preg = '/^  [0-9a-zA-Z]    {2,16}   @  [0-9a-zA-Z]{2,8} .   (com|cn|edu|net|org)     $/x';

$res = preg_match($preg, $e, $result);

if( $res ){
    echo '邮箱格式正确, 邮箱为: '.$result[0];
}else{
    echo '邮箱格式不正确';
}    
手机正则

$tel=18317045591

$preg = '/^1(3\d|4[5-9]|5[0-35-9]|66|7[013-8]|8\d|9[89])\d{8}$/';

if( !preg_match($preg, $tel) ){
    echo '您的手机号码格式不正确';
    重定向
    echo '<meta http-equiv="refresh" content="3; url='.$_SERVER['HTTP_REFERER'].'">'; 
    die;
    equiv    相等的,等价物
    refresh    使恢复,使振作;
    content 内容

昵称验证
// 2. 昵称验证
$nickname = empty($_POST['nickname'])?null:$_POST['nickname'];
// 长度: 1-10    支持: 中英文, 数字    中文区间:  \x4e00 ~ \x9fa5
$preg = '/^[a-zA-Z0-9\x{4e00}-\x{9fa5}]{1,10}$/u';
if(  !preg_match($preg, $nickname)){
    echo '昵称格式错误';
    echo '<meta http-equiv="refresh" content="3;             url='.$_SERVER['HTTP_REFERER'].'">';die;
}
密码验证
// 2. 验证数据
// 密码验证
if( empty($data['pwd']) ){
    unset($data['pwd']);
    unset($data['repwd']);
}elseif(  $data['pwd'] != $data['repwd'] ){
    echo '两次密码不一致';
    echo '<meta http-equiv="refresh" content="3; url='.$_SERVER['HTTP_REFERER'].'">'; die;
}else{
    // 复杂度  ( 密码必须要有  小写, 大写, 数字, 长度至少6位, 至多16位 )
    $preg = '/^.{6,16}$/';
    if( !preg_match($preg, $data['pwd'])  ){
        echo '密码长度不够';
        echo '<meta http-equiv="refresh" content="3; url='.$_SERVER['HTTP_REFERER'].'">'; die;
    }
    $a = preg_match('/\d/', $data['pwd']);
    $b = preg_match('/[a-z]/', $data['pwd']);
    $c = preg_match('/[A-Z]/', $data['pwd']);
    $res = $a && $b && $c;

    if(!$res){
        echo '密码格式不正确';
        echo '<meta http-equiv="refresh" content="3; url='.$_SERVER['HTTP_REFERER'].'">'; die;
    }

    // 完善密码
    unset($data['repwd']);
    $data['pwd'] = md5($data['pwd']);
}

时间

时间函数
date_default_timezone_set(‘PRC’) 获取中国时区:PRC
time( ) 获取时间戳
date(‘格式’,时间戳) 格式化时间
Y (year) 4位年份
y 2位年份
m (month)
d (day )
H (hour) 小时,24小时制 (h12小时)
i (minute)
s(second)
z 今天是几年第几天
W(week) 本周是今年第几周
t 本月一共多少天
w w: 数字型的星期几,从”0(星期天)”至”6(星期六)”
mktime(时,分,秒,月,日,年) 创建时间点(返回的时一个时间戳)
strtotime(‘时间字符串’) 字符串转时间戳

创建时间点

​ mktime(时,分,秒,月,日,年)

​ 返回值: 时间戳

​ 例: $birthday = mktime(11, 11, 11, 6, 20, 1994);

​ $now = time( );
​ \$diff = \$now - \$birthday;
​ echo “老王目前已经活了 {$diff} 秒

字符串转时间戳

​ strtotime(‘时间字符串’)

​ 例:5天后

​ echo date(‘Y-m-d H:i:s’, strtotime(‘5 day’) );

面试题:

请用最短的代码 获取昨天的时间

​ echo strtotime(‘-1 day’);

其返回值: 时间戳

微秒 microtime
microtime(true)

PHP错误

错误类型

PHP程序的错误发生一般属于以下3种领域:
语法错误 若文件中, 有任意一行代码发生语法错误, 那么整个文件一行代码都不会运行
运行时错误 有些运行时错误, 会终止程序的运行.有些运行时错误, 不会终止程序的运行
逻辑错误 最麻烦的错误, 第一不会提示错误, 第二不会终止程序是 人的问题

错误级别

错误级别
error 1 致命错误, 终止程序致命错误, 终止程序
warning 2 警告错误, 不会终止程序
notice 8 提示错误, 不会终止程序

屏蔽错误

屏蔽错误 原理 例子
方法1: @ : 错误抑制符 哪边变量报错, 就在哪里加@. 仅限于小代码块范围使用 echo @$a;
方法2: error_reporting() 函数来屏蔽 函数后面的错误提示. 位置: 靠前 error_reporting(E_ALL ^E_WARNING); // 除了 warning 不报, 其余都报
方法3 ini_set() 临时改变”配置文件” ini_set(‘error_reporting’, E_NOTICE)或者ini_set(‘error_reporting’, 8);
方法4 修改配置文件 通过直接 修改配置文件, 来屏蔽错误提示 (影响到整个服务器) 1. error_reporting = 常量 2.display_errors = On/off 开关错误提示(完成后需要重启服务器)​

如何屏蔽错误:

​ 仅限本文件:

方法一: 通过@抑制符 只能抑制一个变量的错误

方法二: error_reporting() 从当前代码向下全部抑制

​ E_ALL 显示所有错误

​ 0 屏蔽所有错误

​ E_ERROR 只显示error级错误

​ E_WARNING 只显示warning级错误

​ E_ALL ^E_NOTICE 除了notice不报,其他都报

​ E_ALL & ~E_NOTICE 除了notice 不报,其他都报

方法三: ini_get() 获取配置

​ ini_set() 设置配置

相对于整个WWW目录

​ 方法一: 修改配置文件

​ display_errors = On 打开错误提示

​ Off 关闭错误提示

​ 方法二:

​ error_reporting = ( 函数值)

自定义错误&生成错误日志

自定义错误
trigger_error(报错信息报错类型)
E_USER_ERROR
E_USER_WARNING
E_USER_NOTICE
错误日志
error_log(报错信息, 消息类型(3:将错误信息填写入到目标文件),目标文件 )

自定义错误和错误日志结合例子:

if($b == 0){    
    $msg = '第二位参数不能为0 ';
    $type = E_USER_WARNING;

    $now = date('Y-m-d H:i:s');
    $timezone = date_default_timezone_get();
    $file = __FILE__;
    $line = __LINE__;
    // 在 txt文档中, 换行是通过 \r\n 来实现的
    $message = "[ {$now} {$timezone} ] PHP {$msg}  in {$file} on line {$line} \r\n \r\n";
    error_log($message, 3, './logs.txt');

    trigger_error($msg, $type);
}else{
    echo $a / $b;
}

排除错误

​ 缩小错误范围
​ 断点法: 通过 die 来终止程序, 并输出之前的相关变量, 来判断是否有问题
​ 注释法: 通过 注释 来屏蔽局部程序

文件


文件属性

文件属性 返回值
file 文件
dir 文件夹, 目录
filetype( ) 获取文件的类型 类型 常见以 file 和 dir 居多,文件不存在, 则返回false
filesize( ) 获取文件的大小 返回值: 文件的大小(b)
file_exists( ) 判断文件是否存在 返回值: bool
is_readable() 判断文件是否可读
is_writeable() 判断文件是否可写
filectime() 创建文件时间
filemtime() 修改文件时间
fileatime() 访问文件时间

文件路径

文件路径 注意
window系统支持的路径分隔符 \ /
linux系统支持的路径分隔符 /
dirname 获取指定路径的目录
basename 获取制定路径的文件 注意: 会获取到 参数
面试题,获取url扩展名

​ // 需求: 请获取$url 的文件扩展名 ( .html 或 html )
$url = 'http://www.baidu.com/image/index.html?name=laowang&age=18#xxoo';

涉及到的一些字符串函数

字符串函数 www.baidu.com?m=aad
strtok($str , ‘.’ ) www
strchr($str , ‘.’) = strstr( \$str , ‘.’) 加第三个参数true=strtok .baidu.com?m=aad
strrchr($str , ‘.’) .com?m=aad
substr($str, n ) 从下标n 开始截取到 末尾
substr($str, n,m) 从下标n 开始截取m长
strpos($str,’.’) 3(第一个.出现的位置下标为3)
strrpos($str,’.’) 9(最后一个.出现的位置下标为9)

文件操作

文件操作 返回值
opendir( ) 打开目录 资源
readdir( ) 读取目录 资源名,已经读取完则返回false
closedir( ) 关闭资源
is_file( ) 判断是否位文件
is_dir( ) 判断是否为目录

每个目录都有 .(当前目录) 和 .. (上一级目录)

需求:
计算 目录a 的大小

getSize 统计任意一个目录的大小
function getSize($dir){
    // 1. 打开目录
        $handle = opendir($dir);

    // 2. 读取目录
        $size = 0;

        while( $res = readdir($handle) ){
            // 排除 . 和 .. 
            if( $res == '.' || $res == '..'){
                continue;
            }

            // 凑完整的路径
            $path = $dir.'/'.$res;

            // 判断是否为文件, 是: 获取大小, 并累加size
            if ( is_file($path) ) {
                $size += filesize($path);

            }
            // 判断是否为目录, 是: 打开目录
            if ( is_dir($path) ) {
                $size += getSize($path);
            }

        }

    // 3. 关闭目录

        closedir($handle);

    // 4. 返回当前目录的大小
        return $size;
}

echo getSize('./a');

other

other
copy(复制谁, 复制到哪儿去 ) 复制文件( 不能复制文件夹 ) copy(‘./07-other.php’, ‘./a/077-other.php’);
mkdir(目录地址) 创建空目录 mkdir(目录地址, 0777, true) 开启递归创建
rmdir(目录地址 ) 删除空目录 rmdir(‘./x’)
touch( 文件地址) 创建空文件 touch(‘./a.txt’)
unlink( 文件地址) 删除文件 unlink(‘./a.txt’)
rename(剪切谁, 剪切到哪儿去) 剪切/重命名 rename(‘./a.txt’, ‘./b.txt’)
目录不同, 就属于剪切…目录相同, 就属于重命名

文件加载

文件加载
include(‘文件地址’) 加载文件 加载地址出错, 不会终止程序的运行,支持相对路径,盘符式路径,不支持网址路径
include_once(‘文件地址’) 加载文件 为了避免 文件重复加载, 通过 include_once 来加载
require(‘文件地址’) 加载地址出错, 立马终止程序的运行.支持相对路径, 盘符式路径, 不支持网址路径
require_once(‘文件地址’) 为了避免 文件重复加载, 通过 require_once 来加载

include 和 require 最大的区别?
include加载出错, 不会终止程序, 不是用require 就用include
require加载出错, 立马终止程序, 适合加载 核心文件, 配置文件 等重要文件

文件上传/下载

赋予,读取文件内容 注意
file_put_contents(文件路径, 内容) 向文件赋予内容 直接删除原本内容
file_get_contents(文件路径,内容) 获取文件内容 有多少获取多少
何种方式打开文件 打开方式
fopen(文件路径,打开方式) r 读 文件指针指向开头,若读不存在的文件则会报错
w 写 文件指针指向开头,若文件不存在则会自动创建
a 写 文件指针指向末尾(文章末尾接着写),若文件不存在则自动创建
r+ w+ a+ 增强模式, 同时兼具读写功能
打开后操作
fread(资源,file_size(文件内容 ) ) 读取全部文件资源 这里的资源是指打开文件后的资源
fwrite(资源, 内容) 写入
fclose(资源) 关闭文件资源
面试题:获取百度首页

请用一行代码获取百度首页:

echo file_get_contents('https://www.baidu.com');

上传文件

上传文件大小三道坎

// 1. 前端form, 设置 MAX_FILE_SIZE 上传大小
// 2. post协议(post_max_size), wamp限制: 8M以内. 一旦超过, $_FILES 则接收不到上传文件
// 3. 服务器限制(upload_max_filesize): 2M以内. 一旦超过, 则error = 1

// 如果是需要更大的上传限制, 则修改配置文件php.ini

上传文件步奏

1.判断error
2.判断是否是从post协议传输 // is_uploaded_file( 临时文件路径 )

3.判断文件类型 //in_array

4.设置新的文件名 //格式: 20190128xxxxxxxxxxxxxxxxxx.jpg

5.设置存储目录 //格式: upload/2019/01/28/

6.移动文件 // move_uploaded_file( 临时文件, 新目录+新文件名)

涉及函数
字符串切割函数 strtok,strchr……………
key 获取前端传输过来的name值
in_array(s1,数组 ) 判断一个数组里面有没有给定的值
is_uploaded_file( 临时文件 ) 判断是否从post协议传输
move_uploaded_file( 临时文件, 新目录+新文件名)=>括号里面都是文件 移动临时文件到指定目录
uniqid() 基于1微秒 产生一个唯一ID, 适合低频率
function UUID() 高频率需要自己做

上传文件imge或text例子

    var_dump($_FILES);    

    function singleFile(allowType=['image'], save = './upload')

    {

    // 1. 判断error

        // 1.1 获取$_FIELS 的下标, 由此判断是否超过 8M
            key = key(_FILES);
            if( empty($key) ){
                return '您上传的文件过大, 换个小点的'; 
            }
        // 1.2 获取 error 
                error = _FILES$key;
                if($error != 0){
                    switch ($error) {
                        case 1:    return '您上传的文件过大, 换个小点的'; break;
                        case 2:    return '您上传的文件过大, 换个小点的'; break;
                        case 3:    return '请检查您的网络'; break;
                        case 4:    return '请上传您的文件'; break;
                        case 6:    return '服务器繁忙, 请稍后再试'; break;
                        case 7:    return '服务器繁忙, 请稍后再试'; break;
                    }
                    die;
                }         
    // 2. 判断是否是从post协议传输
    $tmp = $_FILES[$key]['tmp_name'];
    if( !is_uploaded_file($tmp)){
    return '非法上传';
    }

    // 3. 判断文件类型
    // 3.1 获取上传文件的type
    $type = strtok($_FILES[$key]['type'], '/');

    // 3.2 判断是否为 允许类型之一
    // $allowType = ['image'];
    if ( !in_array($type, $allowType) ) {
    return '您上传的格式有误'; 
    }

    // 4. 设置新的文件名 (唯一性)
    // 格式: 20190128xxxxxxxxxxxxxxxxxx.jpg

    // 4.1 获取当前的年月日
    $time = date('Ymd');
    // 4.2 获取上传文件的扩展名
    $suffix = strrchr( $_FILES[$key]['name']  , '.');
    // 4.3 获取唯一字符 uniqid()
    $newFile = $time.uniqid().$suffix;

    // 5. 设置存储目录
    // 5.1 设计 上传目录/年/月/日/
    // $savePath = './upload/'.date('/Y/m/d/');
    $savePath = $save.date('/Y/m/d/');

    // 5.2 判断 该目录是否存在
    if ( !file_exists($savePath) ) {
    mkdir($savePath, 0777, true);
    }

    // 6. 移动文件
    if ( move_uploaded_file($tmp, $savePath.$newFile)) {
    return [$newFile];
    }
    return '上传失败';  
    }

    $result = singleFile(['image','text']);
    var_dump($result);

单文件下载

涉及知识点(下载核心)
header(‘content-Disposition:attachment; filename=”‘.$filename.’”‘); 下载
readfile($path); 读取下载内容
// 1. 接收 需要下载的名字
    $name = $_GET['name'];

// 2. 准备下载路径
    $path = './download/'.$name;

// 3. 准备下载之后的名字 (唯一性)
    $suffix = strrchr($name, '.');

    // 产生32位 随机16进制字符, 以保证唯一性
    $filename = str_shuffle(str_shuffle(md5(mt_rand().uniqid()))).$suffix;
    header('content-Disposition:attachment; filename="'.$filename.'"');

// 4. 读取下载内容
    readfile($path);

mysql数据库

基本知识

注释:–单行注释;#单行注释;/ 多行注释/

数据库类型:

  • 关系型数据库
    * mysql, sql server, oracle, ...
    
  • 非关系型数据库
    • redis, mongodb, …

基本语法:

  • 每一条命令均已 分号 作为结束
  • mysql 命令均大写(大写), 不区分大小写
  • 字段名,表名,数据库,加反引号 ` ` : 主要是为了屏蔽 关键字

配置windows环境变量:

1.配置环境变量
    在windows 任何地方都可以直接操作mysql
    1. 右键"我的电脑" 
    2. 选择"属性"
    3. 左侧 选择"高级系统设置"
    4. 选项卡 "高级"
    5. 选择 "环境变量"
    6. 查看是否有 变量path
        有: 选择"编辑", 粘贴 mysql 目录地址
        没有: 选择"新建", 粘贴 mysql 目录地址
        win7系统, 在原有path值的最后面加 分号; 再粘贴 mysql 目录地址


2.使用mysql
    1. 进入 cmd
    2. 输入 mysql -u root -p回车
            mysql -h 主机或ip地址 -u 用户名 -p 回车

    3. 输入密码:  wampsever默认密码为 空

    分析:
        -h         若地址为 localhost 即可省略
                否则 必须填写

        -u         用户名
                wampserver 默认用户名为 root

        -p         密码
                wampserver 默认密码为 空    即可以回车

数据库引擎

MyISAM InnoDB
事务 No Yes
全文索引 Yes No
可用Sphinx代替
表总行数 存储
count() 可直接
count() 若带where条件, 则会遍历整表, 消耗巨大
未存储
当场遍历整表, 消耗
CURD 擅长R (read), 查询数据 擅长CDU
行表锁 表锁
开销小,加锁快,低并发
行锁(默认),表锁
开销大加锁慢,易死锁,高并发

字段类型

字段类型 数据类型(宽度)来设定宽度,
可超过设定,但是不可以超过默认,超过就报错
例如:987占3位
整形
tinyint 0~255
int 42亿
定点型 decimal(M,D)
日期 datetime
date
字符串 char
varchar
其他 blod, text, enum, set…….

字段属性

属性 属性名 描述
PRIMARY KEY 主键 主键数据不能为空,不能重复
UNIQUE 唯一索引
AUTO_INCREMEN 自增
NOT NULL 不能为空
NULL 可以为空
DEFAULT 默认值
UNSINGED 无符号
COMMENT 描述
ZEROFILL 补零

基本命令

数据库数据表基本命令 注意
set password = password(密码) 设置密码
show database; 查询所有的数据库
create database if not exists `库名` default charset=编码 创建一个数据库
drop database`库名` 删除一个数据库
use `库名` 使用一个数据库 在使用任意数据表之前, 必须先选择好 数据库
show tables 查询所有的数据表
create table if not exists `表名`(`字段名` 字段类型 字段属性 , `字段名` 字段类型 字段属性)engine=引擎 default charset=编码 创建数据表 最后一条字段, 不要加 逗号
drop table `表名` 删除数据表
desc `表名` 查看表结构
show create table `表名` 查看建表语句 (引擎)
-- 创建用户表
create table if not exists `user`(
    `id`             int             auto_increment primary key,
    `nickname`         varchar(20),    
    `tel`             char(11)         unique not null,
    `pwd`             char(32)         not null     comment '加密32位密码',
    `sex`             tinyint(1)     default 1     comment '1-男  2-女',
    `birthday`         date,
    `address`         varchar(50),
    `status`         tinyint(1)     default 1  comment '1-激活 2-禁用',
    `regtime`         int
)engine=myisam default charset=utf8;

函数

聚合函数 例子
count( ) 统计 select count(字段名) from(表) =>统计此字段里有多少个值
sum( ) 求和
avg( ) 求平均值
max( )/min( ) 求最大/最小
函数
concat( 字符串或字段名, 字符串或字段名, 字符串或字段名, 字符串或字段名, ) 字符串拼接函数
now( ) 现在的格式化时间
unix_timestamp( ) 现在的时间戳
version( ) 当前数据库的版本
md5(‘123456’) 查看加密之后的值

增:

  • 插入一条数据

    • insert into `表名` values(值1, 值2, …)

      • 注意点: 1.字段有多少个,值就要有多少个,没有值也要写上null

        ​ 2.值 只可以使用 单双引号

        ​ 3.库名,表名, 字段名 只可以用 反引号

  • 插入一条 部分字段的数据

    • insert into `表名`(字段名1, 字段名2, …) values(值1, 值2, …)

      • 注意点: 1.值的个数 要随着前面的字段名的个数, 保持一一对应

        ​ 2.具有not null 属性的字段, 必须要添加值

        ​ 3.auto_increment 是从记录+1, 而不是从最大字段值+1(学过的唯一以1开始的)

  • 插入多条 完整的数据

    • insert into `表名` values(值1, 值2, …),(值1, 值2, …),(值1, 值2, …),(值1, 值2, …) …
      • 注意点: 即在第一种里直接加 , (值1,值2,…)
  • 插入多条 部分字段的数据

    • insert into `表名`(字段名1, 字段名2, …) values(值1, 值2, …), (值1, 值2, …), …

删:

  • 删除一张表中的 所有数据

    • DELETE FROM `表名`
  • 删除一张表中的 部分数据

    • DELETE FROM `表名` WHERE 条件

      • 例子:delete from `user` where `sex` = 1 //删除 user表中所有的男生

  • 删除 排序之后的前几条[满足条件] 数据

    • DELETE FROM `表名` [WHERE 条件] ORDER BY 排序依据 LIMIT 行数

      • 例子:delete from `user` order by `birthday` desc limit 5 //删除 年级最小的5个人

  • 删除树结构

    • TRUNCATE TABLE `表名`
      • 相当于dorp然后create,创建了一个与原表一样的表,但是auto_increment(主键)会重置,适合删除大批量数据(整表)

数据库备份和导入

备份

  • 进入cmd (前提条件: 配置好环境变量)
    • 输入 mysqldump -u root -p s84 > c:/s84.sql
      • 备份 mysqldump -u 用户名 -p 库名 > 目标地址
  • 导入
    • mysql -u 用户名 -p 库名 < 来源地址

改:

  • 更新整表数据

    • UPDATE 表名 SET 字段名1=值1, 字段名2=值2, …

      • 例子:update `user` set `sex` = 2, `status` = 2; //将所有的性别改为2,状态改为2

  • 更新 部分数据

    • UPDATE 表名 SET 字段名1=值1, 字段名2=值2, … WHERE 条件

      • 例子:update `user` set `status` = 2 where `birthday` >= ‘2002-01-01’ //将user表里生日大于>=2002-01-01的status状态改为2


查:

select数据结构

select distinct | * | 字段名 | 表名.字段名 | 字段名 as 别名
[ from ] 表名
[ where ] 条件 (分组之前的条件筛选)
[ group by ] 分组依据
[ having ] 筛选条件 (分组之后的条件筛选)
[ order by ] 排序依据
[ limit ] 下标, 行数

In操作

别名as

1.查询数据库

  • select * from 表名

    • select * from user; //全查容易被打

2.查询指定字段数据

  • select tel, pwd from user;

3.带条件查询字段数据

  • select nickname, tel, sex, address

    from user

    where id = 8 //查询路飞的 昵称, 电话, 性别, 住址

  • 逻辑与 and / 逻辑或 or (两个条件时)

    • select nickname, tel, sex, address
      from user
      where sex = 2 and status = 1 //and: 查询user表中 所有状态为激活的 女生的昵称, 电话, 住址, 性别

  • is null / is not null

    • select nickname, tel
      from user
      where address is not null //查找user表中,所有地址不为空的人

  • 区间查询 between A and B / not between A and B

    • select nickname, birthday
      from user
      where birthday not between ‘2005-01-01’ and ‘2015-12-31’ //查询user表中, 生日在 05 ~ 15 年之间的人的 昵称 和 生日

  • in 操作

    • select nickname, address
      from user
      where address in (‘老王隔壁’, ‘召唤师峡谷’, ‘木叶忍者村’) //查询 住在( 老王隔壁, 召唤师峡谷, 木叶忍者村 ) 的昵称和住址

4.分组/分组后的筛选:

  • group by 分组依据

    • select dep, count(`id`)
      from salary
      group by dep //查询salary表 每个部门各有多少人

  • having 筛选,配合group by使用的 (分组之后的条件筛选)

    • select dep, count(`id) from salary group by dep **having count(\id`) > 2** //查询salary表 人数超过2个的部门

5.嵌套查询

    • select uid, dep, money
      from salary
      where money in (select max(`money`) from salary group by dep //扩号内命令用于查询每个部门的最高工资,然后在表格里面查出这些这些最高工资的数值,万一有一些不是最高工资的数值跟其他部门最高工资相同也会被查出,所有是BUG ); //查询每个部门最高工资的uid, 该命令有BUG

6.多表查询
  • 格式:

    • select 查询的字段
      from 表名1, 表名2, …
      where 表与表之间的关系(必须声明)
    • 当 查询时, 发生多表字段重名? 解决方法: 使用 表名.字段名 区分重名字段
  • 取别名 as

    • 在from里面写别名,表名as简单字母

      • from salary as s, test as t

  • 最终版:

    • select uid, s.dep, s.money
      from salary as s, (select dep, max(`money`) as money from salary group by dep //这里命令查出来就相当于是一个表格,直接当两表联查用) as t
      where s.dep = t.dep and s.money = t.money //查询每个部门最高工资的uid

7. limit 下标, 行数

  • 经常被利用在 后期 分页效果
  • 公式 key = (page -1)×rows 行数:rows 页数page key从多少开始

    • select id, nickname
      from user
      limit 5 # ===> limit 0, 5 //查询前5条数据

8. 取消重复 distinct

  • select dep from salary
    select distinct dep from salary //查询该公司有哪些部门


面向对象(OOP)

基本知识点:

​ 想要用类就先实例化:例,\$a = new plane; 类由:属性和方法组成,外面调用时 $对象->属性

$对象->方法名( ),里面调用时 调用另一个方法\$this->fly( ),调用一个属性:\$this->name;

例子:

class plane{
    public $name = '波音747';
    public $material = '黄金';

    public function fly()
    {
        echo '我会飞 <br>';
    }        

    public function biu()
    {
        echo '我会biu biu biu <br>';
    }

    public function test()
    {
        // 查看对象自己
        // 方法1:
        // var_dump($GLOBALS['a']);

        // 方法2:
        // $b = new plane;
        // var_dump($b);

        // if($b == $GLOBALS['a']){
        //     echo 'Yes';
        // }else{
        //     echo 'No';
        // }
        // 方法3: 伪对象
        // 查看自己的名字
        echo $this->name;
        echo '<br>';

        // 查看自己的材料
        echo $this->material;
        echo '<br>';

        // 查看自己的功能fly
        $this->fly();

        // 查看自己的功能biu
        $this->biu();

   }
}

$a = new plane;
echo $a->name;
echo $a->material;
// echo $a->xxxx;  # 对象a 中没有属性 xxx
$a->fly();
$a->biu();

PDO类

PDO 只是PHP系统 封装好的 一个类

class PDO
{
    public function __construct( DSN, USER, PWD){

    }
    执行一条sql命令, 返回 PDOStatement对象
        public function query(){}

    执行一条sql命令, 返回 受影响的行数
        受影响的行数:
    >= 1 : 证明操作成功
        0    : 证明操作失败
            public function exec(){}

    获取 sql 报错信息
        public function errorInfo(){}

    获取 最新一次 新增的ID
        public function lastInertId(){}
}

主要负责:操作数据库

  • 在使用任何PDO方法前,必须先实例化PDO(连接数据库)

      •  $dsn = 'mysql:host=localhost;dbname=s84;charset=utf8';
             $user = 'root';
             $pwd = '';
             $pdo = new PDO($dsn, $user, $pwd);
        
        在wampserver软件中,用户名 = root  pwd = 密码
        
        在wampserver软件中,密码 ='' 空
        
PDO的方法
  • query( ) 执行一条sql语句,并返回PDOStatement 对象,适合 查

    • fetch( ) 以一维数组的形式, 获取一条数据
      fetchAll( ) 以二维数组的形式, 获取所有数据 (查询到的所有数据)

      • fetch 和 fetchAll 可添加参数: PDO::FETCH_ASSOC 以关联数组形式存储**

                                   PDO::FETCH_NUM     以索引数组形式存储
                                        PDO::FETCH_BOTH     以混合数组形式存储 (关联+索引)(默认)
        

        $res = $pdo->query( $sql );

        $row = $res->fetchAll(PDO::FETCH_ASSOC);


      **exec(     )**            执行一条sql语句, 并返回受影响的行数,**适合增删改**
      

      errorInfo( ) 获取执行sql失败的错误信息
      lastInsertID( ) 新增时使用:获取最后一次 插入的id => $row = $pdo->exec( $sql );

                                                        `$newId = $pdo->lastInsertID();`
      

      $row = $pdo->exec( $sql );


连贯操作

    1. 类外先实例化类 2. 对象->方法1( )->方法2( )->方法3( )

      1. \$a = new Person 2.$a->step1()->step2()->step3();
    • 在使用连贯操作时, 需要前面一个方法 返回一个对象. 用以调用后面的方法
      • 在方法里写上 return $this 代表返回的就是本身对象,即可以使用连贯操作

魔术方法

​ 在触发特定条件时, 自动调用魔术方法

构造(__construct)

​ public function __construct()

知识点:

  • 触发条件: 实例化时,自动调用

  • 常用于:初始值(手机初始化)

  • 不需要返回值

    • 实例化时,变量接收对象
    • 调用时,变量接收返回值
  • 位置: 写在属性的最后面,方法的在最前面

  • 类名和方法名相同时,当在没有构造方法时, 实例化的瞬间会自动执行同类名的方法

  • 在实例化时, 传递参数给 __construct()

    • 例题1:手机初始化时各两个参数,账号和密码

    • class Computer
      {
          public $name;
          public $pwd;
          public function __construct($a, $b)
          {
              // var_dump($this); 
              \$this->name = $a;
              \$this->pwd = $b;
          }
      }
      
      // 在实例化时, 传递参数给 __construct()
      // $a = new Computer;
      $a = new Computer('Asus', '123456');
      var_dump($a);
      
      $c = $a->name;
      var_dump($c);
      

      例子2:编写一个求自定义圆的面积、周长的类(圆的周长C=2πr,圆的面积S=πr * r,保留2位小数,需要用到构造方法)

       class circle
       {
           public $r = 0;
      
           //设置半径
           public function __construct($value = 0) {
               $this->r = $value;
           }
      
           //周长
           public function getGirth() {
               return round(2 * pi() * $this->r, 2);
           }
      
           //面积
           public function getArea() {
               return round(pi() * $this->r * $this->r, 2);
           }
       }
      
       $test = new circle(10);
       echo "周长:".$test->getGirth();
       echo "<hr>";
       echo "面积:".$test->getArea();
      
析构(__destruct)

public function __destruct()

知识点

  • 触发条件:
    • 在对象被销毁时,自动调用!
    • 被销毁的情况
      • 程序结束时 // die
      • 对象被覆盖时 // $a = 100 $a =30
      • 对象被删除时 // $a= 100 unset $a
  • 不能有参数(有参数就会报错)
  • 位置:写在方法的最后面
克隆(__clone)
  • 触发条件:

    • 在克隆时, 自动触发
  • 一般用于

    • 可用于在克隆时, 重新初始化属性
  •  class demo
         {
             public $name = '老王';
             public function __clone()
             {
                 $this->name = '老李';
             }
         }
         $a = new demo;
         $b = clone $a;   #将 标识 和 内存 各自复制了一份, 重现划分内存, 与 $a 不再有联系
         $c = $a;         # 将 $a 与 标识之间的联系 复制一份给 $c
         unset($a);         # 仅仅删除了 $a 和 标识之间的联系, 不影响 $c 和 标识之间的联系
    

OOP的封装性

封装性

  1. 将对象的全部成员和方法结合在一起, 形成一个不可分割的独立单位(对象)
  2. 尽可能的隐藏对象内部的属性和方法, 只留下部分接口与外部联系
类外 本类 继承
public 公有属性
private x x 私有的
protected x 受保护的
class People
{
    public $name = '老王';
    private $wife = '老李';
    protected $money = 5;
    public function test()
    {
        echo $this->name;    
        echo $this->wife;
        echo $this->money;
    }
}
    $a = new People;

​ echo $a->name; 正常->公有属性
​ // echo $a->wife; 报错->私有属性
​ // echo $a->money; 报错->继承属性

//调用方法,方法里面有被调用的属性
$a->test();

权限不足,如何避免error级报错

当访问了 非公有属性 或 方法(权限不足)时, 如何避免error级错误的发生?

通过一些魔术方法,来避开error错误

魔术方法 注意点
__get( ) 当访问非公有属性(即权限不足)时,自动触发 一个形参
__set( ) 当设置非公有属性(即权限不足)时, 自动触发 两个形参
__unset( ) 当删除非公有属性(即权限不足)时, 自动触发 一个形参
__isset( ) 当判断非公有属性(即权限不足)是否设置时, 自动触发 一个形参(类外判断是一定是false(其实有),通过魔术方法__isset类内return,然后再在类外调用)
__call( ) 当调用不存在的方法时, 自动触发 两个形参
__toString() 当输出(echo)对象时, 自动触发, 必须返回 字符串值(魔术方法内必须return字符串) 没有形参(但是必须return一个字符串)
__callStatic( ) 当调用一个不存在的静态方法时,自动触发 与_call()一样也是两个形参,\$a接收静态方法,$b接收实参.
串行化触发(__sleep)

有东西不想被看(保密),return什么,显示什么,其他的不显示但是其实都在

    public function __sleep()
    {    
        #有东西不想被看时,返回什么,显示什么,其他的不显示但是其实都在
        return[]
    }
反串行化触发(__wakeup)

醒来时(反串行化时),重新赋值做初始化

    public function __wakeup()
    {    
        #醒来时,重新赋值做初始化
        $this->age = 1018;
    }
自动加载(__autoload)

在实例化一个不存在的类时, 自动触发,用于自动加载其他文件

new哪个类就获得哪个类类名,并将类名送进参数,include时凑近去

// 魔术方法 __autoload
//     在实例化一个不存在的类时, 自动触发
//     
    #获取到类名送进参数
function __autoload($className)
{
    // var_dump($className);
    #凑出一个路径
    include "./class/{$className}.php";

    // 实际开发中, 一般情况下:
    //     类名 与 类文件名 有一定的关联
    //  一个类文件中, 一般只有一个类
}

$a = new Image;

OOP的封装性

​ 1.1将对象的全部成员和方法结合在一起, 形成一个不可分割的独立单位(对象)
​ 1.2 尽可能的隐藏对象内部的属性和方法, 只留下部分接口与外部联系

// 通过 修饰符 来控制对象与外部的联系
// 
//              类外     本类        继承
// public          √          √          √         公有的
// private          x          √          x         私有的          
// protected      x          √          √         受保护的

OOP的继承性

概念

  • 继承性
    • 儿子 继承老子的 一些东西
      • 儿子: 派生类, 继承类, 子类
      • 老子: 基础类, 基类, 父类
继承(extends)

特性:

  1. 子类可继承父类属性 和 方法 (私有的无法继承)

    1. class son extends laozi
      {
          public function test()
          {
              echo $this->name.'<br>';
              // echo $this->wife.'<br>';     #==>这行时laozi的私有属性
              echo $this->money.'<br>';
          }
      
      }
      
  2. 子类继承父类后可重写属性 和 方法 (方法如果重名, 可以做覆盖, 可以做扩展) 扩展==>即通过 parent::父级方法名() 再调用一次

    1. class son extends laozi
      {
          public $name = '小宋';
      
          public function skill()
          {
              parent::skill();             #===>精髓所在
              echo $this->name.'泡男人一绝 <br>';
          }
      
      }
      

    3.访问级别:子类在继承父类时要么保留等级,要么降级,不能升级.private>protected>public

    4.一个父类可以有多个子类继承
    一个子类不能继承多个父类

一些修饰符

静态(static)

静态:

    class Person
    {
        public $name = '老王';
        // public static $age;     =>修饰符位置可颠倒
        static public $age = 18;

        static public function skill()
        {
            // echo '老王擅长翻墙去隔壁 <br>';

            // echo $this->name.'擅长翻墙去隔壁 <br>';   =>调用普通属性无法调用

            // echo '老王今年 '. $this->age .' 岁';        =>且无法使用$this->代表这个类,$this代表对象
            // echo '老王今年 '. Person::$age .' 岁';    =>可以用self 代表本类
            echo '老王今年 '. self::$age .' 岁';
        }
    }

    echo Person::$age;  //      =>不需要new实例化,即可直接在类外调用静态属性
    Person::skill();    //     这里不能使用self这是类外,直接写class名  =>不需要new实例化,即可直接在类外调用静态方法

特性:

  • 静态属性/方法 属于类, 不属于对象 (不需要实例化)
  • 在静态方法内 只能访问静态属性/静态方法
  • 静态属性/方法 都可以继承, 重写
  • 魔术方法 __callStatic( )
    • 当调用一个不存在的静态方法时,自动触发
类常量(const)

类常量

class Person
{
    const STEAM = '火箭队';

    public function test()
    {
        // echo Person::STEAM;
        echo self::STEAM;
    }
}

$a = new Person;
$a->test();        #调用方法

echo Person::STEAM;        #调用属性

特性:

  • 类常量 属于类, 不属于对象
  • 类常量 可以继承, 但只能重写一次类常量
  • 其余的特性 与 普通常量一样
    • 普通常量 可以直接在类内或函数内使用

访问常量

类名::类常量名

最终类(final)

最终:

作用=>保护方法和类

  • 修饰类: 最终类, 不能被继承

  • 修饰方法: 最终方法, 可以继承, 但不能重写

    • class Person
      {
          final public function skill()
          {
              echo '练 天外飞仙 <br>';
          }
      }
      class son extends Person
      {
          // public function skill()            =>这个方法可以被继承,但不能重写,因为上面类被final修饰了!!
          // {
          //     echo '练 葵花宝典 <br>'; 
          // }  
      }
      
  • 不能修饰属性

滴血认亲(instanceof)

instanceof为运算符

  • 判断 对象是否从 某一类 实例化过来的
  • 判断 对象是否从 某一对象 继承过来的
    • 返回值:bool
var_dump( $b instanceof $a );   #   =>前面是后辈,后面写长辈
var_dump( $b instanceof son );    
var_dump( $b instanceof laozi );
克隆(clone)

作用:主要给对象做一个副本,副本 和 本尊 互不影响, 完全独立

也属于运算符, 优先级为 第一优先级 , 与new 同级

引入了一个概念:标识 $a = 一个对象,是复制的标识

克隆标识

class demo
{
    public $name = '老王';

    public function __clone()
    {
        $this->name = '老李';
    }
}
$a = new demo;
$b = clone $a; # 将 标识 和 内存 各自复制了一份给$b, 重现划分内存, 与 $a与$b 不再有联系
$c = $a;         # 将 $a 与 标识之间的联系 复制一份给 $c
unset($a);         # 仅仅删除了 $a 和 标识之间的联系, 不影响 $c 和 标识之间的联系
var_dump($a, $b, $c);

对象串行化(serialize)

作用:将对象串行化为字符serialize串,存入数据库,传递给其他文件,写入文件等

特性:方法不参与串行化,不代表会消失,只是没显示出来而已,可以正常使用

反串行化:unserialize=>将字符串重新转化为对象

存档过程
$a = new Demo123 将DEmo123类实例化
\$str = serialize($a) 串行化
$handle = fopen(‘./demo.txt’,’w’) 创建并打开文件
fwrite(\$handle,$str) 将内容串行化写入打开的文件
fclose($handle) 关闭文件
存档过程
$result = file_get_contents(‘./demo.txt’) 读取获取文件内容(上面存档后的字符串)
\$obj = unserialize($result) 反串行化: 将 字符串 反串行化为 对象,将读到的内容(字符串)反串行化为对象
class Demo123
{
    public $name ='老王';
    public $age = 18;

    public function skill()
    {
        echo '老王就是会赚钱';
    }
}
$a = new Demo123;
var_dump($a);

#串行化
$str = serialize($a);

//写入文件(存档)
    #创建并打开文件
    $handle = fopen('./demo.txt','w');
    #将内容串行化写入打开的文件
    fwrite($handle,$str);
    #关闭文件
    fclose($handle);

//一千年以后(读档)
#读取文件内容
$result = file_get_contents('./demo.txt');
// 反串行化: 将 字符串 反串行化为 对象
    #将读到的内容(字符串)反串行化为对象
    $obj = unserialize($result);
    var_dump($obj);
    echo $obj->name;
/*
    分析 串行化后的字符串
        O:4:"Demo":2:
        {
            s:4:"name";
            s:6:"老王";
            s:3:"age";
            i:18;
        }

        数据类型: 内容长度 : 内容
 */
抽象(abstract)

修饰方法(抽象方法):没有方法体的方法

修饰类(抽象类):不能new,必须让子类继承,并实现,才能使用 这里的继承也是用extends

  • 继承后的方法必须要有,不然继续报错直到有子类用了这个方法

注意:1.含有抽象方法的类 必须是抽象类 2.抽象类不一定要有抽象方法

与final总结: final 保护父类 | abstract 约束子类

abstract class Project
{
    public function fun1()
    {
        echo '已完成 20% ... <br>';

    }
    public function fun2()
    {
        echo '已完成 50% ... <br>';

    }
    abstract public function fun3();
}

#父类无法完成时交给子类
class Son extends Project
{    
    #假如这里没有方法3和代码体会继续报错
    public function fun3()
    {
            echo '已完成 30% ... <br>';
    }
}

$b = new Son;

$b->fun1();
$b->fun2();
$b->fun3();    
接口(interface)

修饰类:全部都是抽象方法时, 可以使用接口

​ 通过 implements 来实现接口方法, 不是通过 extends #类似继承

特新:php不支持多继承,但一个类可以实现多个接口.接口的多继承(implements)

interface laozi
{
    public function dream1();

}

interface niang
{
    public function dream2();
}
#继承
# 通过 implements 来实现接口方法, 不是通过 extends
class son implements laozi,niang
{
    public function dream1()
    {
        echo  '我实现了爹的梦想 <br>';
    }

    #如果这儿被注释将会报错,因为有抽象方法没被调用
    public function dream2()
    {
        echo '我实现了娘的梦想 <br>';
    }
}

$a = new son;
$a->dream1();
$a->dream2();

类型约束

​ 类型约束,目前仅支持两种
​ 1.数组 (\$arry $a ) #第一个参数填的是array,第二个参数填的是要接受的对象(随便给一个变量)
​ 2.对象 (类名 $n ) #第一个参数填的时类名,第二个参数填的是要接受的对象(随便给一个变量),送入数据:

​ $b = 类名;

​ \$b->demo( $c ); 这里的\$c是一个对象

function A( array $a )#$a只接收数组
{
    var_dump($a);
}

// A(100);
A([10,20,34]);

echo '<hr>';

// 2.对象

class A
{}
$a = new A;

class C
{}
$c = new C;

class B
{
    // public function demo( $b )
    // public function demo( A $b )          # $b 只接收 对象A
    // #第一个参数填的时类名,第二个参数填的是要接受的对象(随便给一个变量)
    public function demo( A $n )      # $b 只接收 对象Object
    {
        var_dump($n);
    }
}

$b = new B;

// $b->demo( 100 );
$b->demo( $a );
// $b->demo( $c );

OOP的多态性

作用:通过同一个接口, 传入不同的对象, 从而实现不同的效果

  • 定义一个接口类,类和方法都是抽象的
    • 这里也可以用抽象或者普通类
      • 不建议使用普通类,因为普通类对子类没有约束性,即使子类不执行一定要做的方法,他也不报错!
//     通过同一个接口, 传入不同的对象, 从而实现不同的效果

// usb接口

#定义一个接口类,类和方法都是抽象的
interface USB
{
    public function run();
}

// 外设
// 继承端口
class Mouse implements USB
{
    // 必须实现 run
    // #继承过来的run是抽象类,必须有方法体,调用执行,否则报错;例如鼠标链接不成功时电脑右下倒三角警告
    public function run()
    {
        echo '鼠标已连接成功 ... <br>';
    }
    #一些其他的普通方法
    public function Hong(){}

    public function dpi(){}

    public function color(){}
}

class Keyboard implements USB
{    
    #键盘继承run
    public function run()
    {
        echo '键盘已连接成功 ... <br>';
    }

    public function skill(){}
}

class UDisk implements USB
{    
    #U盘继承run
    public function run()
    {
        echo 'U盘已连接成功 ... <br>';
    }
}

// 电脑
// 创建一个类
class Computer 
{    
    #创建一个方法,接收对象USB,即这里的$a
    public function start( USB $a )
    {
        #然后调用$a里的方法run
        $a->run();         # 电脑一旦开始, 强制执行所有跟USB有关 的run 方法
    }
}

$computer = new Computer;
$m = new Mouse;
$k = new Keyboard;
$u = new UDisk;

// var_dump( $m instanceof USB );

$computer->start($m);
$computer->start($k);
$computer->start($u);

迭代对象 (foreach)

foreach (数组 or 对象 as \$key => $value) {
循环体, 代码块
}

class Book
{
    public $name;
    public $price;
    private $author;#受保护属性

    #构造
    public function __construct( $name, $price, $author )
    {
        $this->name = $name;
        $this->price = $price;
        $this->author = $author;
    }

    #方法
    public function fun()
    {
        echo $this->author.' 写了一本 '.$this->name.', 零售价: '.$this->price.'<br>';
    }
}
#new时送入参数给构造
$wang = new Book('金瓶梅', '998', '老王');

$tao = new Book('跟兄弟学PHP', '9800', '小陶');

$wang->fun();
$tao->fun();
echo '<hr>';

// 在类外, 依旧遵守 作用域
#private私有属性无法被打印
foreach($wang as $k => $v){
    echo $k .'=======>'. $v .'<br>';
}

魔术常量

魔术常量
var_dump( __FILE__ ) 获取文件路径
var_dump( __LINE__ ) 获取行
var_dump( __DIR__ ) 获取文件夹名
var_dump( __FUNCTION__ ) 获取函数名
var_dump( __METHOD__ ) 获取方法名
var_dump( __CLASS__ ) 获取类名

对象函数(objFun)

objFun
class_exists(类名) 判断类 是否存在
property_exists(‘Book’, ‘name’) 判断BOOK类里面是否有name属性
get_class_vars(‘Book’) 获取BOOK中 所有的公有属性
get_object_vars($wang) 获取对象 wang 中所有公有属性
get_class_methods(‘Book’) 获取BOOK中 所有的公有方法
get_class($wang) 获取对象$wang被new之前的类名

设计模式(单例模式)

单例模式:
只有一个对象, 多次实例化, 也只有一个对象
从而节省内存, 提高性能
只有一个对象, 多次实例化, 也只有一个对象
从而节省内存, 提高性能

class MySQL
{
    static private $link = null;

    // 设为 private, 就是为了防止在类外 直接new
    private function __construct()
    {
        echo '数据库连接成功... <br>';
    }

    // 在类内 触发构造, 通过 new self, 来实例化自己, 从而触发构造
    static public function getConnect()
    {
        // 如果 已经实例化过了, 则不再new
        // 如果 从未实例化过, 则 new MySQL
        if( is_null(self::$link) ){
            self::$link = new self;
        }
        #返回一个对象
        return self::$link;
    }

    public function select()
    {
        echo '这里是 select 查询方法 <br>';
    }
}

// $a = new MySQL;
// $b = new MySQL;
// $c = new MySQL;
// var_dump($a, $b, $c);

$a = MySQL::getConnect();
$a->select();
var_dump($a);

$b = MySQL::getConnect();
var_dump($b);

$c = MySQL::getConnect();
var_dump($c);

异常结构

作用:在try结构 捕获异常,一旦捕获到异常,则立马跳转至处理异常的地方
异常类:**Excepation**
使用场景:不允许发生任何的错误代码块,常用try

语法:

​ echo $e->getFile() # 获取发生异常的文件位置
​ echo $e->getLine() # 获取发生异常的行数
​ echo $e->getMessage()’; # 获取发生异常的信息
​ echo $e->getCode() # 获取发生异常的错误编号

    try{
        捕获异常
    }catch(Exception $e){
        此处相当于 $e = new Exception
        处理异常
    }    
try{
    // 自动抛出异常

    $dsn = 'mysql:host=localhost;dbname=s8;charset=utf8';
    $user = 'root';
    $pwd = '';

    $pdo = new PDO($dsn, $user, $pwd);
    var_dump($pdo);

}catch(Exception $e){
    echo '数据库连接失败 <br>';
    echo $e->getFile().'<br>';         # 获取发生异常的文件位置
    echo $e->getLine().'<br>';         # 获取发生异常的行数
    echo $e->getMessage().'<br>';     # 获取发生异常的信息
    echo $e->getCode().'<br>';         # 获取发生异常的错误编号
}

InnoDB转账事务

mysql自动提交
默认情况, sql一旦执行, 将立马改变数据库
关闭自动提交, sql一旦指针, 可以得到执行之后应该有的结果, 但是不会立马改变数据库

try{
    $dsn = 'mysql:host=localhost;dbname=s84;charset=utf8';
    $user = 'root';
    $pwd = '';

    $pdo = new PDO($dsn, $user, $pwd);        

#此处相当于  $e = new Exception
}catch(Exception $e){
    echo '数据库连接失败'; die;

}

// 事务的操作步骤
try{
    // 1. 关闭自动提交
        $pdo->setAttribute( PDO::ATTR_AUTOCOMMIT, 0 );

    // 2. 开启一个事务  (存档)
        $pdo->beginTransaction();

    // 3. 执行sql 操作
        // 3.1 转出 扣钱
        $sql = "UPDATE `salary` SET `money` = `money` - 5000   WHERE uid = 7 ";
        $rows = $pdo->exec($sql);

        // 若 转出失败, 则主动抛出异常
        if( !$rows ){
            throw new Exception('转出失败');
        }

        // 3.2 转入 收账
        $sql = "UPDATE `salary` SET `money` = `money` + 5000   WHERE uid = 400 ";
        $rows = $pdo->exec($sql);

        // 若 转出失败, 则主动抛出异常
        if( !$rows ){
            throw new Exception('收款失败');
        }

    // 4. 执行成功, 提交事务
        $pdo->commit();

}catch(Exception $e){
    // 4. 执行失败, 回滚事务 (回到 存档时的状态)
    echo $e->getMessage();
    $pdo->rollBack(); # 回滚事务
}

// 5. 开启自动提交 ( 如果不打开, 那么后面所有的sql 都不会真正的执行)
$pdo->setAttribute( PDO::ATTR_AUTOCOMMIT, 1);

会话控制区别

特性:HTTP协议时是无状态协议,HTTP协议不能告诉我们请求是否来自同一个客户端

会话控制就是允许服务器跟踪一个客户端发出连续请求

cookie
var_dump( $_COOKIE ) 查询cookie
setcookie(cookie名, cookie值, 生命周期, 作用域, 有效域名) 设置cookie 例: setcookie(‘pwd’, ‘123’, time()+10000, ‘/‘, ‘localhost’)
setcookie(‘tel’, ‘18888888888’, time()+7*24*3600) 7天后cookie失效(电话在cookie里保存7天)
setcookie(‘age’, ‘18’, time()+7*24*3600, ‘/‘ ) 这里的 ‘/‘ 就是根目录 www目录
setcookie(‘pwd’, ‘’, time()-1, ‘/‘) 删除cookie,即调整生命周期
修改session,就是重新赋值,就跟修改数组一样
session(服务端)

session 本身的作用域: 整个服务器
哪个文件需要session值, 只要开启session即可获取session值
session数据时可以共享的.

生命周期
默认浏览器一关, 就到期了
如果浏览器不关, session也有生命周期, 周期为: 1440s

SessionID
在访问服务器时, 服务器会给客户端分配sessionID, 用于标识客户端

session
var_dump($_SESSION) 访问session
session_start( ) 开启session(开门,不然其他文件用不了)
$_SESSION[‘name’] = ‘雪人’ 设置session
$_SESSION[‘name’] = ‘亚索’ 修改session,跟数组一样直接通过下标修改
unset($_SESSION[‘name’]) 删除session

MVC

MVC流程控制图

登录流程登录流程

增加用户

添加用户流程

删除用户

删除流程

编辑用户

编辑用户流程

配置虚拟域名

<pre>
    1. 配置 hosts
        文件位置:  c:\Windows\System32\drivers\etc\hosts


        配置如下:
            127.0.0.1     www.s84.com

        注意: 
            1. 若该目录下, 没有hosts文件, 自己创建 (该文件, 没有扩展名)
            2. 若不能直接在 ect目录下, 保存hosts配置, 则先hosts 拷贝桌面, 修改完之后再拷贝回来, 并覆盖原来的hosts文件.

    2. 开启虚拟域名
        文件地址: x:\wamp\bin\apache\apache2.4.18\conf\httpd.conf

        搜索 LoadModule vhost_alias_module modules/mod_vhost_alias.so
        将 改行最前面的 # 去掉

    3. 配置虚拟域名
        文件地址: x:\wamp\bin\apache\apache2.4.18\conf\extra\httpd-vhosts.conf
        原文件不要动,复制一份上面的文件做修改!!!!!!!
        原文件不要动,复制一份上面的文件做修改!!!!!!!
        原文件不要动,复制一份上面的文件做修改!!!!!!!
        原文件不要动,复制一份上面的文件做修改!!!!!!!
        配置如下: 
            <VirtualHost *:80>
                服务器名:  域名
                ServerName www.s84.com

                项目根目录
                DocumentRoot D:/wamp/www/s84/project
                <Directory  "D:/wamp/www/s84/project/">
                    Options +Indexes +FollowSymLinks +MultiViews
                    AllowOverride All
                    Require local
                </Directory>
            </VirtualHost>
</pre>

PHP执行流程

域名->apache(80端口监听了域名(路由))->php(接收get post请求完成数据梳理,提交给Mysql)

mysql操作成功->PHPreturn给apache->apache->https

PHP执行流程

aly = 阿里云通过阿里云解析域名

常用状态码

200:请求已成功

301:被请求的资源已永久移动到新位置(永久性转移)

302: 暂时性转移

401:语义有误,当前请求无法被服务器理解

503:由于临时的服务器维护或者过载,服务器当前无法处理请求

500:服务器遇到了一个未曾预料的状况

JS时学的回调和匿名/闭包函数

回调函数

定义:将一个函数名作为参数 ,通过这个参数传递参数就是回调函数

​ 其实就是在一个函数内部使用变量函数

自定回调函数
function sum($n1, $n2)
{
    return $n1 + $n2;
}
// 求积
function mul($n1, $n2)
{
    return $n1 * $n2;
}


// 自定义回调函数
function result($n1, $n2, $callback='sum')
{
    // sum($n1, $n2);
    return $callback($n1, $n2);
}

echo result(10, 20);
echo '<br>';
echo result(10, 20, 'mul');
系统回调函数
function sum($n1, $n2)
{
    return $n1 + $n2;
}
// 求积
function mul($n1, $n2)
{
    return $n1 * $n2;
}

call_user_func(‘sum’, 50, 50)// 把第一个参数作为回调函数调用

call_user_func_array(‘sum’, [99, 99])//调用回调函数,并把一个数组参数作为回调函数的参数

匿名函数(即闭包函数)

定义: 将一个没有函数名的函数赋值给一个变量,这就是定义匿名函数

注意:函数最后必须有分号;

$hehe = function($a)
{
    echo $a;
};  //此处分好不得缺少

// var_dump($hehe);
$hehe('呵呵哒');
echo '<hr>';
use读取全局变量时

在匿名函数内部 使用外部的全局变量时 必须通过use关键字来连接闭包函数的内外变量

$func = function()use(&$x,&$y)
{
    $x*=2;
    $y*=3;
    $z = $x+$y;
    return $z;
};
$x = 3;
$y = 4;
echo $func();
use读取全局变量时

function demo()
{
    $m = 2;
    $n = 3;
    //闭包函数
    $func = function()use($m,$n)
    {
        $m *= 3;
        $n *= 4;
        $k = $m + $n;
        return $k;
    };
    return $func();

}

echo demo();

例子:

如何用它?:

function getInfo($callback)
{
    $callback('死啦死啦地来到萨');
}

1.回调方式:

(1)调用一个方法里面带上参数,这个参数就是函数名

(2)被调用的方法体里面 就是函数名,即参数()的形式,所以开始调用这个方法体里面的方法($callback(‘死啦死啦地来到萨’)其实变成了lm(\$str)

(3)外面有一个函数lm(\$str),被那个方法体里面的方法调用了.

function getInfo($callback)
{
    $callback('死啦死啦地来到萨');//这里的 $callback 是一个对象(一个函数)
}

// 回调方式
function lm($str)
{
echo '回调方式:'.$str;
}

getinfo('lm');
echo '<hr>';

2.匿名(闭包)方式:

说白了就是调用一个函数时参数也是一个函数(这个函数是没有函数名的),通过里面的这个函数传一个参数$str(其实就是那个’死啦死啦地来到萨’)


    function getInfo($callback)
    {
        $callback('死啦死啦地来到萨');    //这里的 $callback 是一个对象(一个函数)
    }

    // 匿名方式
    getInfo(function($str){
    echo '匿名方式: ' . $str;
    });

依赖注入,控制翻转,反射

这样想用任何方式记录操作日志都不需要去修改过User类了,只需要通过构造函数参数传递就可以实现,其实这就是“控制反转”。不需要自己内容修改,改成由外部外部传递。这种由外部负责其依赖需求的行为,我们可以称其为 “控制反转(IoC)”。

那什么是依赖注入呢?,其实上面的例子也算是依赖注入,不是由自己内部new对象或者实例,通过构造函数,或者方法传入的都属于依赖注入(DI) 。


<?php

interface log
{
    public function write();
}

// 文件记录日志
class FileLog implements Log
{
    public function write()
    {
        echo 'file log write...';
    }
}

// 数据库记录日志
class DatabaseLog implements Log
{
    public function write()
    {
        echo 'database log write...';
    }
}

class User
{
    protected $log;

    public function __construct(FileLog $log)
    {
        $this->log = $log;
    }

    public function login()
    {
        // 登录成功,记录登录日志
        echo 'login success...';
        $this->log->write();
    }
}

function make($concrete)
{
    //通过ReflectionClass,我们可以得到User类的信息:
    $reflector = new ReflectionClass($concrete);
//    dd($reflector);
    //获取构造对象
    $constructor = $reflector->getConstructor();
//    dd($constructor);
    // 如果没有构造函数,则直接创建对象
    if (is_null($constructor)) {
        return $reflector->newInstance();
    } else {
        // 构造函数依赖的参数
        $dependencies = $constructor->getParameters();
//          dd($dependencies);
        //array:1 [▼
        //  0 => ReflectionParameter {#1108 ▼
        //    +name: "log"
        //    position: 0
        //    typeHint: "FileLog"
        //  }
        //]
        // 根据参数返回实例
        $instances = getDependencies($dependencies);
//        dd($instances);
        // 创建user对象,需要传递参数的
        return $reflector->newInstanceArgs($instances);
    }
}

function getDependencies($paramters)
{
    $dependencies = [];
//    dump($paramters);
    //array:1 [▼
    //  0 => ReflectionParameter {#1108 ▼
    //    +name: "log"
    //    position: 0
    //    typeHint: "FileLog"
    //  }
    //]
    foreach ($paramters as $paramter) {
        $dependencies[] = make($paramter->getClass()->name);
    }
//    dd($dependencies);
    //array:1 [▼
    //  0 => FileLog {#1853}
    //]
    return $dependencies;
}

$user = make('User');
$user->login();
exit;

反射的概念

其实可以理解成根据类名返回该类的任何信息,比如该类有什么方法,参数,变量等等。我们先来学习下反射要用到的api。拿User举例

json_encode 数组转json encode 编码

json_decode json转数组 decode 解码