php手册:https://www.php.net/manual/zh/langref.php

127.0.0.1 和我们现实生活中的 称谓 ‘我’
127.0.0.1 localhost
F:\wamp\www
http://localhost:80/
站点根目录:
http://localhost/
http://localhost/index.php
同样的效果
访问某个文件夹 默认会去访问这个文件夹下面的index.php 或者 也会访问 index.html(既有index.php也有index.html在我们这个环境里面 默认回去访问index.php)

一个管理资源并为用户提供服务的计算机软件通常分为文件服务器(能使用户在其它计算机访问文件),数据库服务器和应用程序服务器。
php应用服务器(=php软件) :执行文件中php文件中代码
服务器软件: MySQL (数据库管理系统)
格式:协议://主机地址[:端口]/路径(默认端口为80)
dns服务器(域名解析)
1)we b服务器 apache
2)php应用服务器 解释,执行我们编写的PHP程序php
3)数据库管理系统 数据库服务器
<?php
?>
1.在一些php语句的结尾要加上;表示一句话的结束,当然也不需要刻意的去记,因为一旦漏掉分号,程序根本执行不了,会报错
2.结束标记?>就隐含了一个;
所以在?>之前的PHP语句可以省略掉;
/*
多行注释
*/
//我是单行注释
空格,tab制表符,换行 这些写在咱们的PHP代码里面是没有问题的
概述:
变量是用于临时(只有在我们的程序的运行过程中才存在)存储值(数据)的容器
声明:说白了就是事先告知,通知!
在我们一些编程语言里面比如C语言 使用变量之前要事先通知,事先声明一下!
注意:在我们的PHP程序里面 使用变量之前是不需要声明的!
(变量用于存储 数字、文本字符串 或者数组)
$变量名=数值
= 在数学里面是‘等于’的意思,在我们的程序语言里面,它不是等于号,它是 '赋值操作符'
unset($变量名称)
$and1=1;
unset($and1); //销毁$and变量
echo $and1; //提示出错,因为变量已经被销毁了
$name,$NAME,$Name都是不同的变量
错误的命名方式:
$1name 错误点:以数字开头了
$n ame 错误点:中间有空白字符
总结一下:变量名只能包含 字母 数字 下划线 并且必须以字母或者下划线开头!
//可变变量
$abc='test';//定义了一个变量$abc里面存了值test
$$abc='孙胜利';//$test='孙胜利';
echo $test;$a=1000;
/*$b=$a;//相当于把$a的值,复制一份再赋值给$b这个变量*/(普通赋值)
$b=&$a;//相当于给$a起了一个别名,操作其中任何一个,都会影响到另外一个变量的值。(别名赋值)
$b=20;
echo $a;概述:变量类型是指保存在该变量中的数据类型
布尔型:往变量里面存true或者false
<?php
$a=true;
var_dump($a);
?>以下值被认为是false,其他的值都是被认为是true
①布尔值false
②0
③浮点型0.0
④空白字符串和字符串0 //空白字符串指的是直接一对单引号或双引号里面没有任何内容
⑤没有成员的数组
⑥NULL
注:空白字符串就是空格
整型变量:往变量里面存整数
浮点型:往变量里面存小数
$a=1.1;
var_dump($a)字符串:一系列的字符组成串在一起(外面有单引号)
$b=1;
$a='test$bdwqd\'wqdqw';
var_dump($a);
echo $a;
注:PHP不解析单引号中的变量
有单引号的字符里面不能再包含单引号,除非用\(反斜杠)转义
$b=100;
a='te$bst......'; //单引号内的变量不解析
$a="te{$b}st......";//双引号内的变量解析
var_dump($a);
echo $a;
注:双引号内的变量要加{}
$b=200;
$a=<<<www
dwqdqwdwq{$b}dwqdqdqdqdwqdwqcwcfwefwefcscwecwefwdqwdqdefwefwefewfwe
www;
var_dump($a);
=>
string'dwqdqwdwq200dwqdqdqdqdwqdwqcwcfwefwefcscwecwefwdqwdqdefwefwefewfwe'
注:定界符内可包含单引号或双引号
<<<之后提供一个标示符开始,然后是字符串的内容,最后是同样的标示符表示结束
标示符命名规则:字母数字下划线,不能以数字开头
null表示一个变量没有值,表示空
将变量直接赋值为null
声明的变量尚未被赋值
被unset函数销毁的变量
$a=1111;
unset($a);
var_dump($a); //var_dump函数不仅输出值,还输出值的类型;echo只输出值var_dump与echo的区别举例


强制转换:
<?php
$a='孙胜利'; //字符串
$b=(int)$a; //转换为整型
var_dump($a);
var_dump($b);
?>注:转换不会转换自身变量类型
常量是用于临时(只有在我们的程序的运行过程中才存在)存储值(数据)的容器
define('常量名称',常量值) 或者 define("常量名称",常量值)
<?php
define('MY_NAME','孙胜利'); //定义MY_NAME的值为孙胜利
echo MY_NAME;
?>1)和变量一样 只能包含字母数字下划线 并且必须以 字母或者下划线开头
2)按照惯例常量名字总是大写的
3)自定义的常量是严格区分大小写
defined()函数来检查是否定义了某个常量
1)常量前面没有美元符号($)
2)常量只能用define()函数定义,不能通过赋值语句
3)********常量可以不用理会变量范围的规则而在任何地方定义和使用
4)常量一旦被定义就不能被重新定义或者取消定义
5)常量的值只能是bool,int,float,string类型
<?php
$a='孙胜利';
define('MY_NAME','孙胜利');
define('MY_NAME','孙胜利1'); //报错=>常量一旦被定义就不能被重新定义或者取消定义
echo MY_NAME;
?>1)预定义常量:PHP内核已经帮我们定义好了的常量
2)魔术常量其中有的预定义常量是以__开头的,这些预定义常量
代码所在的位置不同他的值也是不同的
3)八个常用的魔术常量
https://www.php.net/manual/zh/language.constants.magic.php
注意:预定义常量区分大小写
预定义常量为MY_NAME自己定义的常量为my_name不会有冲突

$a=1;
$b=2;
$c=$a+$b;
echo $c;2)-
第一个意思: 减号
$a=10;
$b=2;
$c=$a-$b;
echo $c;第二个意思: 取反
$a=1;
$b=-$a;
echo $b; //-1
echo '<br />'; //换行
echo $a; //1注意:取反并不会影响到被取反变量本身的值!
$a=4;
$b=2;
$c=$a*$b;
echo $c;$a=10;
$b=2;
$c=$a/$b;
echo $c; //5$a=12;
$b=2;
echo $a%$b; //0
$a=10;
$b=1;
echo $a%$b; //1前++:当在一个语句里面需要使用到被自增的变量的值的时候,先执行自增,然后再返回自增之后的值
$a=10;
++$a; //$a=$a+1
echo ++$a;//11
$a=10;
$b=++$a; //先$a=$a+1;再返回
echo ++$a;
$a=10;
++$a;//这种情况不需要用到自增变量值的时候,和后++无区别
echo $a;后++:当在一个语句里面需要使用到被自增的变量的值的时候,先返回变量的值然后再去执行自增
$a=10;
//++$a;//$a=$a+1;
//$a++;//$a=$a+1;
echo $a++; //echo $a; $a=$a+1;
echo '<br />';
echo $a; //11<?php
//前++
$a=10;
$b=++$a; //先$a=$a+1; 再赋值给$b
echo $b; //11
//后++
$a=10;
$b=$a++; //先赋值$b=$a; 再$a=$a+1;
echo $b; //10
?>注意:
$a=10;
++$a; //$a=$a+1
echo ++$a;前--
$a=10;
//$a--;//$a=$a-1; 和--$a没区别;
echo --$a;//$a=$a-1; echo $a; $a=9
echo '<br />';
echo $a;后--
$a=10;
//$a--;//$a=$a-1; 和--$a没区别;
echo $a--; //echo $a;$a=$a-1;
echo '<br />';
echo $a;注意:自增或者自减是对变量而言的!
$a='孙胜利';
$b='测试字符串连接符';
echo $a.$b; //孙胜利测试字符串连接符1)=
把右边的值赋给左边的变量
$a=1;2)二元运算符
表达式是 PHP 最重要的基石。在 PHP 中,几乎所写的任何东西都是一个表达式。简单但却最精确的定义一个表达式的方式就是“任何有值的东西”。
<?php
$b=2;
$a=1+$b;
?>3)+=
$a=1;
$b=2;
$a+=$b; //$a=$a+$b;
echo $a; //34)-=
$a=2;
$b=1;
$a-=$b; //$a=$a-$b
echo $a; //1注:
赋值运算符整个语句是有值的,所以整个语句就是一个表达式,所以也可以写为
$a=$b=2;相当于$a=($b=2);也相当于$a=2;$b=2;
对操作数(按照比较运算符的要求,规则)进行比较
如果比较出的结果满足比较运算符的要求那么结果就是true(真,成立,满足),否则就是false(假,不成立,不满足)
<?php
$a=1;
$b=1;
var_dump(false); //false
?>使用echo输出布尔类型值的时候
echo true;它在页面中会输出1
echo false;它会在页面中什么都不输出
注:在测试的过程中如果需要输出布尔类型值的时候我们最好使用var_dump()来输出更明了的结果!
如果值相等则就是 true(真,成立)
如果值不相等那么就是false(假,不成立)
<?php
$a=1;
$b=1;
var_dump($a==$b);//boolean true //var_dump()函数:不仅可以输出值还可以输出值的类型
echo $a==$b; //true
?>如果两边操作数的值,全等那么就是true否则就是false
$a=11;
$b='11';
//var_dump($a==$b);//true
var_dump($a===$b);//false如果两边操作数的值不相等那么就是true,否则就是false
$a=1;
$b=11;
var_dump($a!=$b); //true如果两边操作数的值不相等那么就是true,否则就是false
$a=1;
$b=11;
var_dump($a!=$b); //true如果两边的操作数不全等那么就是true,否则就是false
<?php
/*
$a=1111;
$b=2;
var_dump($a!=$b); //true (!=不等:值不相等)
var_dump($a!==$b); //true (!==不全等,类型不相等)
*/
$a=11;
$b='11';
var_dump($a!=$b); //false boolean false(两个值相等,忽略类型)
var_dump($a!==$b); //true, $a不全等于$b (两个值的类型不相等,不全等)
?>比较两边操作数的值,前面的是否小与后面的
$a=1;
$b=1;
var_dump($a<$b);//false, $a小与$b这句话正确还是错误,输出布尔值$a=10;
$b=1;
var_dump($a>$b); //$a=1;
$b=1;
var_dump($a<=$b); //$a小与等于$b就是true,否则就是false$a=2;
$b=1;
var_dump($a>=$b); //true对表达式进行逻辑运算,运算出的结果是布尔类型的值(true,false)
参与逻辑运算的表达式的值是布尔类型的值,如果不是布尔类型的值会被PHP自动转换成布尔类型的值,然后再参与运算!
左右两边的表达式的值都为true的时候,运算的结果就是true,
只要其中任意一个为false,运算的结果就是false;
true 及格
false 不及格
左右两边的表达式就是我们要考试的科目;
要求:当语文和数学都及格的时候那么,最终的结果才能够通过(true),否则就是不通过(false)
<?php
$a=true; //语文
$b=true; //数学
echo ($a && $b); //boolean true
$a=true; //语文
$b=false; //数学
echo ($a && $b); //boolean false
?>中间隐含一个问题:“短路”,运算符的优先级的问题!
$a=false;
$b=1;
$a && ++$b; //$a已经是false了,后面的可以忽略了
echo $b; //1 短路,上面的++$b被短路了,因此$b还是原来的值
我们的程序语言的设计者认为:
只要有逻辑运算符 (逻辑与,逻辑或)那么运算结果就是就是一个true或者false,那个这个整个运行的过程就不重要了!当然短路问题并不会遇到太多,就算遇到也不会有什么影响!
左右两边的表达式的值有一个为true,运算的结果就是true,
只有当两边的值都是false的时候,结果才会是false
$a=false;//语文
$b=true;//数学
var_dump($a || $b); //boolean true现实举例:
要求:当语文和数学有一门及格那么最终的结果就是通过true
中间隐含一个问题:“短路”,运算符的优先级的问题!
$a=true;
$b=1;
$a || ++$b; //$a已经是true了,后面的可以忽略了,结果一定是true
echo $b; //++b被短路,$b依旧是原来的值1.我们的程序语言的设计者认为:
只要有逻辑运算符 (逻辑与,逻辑或)那么运算结果就是就是一个true或者false,那个这个整个运行的过程就不重要了,当然短路问题并不会遇到太多,就算遇到也不会有什么影响!
左右两边的表达式的值不一样的时候结果就是true,如果一样那么运算的结果就是false
$a=false;
$b=false;
var_dump($a xor $b); //boolean true
$a=false;
$b=true;
var_dump($a xor $b); //boolean false将原来表达式的值否定掉,原来是true,那么结果就是false
原来是false,那么结果就是true
$a=false;
var_dump(!$a); //boolean true
$b=true;
var_dump(!$b); //boolean false三元运算
格式:表达式1 ? 表达式2 : 表达式3;
如果表达式1的值为true,那么就执行表达式2,否则那么就执行表达式3
$a=false ? 10 : 20;
echo $a;//20可以把系统的命令放在里面执行!
涉及到跨平台:(几乎不用)
$a=`ipconfig`;
$b=`ifconfig`;
var_dump($b); //NULLecho @$a;谁的优先级别高就先算谁!
规定了从那个方向开始算的问题!
①[无结合方向]递增递减(++ --)
②[右结合]逻辑非(!)
③[左结合]乘,除,取余(* / %)
④[左结合]加,减,字符串连接符(+ - . )
⑤[无结合]包含大于号或者小于号的比较运算符(< <= > >= <>)
⑥[无结合]不包含大于号或者小于号的比较运算符(== != === !==)
⑦[左结合]逻辑与(&&)
⑧[左结合]逻辑或(| |)
⑨[左结合]三元运算符(?:)
⑩[右结合]赋值运算符(= 二元 += -=)
⑪[左结合]逻辑异或(xor)
用圆括号可以将表达式里面的某一块看成一个整体!
*使用括号可以增强代码的可读性。
哪怕有的地方不需要加括号你也可以加上以增加可读性!
<?php
$a=1 + (5 * 3);
echo $a; //16
?><?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
// PHP 的三元操作符跟 C/C++ 有区别
$a = (true ? 0 : true) ? 1 : 2; // false ? 1 : 2; 2
echo $a;
$a = 1;
$b = 2;
$a = ($b += 3); // $b+=3 -> $b=$b+3=2+3=5; $a=5
echo $a; //5
echo '<br />'; //换行
echo $b; //5
?><?php
$a = 1;
echo $a + $a++; // $a=$a+1=2
?>对PHP程序执行的过程进行控制!
PHP有哪些手段对程序执行过程进行控制!
自上而下的执行即可! 对这个执行过程没有控制!
分支执行可以根据条件是否满足来选择执行某些代码,PHP的分支执行主要通过两种语句(if,switch)来实现!
注:我们if语句的表达式所控制的代码,最好用花括号括起来,哪怕就是一条语句也用花括号括起来!
if语句可以嵌套,这是根据实际需求来的!
if(表达式) 语句1;
表达式的值为true 那么就执行语句1,否则就不执行!
$pass=60;
$a=40;
if($a>=$pass){
echo '恭喜,考试通过';
echo 'dwqdwqdq';
//.......各种其他语句!
}
echo '代码执行结束!';
$pass=60;
$a=40;
if($a>=$pass){
echo '恭喜你!考试通过啦!';
//.......
echo '很遗憾,您的科目没有通过!';
}else{
//.......
}
$a=84;
$grade1=60;//低于60不及格
$grade2=75;//及格
$grade3=85;//良好
if($a<$grade1){
echo '不及格';
}elseif($a<$grade2){
echo '童鞋你及格了';
}elseif($a<$grade3){
echo '良好!';
}else{
echo '优秀';
}
switch(表达式){
case 值 1://case相当于==(值相等,三个=才是类型和值都相等)
语句块1;
break;//跳出,打断的意思
case 值 2:
语句块2;
break;
.......
default: //默认
语句块n
}注:
1)表达式的值最好是整形或者字符串!
2)不要忘记break语句!来跳出switch语句!每个case语句后面都加上break
3)如果某个case语句后面并没有接语句块,那么就说明这个语句块的内容是同下!
4)case后面的语句块是不需要{}括起来的
计算机最擅长的功能之一就是按照规定的条件,重复执行某些操作,这是程序设计中最能发挥计算机特长的程序结构。
while(表达式){
各种语句....
}当表达式的值为true,那么就执行下面的语句块,当语句块执行结束之后,继续返回上面来判断表达式的值是true还是false,如果还是true,那么就继续执行语句块
知道,这个表达式的值为false,那么这个while语句就执行结束了!
$i=0;
while($i<10){
echo $i++.'<br />';//连接符
}
echo '执行结束了!';do{
各种语句
}while(表达式);举例:
$i=10;
do{
echo $i++;
}while ($i<10);
echo '......';注:与while语句区别就是,do while语句至少会执行一次!
for(表达式a;表达式b;表达式c){
各种语句
}表达式a会放一些初始化话的语句,$i=0,放多个表达式,中间用,隔开
表达式b:会放一些用来判断true或者false的表达式!,也可以放多个表达式,中间用逗号隔开
表达c:会放一些对初始化的变量进行自增的语句!放多个表达式,中间用,隔开
执行顺序:
表达式a
表达式b 如果是true
语句块
表达式c
表达式b
(一直执行到不满足表达式b才停止循环)
举例:
for($i=0;$i<10;$i++){
echo "执行到第{$i}遍了<br />";
}
for($i=0,$j=0;$i<10;$i++,$j++){
echo "{$j}执行到第{$i}遍了<br />";
}
for($i=0,$j=0;$i<10,$j<10;$i++,$j++){
echo "{$j}执行到第{$i}遍了<br />";
}作用:用于switch语句,for,while,do...while,foreach,用于中断这些语句!
后面可以接上一个数字来表示跳出几层循环!默认不加就是跳出当前循环语句!
举例:
for ($i=0;$i<10;$i++){
if(i==5){
break;//中断当前所在循环语句,后面的数字表示跳出几层
}
echo "执行到第{$i}遍!<br />";
}
echo '执行结束!';作用:只能用在循环语句,跳出本次循环,并不是结束整个循环语句!
作用:结束当前整个程序的执行!
举例:
echo '执行到第1步了!<br />';
exit( );
echo '执行到第2步了!<br />';
echo '执行到第3步了!<br />';
echo '执行到第4步了!<br />';
echo '执行到第5步了!<br />';
//输出执行到第1步了!
echo '执行到第1步了!<br />';
exit('对不起,程序执行完毕!');//结束整个PHP程序的运行!
echo '执行到第2步了!<br />';
echo '执行到第3步了!<br />';
echo '执行到第4步了!<br />';
echo '执行到第5步了!<br />';
->执行到第1步了!
对不起,程序执行完毕!function 函数名( [形式参数1,形式参数2,....形式参数n] ) {
//各种PHP代码....
//......
return 表达式;//可以返回,也可以不返回,如果不写那么默认返回null
}function test(){
echo '你好!'; //无返回值,函数不调用,不会返回值
}函数的调用需要遵循定义函数的时候写的规则,一一对应,将具体的实际参数传给定义函数时候写的形式参数!
调用函数之后执行的过程是相对独立的,互补干扰,默认没有联系!
执行完毕返回调用的位置继续向下执行
返回给调用者,默认返回NULL
原材料或者是这个零件的一些具体的参数
function test(){
echo '你好!';
}
//调用
test (); //函数调用后输出函数体内代码 输出你好!调用一次开辟一次空间
test ();
echo 'PHP脚本执行完毕';
参数:原材料或者是这个零件的一些具体的参数!
function add ($a,$b){ //形式参数,就是一个形式,因为他们里面并没哟具体的值
echo $a+$b;
}
add(2,3); //5
function add ($a,$b){
return $a+$b; //return返回值给调用的地方,结束这个函数的运行
}
$i = add(10,20)*10
echo $i; //30
function add ($a,$b){
echo $a+$b;
}
var_dump(add(10,20)); //没写返回值,默认返回NULL在函数内定义,作用域仅限于函数内部
function test(){
$a=1;//局部变量$a,仅在这个函数内部有效 函数内定义
}
echo $a; //报错
function test(){
$a=1;//局部变量$a,仅在这个函数内部有效
echo $a;
}
return $a; //调用函数,返回值
在函数外定义,作用域从变量定义处开始,到本程序文件的末尾
注:PHP函数中无法直接使用全局变量,使用前必须使用global声明变量
$i=10;//全局变量(外部变量) 函数外定义
define('MY_NAME','孙胜利');
function test(){
echo MY_NAME;
global $i;//声明$i为全局变量,然后再这个函数内部就可以使用$i
echo $i;
$a=1;
}
test(); 
使用static关键字来定义变量
函数执行完后变量不会立即消失,当再次调用时,静态变量保存的值依然存在,且仅再第一次执行函数时会初始化值
function test(){
static $a=10; //静态变量$a,初始化静态变量,仅在第一次调用的时候执行
echo ++$a; //当第二次执行这个函数的时候$a这个变量依然存在并且里面的也值依然存在!
}
test();
echo '<br />';
test();
echo '<br />';
test();
echo '<br />';
test();
echo '<br />';
test();
echo '<br />';
test();
echo '<br />';
test();
默认的,我们在传递参数的时候默认使用的就是这个方式!
对形式参数的操作,不影响到实际参数(变量)的值,两者相当于没有联系!
function test($a){ //自定义函数
echo ++$a;
}
$i=10;
test($i); //调用函数
echo '<br />' .$i;
按引用传递参数,相当于形式参数和实际参数指的是同一个人,只是名字不一样,对于形式参数的操作会直接影响到实际参数(变量);
function test(&$a){
echo ++$a;
}
$i=10;
test($i);
echo '<br />' .$i;
可以给形式参数设置默认值,设置方法很简单直接赋值即可!
给形式参数加默认值的时候是从右往左加的,右边的必须有,才能够给左边的加!
function test($a=10){
echo ++$a;
}
test (); //10 不传为默认值
function test($a=10){
echo ++$a;
}
test (20); //20 传20
function test($a,$b){
echo $a+$b;
}
test (20,10);

PHP提供给我们的,可以直接使用
func_get_args( ); //获取当前用户自定义函数的所有实际参数,返回值是一个索引数组,数组中的元素依次对应函数被调用时传入的参数
func_get_arg( ); //调用这个func_get_arg函数的时候可以传入一个值表示获取第几个实际参数(从0开始)
func_num_args( ); //返回传入所在自定义函数的参数的个数
这三个函数可以使用在我们的自定义函数内部,能够返回给我们一些关于参数的信息!
function test(){
var_dump(func_get_args()); //将传进去的参数以数组形式调用出来
}
test(21,222,3333,'单位取得完全','aahssjs'); //调用test函数,并传入值
function test(){
var_dump(func_get_arg(4)); //调用这个func_get_args函数的时候可以传入一个值表示获取第几个实际参数(从0开始)
}
test(21,222,3333,'单位取得完全','aahssjs');
function test(){
var_dump(func_num_args()); //返回传入所在自定义函数的参数的个数
}
test(21,222,3333,'单位取得完全','aahssjs'); 
直接把函数赋值给变量
可变函数不能用于例如 echo,print,unset(),isset(),empty(),include,require 以及类似的语言结构。需要使用自己的包装函数来将这些结构用作可变函数。
function test(){
echo '我是test函数!';
}
$a=='test'; //把函数名字加上引号,赋值给变量即可
$a(); //test();定义:在函数内部自己调用自己的函数。
递归函数:
1)函数在被调用的执行过程中会在内存里面分配空间用于存储临时数据,那么函数在执行过程中默认之间时没有联系的(除了静态变量,按引用传,全局变量)。里面的变量默认都是局部变量,相互之间没有影响!
2)递归函数,在函数的内部需要有适时结束函数运行的条件!
function test($n){
echo $n.'$nbsp;'; //$nbsp:空格
if($n>0){
test($n-1); //自己内部调用自己 即递归函数
}else{
echo '<-->';
}
echo $n.' ';
}
test(3);
/*
死循环了,所以在使用递归的时候要注意避免这种情况!
function test($n){
echo $n.'$nbsp;';
test($n-1);
}
test(3);
*/



方法一:
1) 变量名称[索引值]=数据;
2) 变量名称[]=数据;//不写索引值默认是 索引数组,从0开始
方法二:
变量名称=array(
索引值=>数据,
..........
);
数据里面还可放数组类型的数据,同一个数组中存储任何类型的数据
访问数值的方法
变量名称[索引值][索引值]....
创建数组方法一:
//1)$student[索引值]=具体的值
$student[0]=10;
$student[1]='孙胜利';
$student[2]=true; //在使用echo和print_r时,输出的为1,用var_dump时,输出的为true
$student[3]=60.5;
//需要使用print_r()函数来输出数组的具体内容
print_r( $student);
//2)$student[索引值]=具体的值
//如果省略索引值不写,那么默认的索引值就是整数,并且从0开始,依次增1
$student[]=10;
$student[]='孙胜利';
$student[]=true; //在使用echo和print_r时,输出的为1,用var_dump时,输出的为true
$student[]=60.5;
//需要使用print_r()函数来输出数组的具体内容
var_dump( $student);
创建数组方法三:
//$student=array(suoyinzhi=>具体的值, …………);
$student=array(10,'孙胜利',true,60.5);
var_dump( $student);
$dtudent1=array(
0=>10,
1=>'孙胜利',
2=>true,
3=>60.5
);
var_dump($student1);
//使用数据里面具体数据的方法
//数组变量名称[索引值];
$student['num']=10;
$student['name']='孙胜利';
$student['sex']=true;
$student['grade']=60.5;
var_dump($student);
//数组嵌套(多维数组)
//二维数组
$students=array(
0=>array(1,'孙胜利',true,60.5); //一维数组
1=>array(2,'李雷',true,80.5);
2=>array(3,'韩梅梅',true,85.5);
);
var_dump($students);
echo $students[0][1];
遍历数组:每个都经历一遍的意思
用的比较少,因为有缺陷
//图1
$arr=array(
'a','b','c','d','e','f'
);
for($i=0;$i<10;$i++){
echo $i.'<br />';
};
//图2
$arr=array(
'a','b','c','d','e','f'
);
//count(数组变量/数组): 返回数组里面数据的个数,还可以获取多维数组的个数
echo count($arr); //6
//图三
$arr1=array(
array(1,2,3);
array(4,5,6)
);
//echo count($arr1);
echo count($arr1); //2 两个数组
//图4
$arr1=array(
array(1,2,3),
array(4,5,6)
);
//echo count($arr[,1]);
echo count($arr1,1); //8 两个数组为2个,再加上1,2,3,4,5,6这6个,一共8个
$arr=array(
'a','b','c','d','e','f'
);
for($i=0;$i<count($arr);$i++){
echo $arr[$i];
};



foreach(数组变量 as 变量1){
//每次循环执行的语句
变量1代表当前正在经历(访问)的数据
}
foreach(数组变量 as 变量1=>变量2){
//每次循环执行的语句
变量1代表当前正在经历(访问)的数据的索引值
变量2代表当前正在经历(访问)的数据
}/*
foreach来遍历数组
这个比较常用,因为是专门为我们来遍历数组
*/
$arr1=array(
'name'=>'孙胜利',
'num'=>10
);
$arr=array(
'a','b','c','d','e','f'
);
foreach($arr as $value){
echo $value.'<br />';
};
$arr1=array(
'name'=>'孙胜利',
'num'=>10
);
foreach($arr1 as $value){
echo $value.'<br />';
};
$arr1=array(
'name'=>'孙胜利',
'num'=>10
);
foreach($arr1 as $key=>$value){
echo $key.'=>'.$value.'<br />';
};
/*
递归思想
*/
$arr=array(
'a',
'b',
'c',
'd',
array(
1,2,3,4,5
)
);
foreach ($arr as $val){
var_dump($val);
};



//总结案例
<?php
$students=array(
array(1,'孙胜利',true,60.5);
array(2,'李雷',true,80.5);
array(3,'韩梅梅',true,85.5);
);
echo '<table border=1>';
foreach ($students as $val){
if($val[2]===true){
$val[2]='男';
}else{
$val[2]='女';
}
echo "<tr><td>{$val[0]}</td><tr><td>{$val[1]}</td><tr><td>{$val[2]}</td><tr><td>{$val[3]}</td></tr>";
}
echo'</table>';
?>已经定义好了(存在)的变量(存放的数据的类型是数组)。
超级全局变量,作用域(有效区域)!
超全局变量 — 在全部作用域中始终可用的内置变量
$GLOBALS — 引用全局作用域中可用的全部变量
$_SERVER — 服务器和执行环境信息
$_GET — HTTP GET 变量
$_POST — HTTP POST 变量
$_FILES — HTTP 文件上传变量
$_REQUEST — HTTP Request 变量
$_SESSION — Session 变量
$_ENV — 环境变量
$_COOKIE — HTTP Cookies
$php_errormsg — 前一个错误信息
$http_response_header — HTTP 响应头
$argc — 传递给脚本的参数数目
$argv — 传递给脚本的参数数组传多个参数的格式:
?参数名=参数值&参数名=参数值......
举例:
http://localhost/demo5_3/index.php?参数名=参数值
在服务器端(请求的php文件这边)可以通过$_GET来获取到
$_GET索引值为参数名,索引值对应的数据就是参数值



比如表单 post发送过来的!
可以通过$_POST来获取到! $_GET无法获取到



$array = array(1, "hello", 1, "world", "hello");
$arr=array_count_values($array);//函数返回数组类型的数据
print_r($array);//原来的数组不会受到任何影响$search_array = array('first' => 1, 'second' => 4);
var_dump(array_key_exists('second',$search_array));$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red',4=>15);
var_dump(array_search('15', $array,true)); //true:比较'15'的类型,没有第三个参数就不比较第一个参数的类型
//上面的'15'是字符串类型,没有true的话只要是15就行,有true决定了必须要是字符串15才可$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red',4=>15);
var_dump(count($array)); //int(5)$os = array("Mac", "NT", "Irix", "Linux");
var_dump(in_array('Mac', $os));$arr=array(60,80,100);
list($sunshengli,$xiaohong,$xiaoming)=array(60,80,100);
echo $sunshengli;
//仅能用于数字索引的数组并假定数字索引从0开始.$students=array(
'sunshengli'=>60,
'lilei'=>80,
'hanmeimei'=>100,
'zhangsan'=>90
);
asort($students);
print_r($students);直接对数组里面的数据进行排序,第二个参数
SORT_REGULAR - 正常比较单元(不改变类型)
SORT_NUMERIC - 单元被作为数字来比较
SORT_STRING - 单元被作为字符串来比较
SORT_LOCALE_STRING - 根据当前的区域(locale)设置来把单元当作字符串比较。
function odd($var)
{
return($var % 2 == 1);
}
function even($var)
{
return($var % 2 == 0);
}
$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array(6, 7, 8, 9, 10, 11, 12);
echo "Odd :\n";
print_r(array_filter($array1, "odd"));
echo "Even:\n";
print_r(array_filter($array2, "even")); $str=' abc ';
var_dump($str);
var_dump(trim($str));
$str='abcabcdefac';
var_dump($str);
var_dump(trim($str,'bac')); //去除两边的abc //如果要去除多个字符可以连着写!$str='test';
var_dump($str);
$str1=strtoupper($str);
var_dump($str1);
$str='TeSt';
var_dump($str);
var_dump(strtolower($str));
var_dump($str);$str='testteste';
var_dump(substr_count($str,'te'));
$text2 = 'gcdgcdgcd';
echo substr_count($text2, 'gcdgcd');
$str='testteste';
var_dump(substr_count($str,'te',1)); //计算偏移位置,从第1位开始找,默认从第0位(首位)开始找
$str='testteste';
var_dump(substr_count($str,'te',1,8)); //不能超出字符串 从第1位开始到第8位$str='testteste';
var_dump(strpos($str, 't1'));
if(strpos($str, 't')===false){
echo '没找到!';
}else{
echo '找到啦!';
}
$str='testteste';
var_dump(strpos($str, 't',1));$str='testteste';
var_dump($str);
var_dump(strstr($str,'s'));
var_dump(strstr($str,'s',true));$str=array(
'abc123abc',
'123abcabc',
'abcab123c'
);
var_dump($str);
$str1=str_replace(array('1','2','3'),array('一','二','三'),$str,$count); //替换后输出新的
echo $count;
var_dump($str1);$str=<<<START
<p style="color:red;font-size:128px;">单位确定为取得完全</p>" '
START;
echo $str;
echo "\n";
echo htmlspecialchars($str);$str=<<<START
<p style="color:red;font-size:128px;">单位确定为取得完全</p>
<div style="color:red;">的武器大全我</div>
START;
//echo $str;
//echo "\n";
echo strip_tags($str,"<div><p>");$str='testdqwdwqdwqdqdwq';
echo substr($str,3,2);
$str='test';
echo substr($str,-3,2);$str='test,test1,test2,test3';
var_dump(explode(',',$str,2));$str='test';
var_dump(str_split($str,3));描述了一类字符串的特征,然后通过这个特征可以配合一些特定的函数,来完成对字符串更加复杂的一系列操作!
普通字符和特殊字符组成的一个字符串
preg_match_all( ):按指定的正则表达式,在给定的 字符串中进行搜索,匹配到符合特征的部分取出来。$arr取出;var_dump( $arr )以数组形式输出
我们一般习惯使用正斜线"/"作为定界的字符,前后一致,也可以用 #,!,{ },|
\d 匹配任意一个十进制数字,等价于[0-9]
\D 匹配任意一个除十进制数字以外字符,等价于[^0-9]
\s 匹配任意一个空白字符,比如换页符、换行符、回车符、制表符、垂直制表符
\S 匹配除空白字符以外的任何一个字符
\w 匹配任意一个数字或字母或下划线
\W 匹配除数字、字母、下划线以外的任意一个字符
. 匹配除换行符以外的任意一个字符 ( //如果真的只是想匹配一个普通的 . 那么在正则表达式的时候请把 . 使用 \ 来转义 )
* 匹配0次、或1次、或多次其前面的字符( 放在 * 前面的那个字符可以出现0次,也可以出现1次,也可以出现多次 )
+ 匹配1次或多次其前面的字符 ( 放在+前面的那个字符可以出现一次,也可以出现多次 ,但是不能不出去)
? 匹配0次或1次其前面的字符 ( 放在?前面的那个字符可以出现0次,或者1次 )
{n} 表示其前面字符恰好出现n次
{n,} 表示其前面字符出现不少于n次 (放在{n,}前面的那个字符出现的次数应该大于等于n次)
{n,m} 表示其前面的字符至少出现n次,最多出现m次
。*? 解决懒惰匹配的问题,懒惰匹配
^或\A 匹配字符串开始位置
$或者\Z 匹配字符串的结束位置
| 匹配两个或多个模式
[] 匹配方括号中的任意一个字符
[^] 匹配除方括号中字符以外的任意一个字符
() 将括号中作为一个整体以便将其中的内容获取到
在我们的正则表达式中 可以使用圆括号来将某一段括起来,在圆括号的后面部分,我们可以使用
\\数字 来代表圆括号部分所匹配到的内容!
调整表达式的解释,增强正则表达式的处理能力
常见模式修正符
i 在和模式进行匹配时不区分大小写
m 多行匹配, 如果目标字符串中,没有"\n"字符, 或者模式中没有出现^或$, 设置这个修饰符不产生任何影响
(使用条件:1. 目标字符串必须包含“\n”
在目标字符串中必须出现“\n”就表示新的一行开始
2. 正则表达式中必须要出现^或者$)
在Windows系统中所看到的换行(现象)其实是通过连哥哥字符来完成的( \r \n )
在Linux系统中看到的换行(现象),就是通过\n来完成的
\r :回车符
\n:换行符
s 如果设定了此修正符,那么 . 将匹配所有的字符包括换行符( \n)
U 禁止贪婪匹配
注:模式修正符是可以多个搭配使用的
参数说明:
第一个参数:正则表达式
第二个参数:目标字符串
第三个参数:放一个变量,执行完成后,里面会有匹配到的部分以及等等一些数据
第四个参数:可以传PREG_OFFSET_CAPTURE进入,默认传的是0
第五个参数:可以传一个值,来表示从目标字符串的那个位置开始搜索(单位是字节)
第四个参数(可选):PREG_PATTERN_ORDER , PREG_SET_ORDER,PREG_ODDSET_CAPTURE
第五个参数:可以传一个值,来表示从目标字符串的那个位置开始搜索(单位是字节)
参数说明:
第一个参数:正则表达式
第二个参数:要替换成的字符串
第三个参数:目标字符串
第四个参数(可选):默认是-1,就是替换所有符合特征的部分的
第五个参数(可选):你可以放一个变量在这边
注意:第一个参数与第二个参数传数组,一一对应的去替换!
date_default_timezone_set('Asia/Shanghai');//设置时区time( )
mktime( )
date_default_timezone_set('Asia/Shanghai');//设置时区
$nowTime=time();
$time1=mktime(0,0,0,10,1,2014); //取得一个日期的 Unix 时间戳
echo '距离2014年国庆还有'.(($time1-$nowTime)/60/60/24).'天';date()格式化一个本地时间/日期
第一个参数:必填,写上你所需要的时间日期的格式,把format 字符放在第一个参数里面会被转换成对应的信息,其他的字符还是原来的样子
date('Y-m-d G:i:s')
自定义格式化Unix时间戳 为指定的时间格式!
microtime( ) 返回当前 Unix 时间戳和微秒数
var_dump(microtime( )); //字符串类型
var_dump(microtime(true)); //浮点型1. is_file() //判断给定文件名是否为一个正常的文件
2. is_dir() //判断给定文件名是否是一个目录1. file_exists() //检查文件或目录是否存在
2. filesize() //取得普通文件大小
3. is_readable() //判断给定文件名是否可读
4. is_writable() //判断给定的文件名是否可写
5. filectime() //获取文件的创建时间
6. filemtime() //获取文件的修改时间
7. fileatime() //取得文件的上次访问时间
8. stat() //获取文件大部分属性值1.basename()//返回路径中的文件名部分
2.dirname()//返回路径中的目录部分
3.pathinfo()//返回文件路径的信息
4.opendir()//打开目录句柄
5.readdir()//从目录句柄中读取条目,返回目录中下一个文件的文件名
6.rewinddir()//倒回目录句柄
7.closedir()//关闭目录句柄
8.mkdir()//新建目录
9.rmdir()//删除指定的空目录
10.scandir()//列出指定路径中的文件和目录
1. fopen()//打开文件或者 URL
2. fread()//读取文件
3. fgets()//从文件指针中读取一行
4. feof()//测试文件指针是否到了文件结束的位置
5. fwrite()//写入文件
6. rewind()//倒回文件指针的位置
7. flock()//轻便的咨询文件锁定
8. ftruncate()//将文件截断到给定的长度
9. fclose()//关闭一个已打开的文件指针
10. file() //把整个文件读入一个数组中
11. copy()//拷贝文件
12. unlink()//删除文件
13. file_get_contents()//将整个文件读入一个字符串
14. file_put_contents()//将字符串写入文件中
15. rename()//重命名一个文件或目录
16. readfile()//读入一个文件并写入到输出缓冲文件的上传的过程这些细节我们是不需要管的,都是自动的,上传的文件默认是放在一个临时的目录里面的,我们要做的就是把这些临时目录
里面的文件移动到我们需要的地方就OK啦!
<?php
header('Content-type:text/html;charset=utf-8');
if(isset($_POST['submit'])){
if(is_uploaded_file($_FILES['myfile']['tmp_name'])){
$arr=pathinfo($_FILES['myfile']['name']);
$newName=date('YmdGis').rand(1000,9999);
if(move_uploaded_file($_FILES['myfile']['tmp_name'],"uploads/{$newName}.{$arr['extension']}")){
echo '恭喜你!上传成功!';
}else{
echo '对不起移动文件失败!';
}
}else{
exit('可能有攻击,请你做合法的事情!');
}
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>上传页面</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" name="submit" value="开始上传" />
</form>
</body>
</html>获取文件的MIME类型
<?php
if(!function_exists('finfo_open')){
header('Content-type:text/html;charset=utf-8');
exit('请先开启PHP扩展:fileinfo!');
}
$file='a.rar';
$fileinfo=finfo_open(FILEINFO_MIME_TYPE);
$mimeType=finfo_file($fileinfo,$file);
finfo_close($fileinfo);
//发送指定的文件MIME类型的头信息
header('Content-type:'.$mimeType);
//指定下载文件的描述
header('Content-Disposition:attachment;filename='.basename($file));
//指定文件的大小
header('Content-Length:'.filesize($file));
//读取文件内容至输出缓冲区,返回这个文件
readfile($file);数据库:信息存储的仓库,包括一系列的关系措施
表:一个数据库中可以有若干张表(形式上你可以看出我们日常生活中建立的表)
字段:表里面的信息会分若干个栏目来存,这些栏目呢,我们在数据库技术中叫"字段",栏目里面存的具体信息叫"字段值"
记录:一条信息我们叫一条记录
一个数据库管理系统中可以建立若干个数据库,每个数据库中又可以建立若干张表,每张表中可以有若干条记录。
数值类型、日期类型、字符串类型
tinyint、smallint、mediumint、int和bigint
配合int(数字)来用,表示显示的时候一个显示宽度
eg:int(5) 若输入的时候不足5位,显示的时候不足5位用0补齐
主键可以唯一标识某条记录的一个字段或者多个字段
create table 表名(字段名称 类型 primary key,....);
create table 表名(字段名称1 类型,....,primary key(字段名称1));
删除:
alter table 表名 drop primary key;
注意:如果字段具有auto_increment属性必须先删除auto_increment属性
主键最好不要设置在某个与实际信息相关的字段上,主键的作用应该明确且单一
主键最好设置在整数类型的字段上
主键必须不同,且不能为null
既然主键必须不同所以我们会配合auto_increment属性
一个表只能有一个主键,最好只设置在一个字段上
单精度(float):单精度的浮点数精确到大约7位小数位(整数部分加上小数部分的位数)
双精度精度(double):双精度的浮点数精确到大约15位小数位(整数部分加上小数部分的位数)
decimal(7,2) //总位数为7,小数位数为2
DATETIME是常用的日期类型
create table t1(dt datetime);
insert into t1 values(now());
M为0~255之间的整数,表示可以存M个字符(中文/英文字符总共个数是M个就可以)
M为0~65535之间的整数,表示可以存M个字符,具体M最大多大和字符集有密切关系
注意:varchar列的最大的存储空间是65,532字节,如果是英文字符集(一个英文字符占1个字节)就是可以放65532个英文字符
TINYTEXT 允许长度0~255字符
TEXT 允许长度0~65535字符
MEDIUMTEXT 允许长度0~16,777,215字符
LONGTEXT 允许长度0~4,294,967,295字符
char类型的字符所占的存储空间是固定,不管你用的时候存了几个字符,它所占的空间都是你当初设定的字符空间
比如char(255) 哪怕你存的只是1个a,那么它也是站255个字符长度的空间
varchar列所占的存储空间是可变的,根据存入的字符长度来确定实际占多少的空间
varchar(255) 实际所占的空间就是实际字符的长度+1个字节!
varchar(超过255) 实际所占的空间就是实际字符的长度+2个字节!
在检索时,char列删除尾部的空格,而varchar则保留这些空格。
选择:由于char是固定长度,所以它的处理速度比varchar快,但是缺点是浪费存储空间。所以对于那些长度变化不大的数据可以选择此列
create table t1(flag enum('a','b','c','d'));
insert into t1 values('a'),('a'),('f');
注意:enum类型存储的数据忽略大小写,且只允许从值集合中选取单个值
create table t1(flag set('a','b','c','d'));
insert into t1 values('a,b'),('a,d,a');
注意:可以从允许值集合中选择任意1个或多元素进行组合,所以对输出的值只要在允许的组合范围内,都可以正确地注入到set类型的列中
对于超出允许范围的值不允许注入,
对于包含重复的成员的集合只取依次进行注入
数据定义语句,通过这类语言可以对数据库进行创建删除更改
数据操纵语句,用于添加、删除、更新和查询数据库记录并检查数据完整性
数据控制语句,通过此类语句可以对数据库的相关权限进行设置
对数据库内部的对象进行创建、删除、修改等操作的语言,DDL语句更多的是由数据库管理员(DBA)使用,开发人员一般很少使用
登录mysql之后就可以使用sql语句对数据库进行各种操作啦!
show databases; 查看数据库列表
drop database 数据库名称;
create table 表名(
字段1名 字段1类型 列的约束条件,
字段2名 字段2类型 列的约束条件,
...
)
desc 表名;
show create table 表名 \G
\G选项使得记录能够按照字段竖向排列,以便更好地显示内容较长的记录,\G后面无需再加分号
drop table 表名;
alter table 表名 modify [column] 字段定义 [first|after 字段名];
alter table 表名 add [column] 字段定义 [first|after 字段名];
alter table 表名 drop [column] 字段名;
alter table 表名 change [column] 旧的字段名 字段定义 [first|after 字段名];
注:change与modify都可以修改表的定义,不同的是change后面需要接两次列名,不方便,但是优点是change可以修改字段名称
前面介绍的字段增加和修改语法(add/change/modify)中,都有一个可选项first|after 字段名,这个选择可以用来修改
字段在表中的位置新增的字段默认是加载在表中最后位置,而change/modify 默认都不会改变字段的位置
alter table t1 modify id2 tinyint first;
alter table t1 modify id2 tinyint after id1;
注意:change/first|after 字段名 这些关键字都是属于MySQL在标准SQL上的扩展,在其他的数据库上不一定适用
alter table 表名 rename [to] 新的表名;
查询 select * from 表名;
insert into 表名(字段1,字段2,字段3,...,字段n) values(值1,值2,值3,...,值n);
也可以不用指定字段名,但是values后面的顺序应该和字段的排序一致
insert into 表名(字段1,字段2,字段3,...,字段n)
values
(值1,值2,值3,...,值n),
(值1,值2,值3,...,值n),
(值1,值2,值3,...,值n)
;
update 表名 set 字段1=值1,字段2=值2,...字段n=值n [where 条件];
update 表1,表2,...表n set 表1.字段1=表达式1,表n.字段n=表达式n [where 条件];
注:多表更新更多的用在根据一个表的字段来动态的更新另外一个表的字段
简单实例:
update t1,t2 set t1.age=2000,t2.age=3000 where t1.id=1 and t2.id=1;
delete from 表名 [where 条件];
delete 表1,表2,...表n from 表1,表2,...表n [where 条件];
不管是单表还是多表,不加where条件将会把表中的所有记录删除,所以操作时一定要小心。
select * from 表名;
select 字段名 from 表名;
SELECT distinct 字段1,字段2 FROM 表名;
只要 字段名1、字段名2 任何一个字段有不同就会被选择
一般使用distinct,只筛选一个字段( select distinct 字段名 employee; )
注:条件字段比较符号:
=,<,>,>=,<=,!=等比较运算符
多个条件之间可以使用or and等
where 后面接条件
select * from 表名 where 条件
asc:由低到高,也是默认值
select * from employee order by salary asc;
desc:由高到底
select * from employee order by salary desc;
多个字段排序
select * from employee order by salary desc, id desc;
在语句的最后面 加上 limit 数字1,数字2 来进行查询数量的限制。
limit 数字1,数字2 数字1代表从第几条记录开启取(是从0开始的),数字2代表取几条
//查询employee数据路salary列降序排列后的第一条数据
select * from employee order by salary desc limit 1;
//查询employee数据路salary列降序排列后的第二条数据
select * from employee order by salary desc limit 2;
//查询employee数据路salary列降序排列后,第三行数据开始取两行数据
select * from employee order by salary desc limit 3,2;select sum(字段名) from 表名;
select count( * 或字段名) from 表名;
select max(字段名) from 表名;
select min(字段名) from 表名;
select department,sum(salary) from employee group by department;
select sum(salary) from employee group by department with rollup;
select sum(salary) from employee group by department having sum(salary);
having是对聚合后的结果进行条件过滤,
where是在聚合前就对记录进行过滤,应该尽可能的对记录进行先过滤
select sum(salary) from employee group by department having sum(salary)>1000;
在一起使用:select sum(id),max(id),min(id),count(*) from 表名;
需求:显示多个表中的字段的时候即可使用表连接
内连接:选取两张表中相互匹配的记录
外连接:不仅仅选取两张相互匹配的记录,并且会选出其他不匹配的记录
内连接:
select * from 表1名,表2名,……where[匹配的条件比如 表1.字段=表2.字段];
select 表.字段,.... from 表1名,表2名,... where [匹配的条件比如 表1.字段=表2.字段];
select 语句可以给字段起别名!直接写在需要查询显示的字段的后面就,给表起别名
//内连接:查询employee和employlee两张表中相互匹配的数据
select * from employee,employee_record where employee.id=employee_record.eid;
//内连接:查询employee和employlee两张表中相互匹配数据中的id、name、record列
select employee.id,employee.name,employee_record.record from employee,employee_record where employee.id=employee_record.eid;
//给字段起别名
select employee.id a,employee_record.id b,employee.name c from employee,employee_record where employee.id=employee_record.id;
//给表起别名
select * from employee e,employee_record er where e.id=er.id;外连接
1)左连接
概念:包含左边表中的所有记录(包括右表中没有和它匹配的记录)
select ename,deptname from emp left join dept on emp.deptno=dept.deptno;
//左连接:left join为轴,左边是左表,右边是右表,
//查询左边表中的所有记录
select* from employee left join employee_record on employyee.id=employee_record.id;
2)右连接
概念:包含右边表中的所有记录(包括左表中没有和它匹配的记录)
注意:左连接和右连接是可以相互转换的
//右连接
//左连接:right join为轴,左边是右表,左边是右表,
//查询右边表中的所有记录
select* from employee right join employee_record on employyee.id=employee_record.id;
需求:一个查询需要另外一个查询的结果参与的时候用于子查询的关键字:
语法:select * from employee where id in(select eid from employee_late);
in 在..里面
注意点 in后面的子语句必须只返回一个字段
若查询结果唯一(只有一条)可以使用=代替in
语法:select语句 where exists(select 语句);
exists:后面那个子语句有没有查询出记录来,如果查询出记录来返回true,否则就是false,并且查询出来的记录的具体的值是NULL也是没有关系,也是返回true.
select * from employee where exists(select * from employee_late where employee_late.eid=emplooyee.id;)
1)select * from emp where deptno in(select deptno from dept);
2)若查询结果唯一可以使用=代替in
select * from emp where deptno=(select deptno from dept limit 1);
我们常常会碰到需要将两个表或者多个表的数据按照一定的查询条件查询出来后,将结果合并到一起显示这是就需要用到记录联合
多个select 语句用UNION或者UNION ALL隔开即可实现
区别: 前者 会将多个查询结果合并后并且进行去除重复后返回
后者 则直接合并并不去除重复
联合的条件:查询的列个数要相等
seclect id,name,salary from employee union select * from employee_late;MySQL提供了一些运算符号供我们在SQL语句中使用,比如我们需要对SQL语句中的某个值,或者某个字段做运算操作的时候,就可以使用这些运算。
+ | 加法 |
- | 减法 |
* | 乘法 |
/,DIV | 除法(返回商) |
%,MOD | 除法(返回余数) |
= | 等于 |
<>或!= | 不等于 |
<=> | 可以用于NULL值的比较 |
< | 小于 |
<= | 小于等于 |
> | 等于 |
>= | 大于等于 |
BETWEEN | 存在知道范围内 |
IN | 存在于指定集合 |
IS NULL | 为NULL |
IS NOT NULL | 不为NULL |
LIKE | 通配符匹配 |
REGEXP或RLIKE | 正则表达式匹配 |
NOT或! | 非 |
AND或&& | 与 |
OR或| | | 或 |
XOR | 异或 |
CONCAT(S1,S2,...Sn) | 连接S1,S2,...Sn为一个字符串 |
INSERT(str,x,y,instr) | 将字符串str从第x位置开始,y个字符长的字符串换位字符串instr |
LOWER(str) | 将字符串str中所有字符变为小写 |
UPPER(str) | 将字符串str中所有字符变为大写 |
LEFT(str,x) | 返回字符串str最右边的x个字符 |
RIGHT(str,x) | 返回字符串str最右边的x个字符 |
LPAD(str,n,pad) | 用字符串pad对str最左边进行填充,直到长度为n个字符长度 |
RPAD(str,n,pad) | 用字符串pad对str最右边进行填充,直到长度为n个字符长度 |
LTRIM(str) | 去掉字符串str左侧的空格 |
RTRIM(str) | 去掉字符串str行尾的空格 |
REPEAT(str,x) | 返回str重复x次的结果 |
REPLACE(str,a,b) | 用字符串b替换字符串str中所有出现的字符串a |
STRCMP(s1,s2) | 比较字符串s1和s2 |
TRIM(str) | 去掉字符串行尾和行头的空格 |
SUBSTRING(str,x,y) | 返回从字符串str x位置起y个字符长度的字符串 |
LENGTH(str) | 返回字符串长度 |
ABS(x) | 返回x的绝对值 |
CEIL(x) | 返回大于x的最小整数值 |
FLOOR(x) | 返回小于x的最大整数值 |
MOD(x,y) | 返回x/y的模 |
RAND() | 返回0-1内的随机值 |
ROUND(x,y) | 返回参数x的四舍五入的有y位小数的值 |
CURDATE( ) | 返回当前日期 |
CURTIME( ) | 返回当前时间 |
NOW() | 返回当前的日期和时间 |
UNIX_TIMESTAMP(date) | U返回日期date的UNIX时间戳 |
FROM_UNIXTIME() | 返回UNIX时间戳的日期值 |
WEEK(date) | 返回日期date为一年中的第几周 |
YEAR(date) | 返回日期date的年份 |
HOUR(time) | 返回time的小时值 |
IF(value,t,f) | 如果value是真,返回t,否则返回f |
IFNULL(value1,value2) | 如果value1不为空,返回value1,否则返回default |
CASE WHEN [value1] THEN [result1]...ELSE[default]END | 如果value1是真,返回result1,否则返回default |
CASE [expr] WHEN [value1] THEN[result1]...ELSE[default]END | 如果expr等于value1,返回result1,否则返回default |
DATABASE() | 返回当前数据库名 |
VERSION() | 返回当前数据库版本 |
USER() | 返回当前登录用户名 |
INET_ATON(IP) | 返回IP地址的数字表示 |
INET_NTOA(num) | 返回数字代表的IP地址 |
PASSWORD(str) | 返回字符串str的加密版本 |
MD5() | 返回字符串str的MD5值 |
show character set;
或者查看information_schema.character_sets,也可以显示所有的字符集和该字符集默认的校队规则
_ci(忽略大小写)、
_cs(大小写敏感)或者
_bin(二元,即比较是基于字符编码的值而与language无关)结束。
show collation like '字符集前缀%';
(1)在配置文件中设置
[mysqld]
character-set-server=utf8
(2)或者在启动项中指定
mysqld --character-set-server=utf8
(3)或在编译的时候指定
CREATE DATABASE 数据库名字
[[DEFAULT] CHARACTER SET 字符集名字]
[[DEFAULT] COLLATE collation_name]
查看当前数据库的字符集和校对规则:
show variables like 'character_set_database';
show variables like 'collation_database';
ALTER DATABASE db_name
[[DEFAULT] CHARACTER SET charset_name]
[[DEFAULT] COLLATE collation_name]
CREATE TABLE tbl_name (column_list)
[DEFAULT CHARACTER SET charset_name [COLLATE collation_name]]
ALTER TABLE tbl_name
[DEFAULT CHARACTER SET charset_name] [COLLATE collation_name]
遇到这种情况概率比较小,这只是MySQL提供给我们一个灵活设置的手段
过程中要设置正确,诚实守信,这样子如果全部设置正常,服务器端会自动的去按照你设置的字符集转换,但是也要避免想换转换的过程,最好都设置成一样的编码!
连接字符集设置:客户端和服务器之间交互的字符集
1)character_set_client:客户端来源数据使用的字符集
2)character_set_connection:连接层字符集
3)character_set_results:返回结果字符集
1) MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;
2) 进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,内部操作字符集的确定方法如下:
1>使用每个数据字段设定的字符集;
2>若上述值不存在,则使用对应数据表设定的字符集;
3>若上述值不存在,则使用对应数据库设定的字符集;
4>若上述值不存在,则使用服务器设定的字符集。
3) 将操作结果从内部操作字符集转换为character_set_results。
这3个参数设定的字符集应该相同,并且客户端使用的字符集确实是参数character_set_client的值,才可以确保用户的数据可以正确的返回且输出。
查看当前设置:show variables like 'character_set%';
修改:
set names 字符集,可以同时修改3个参数的值,对本次有效
也可以在配置文件中设置:
[mysql]
default-character-set=字符集
修改CMD命令行字符集:
chcp 65001 #换成utf-8代码页(设置为utf-8之后最好手动修改显示字体 )
chcp 936 #换成默认的gbk
客户端使用字符,连接层使用的字符集,内部使用的字符集,返回使用的字符集,最好都设置层一样的,并且客户端使用的字符集确实是character_set_client参数的值,这样就绝对不会出现问题!
$mysqli_connect=@mysqli_connect($host, $user, $password,$database,$port);
举例:
$link=@mysqli_connect('localhost','root','密码','',3306);int mysqli_connect_errno ();//返回最后一次连接调用的错误代码
string mysqli_connect_error ();//返回一个字符串描述的最后一次连接调用的错误代码
举例:
if(mysqli_connect_error()){
exit(mysqli_connect_error());
}bool mysqli_set_charset ( mysqli $link , string $charset );
举例:
mysqli_set_charst($link,'utf8');bool mysqli_select_db ( mysqli $link , string $dbname);
举例:
mysqli_select_db ($link,'d2');bool mysqli_close ( mysqli $link );
举例:
mysqli_close($link);相当于是从本地取数据;而MYSQLI_USE_RESULT方式下,mysqli_fetch_array()每次都要向server请求结果行。
MYSQLI_USE_RESULT:执行SQL的时候并没有从server将结果集取回
$query='insert into 表名(info) values("孙胜利,私房库,sifangku.com")';
//对数据库执行一条SQL语句,第三个参数决定了取具体结果的方式,MYSQL_USE_RESULT,MYSQL_STORE_RESULT
$query='select * from 表名';
$result=mysqli_query($link,$query,MYSQL_USE_RESULT);
var_dump(mysqli_fetch_row($result));也可以使用本函数对数据库执行一条SQL语句,返回结果为布尔值,不返回结果集。
如果想获取结果集可以使用mysqli_store_result()获取结果集对象.
int mysqli_errno ( mysqli $link );
string mysqli_error ( mysqli $link );
mixed mysqli_fetch_row ( mysqli_result $result );
重复使用以获取下一条记录的数据
array mysqli_fetch_assoc ( mysqli_result $result );
重复使用以获取下一条记录的数据
mixed mysqli_fetch_array ( mysqli_result $result [, int $resulttype = MYSQLI_BOTH ] );
重复使用以获取下一条记录的数据
mixed mysqli_fetch_all ( mysqli_result $result [, int $resulttype = MYSQLI_NUM ] );
object mysqli_fetch_field ( mysqli_result $result );
array mysqli_fetch_fields ( mysqli_result $result );
int mysqli_num_rows ( mysqli_result $result );
注意:如果使用MYSQLI_USE_RESULT模式则必须在获取完所有的结果才可使用该函数。
返回的结果集在数据量很大的时候需要很多的内存支持,所以在操作完结果集的时候有必要立刻释放与一个结果集相关的内存, 释放之后,结果集就不可用了
void mysqli_free_result ( mysqli_result $result );
int mysqli_affected_rows ( mysqli $link );
mixed mysqli_insert_id ( mysqli $link );
string mysqli_real_escape_string ( mysqli $link , string $escapestr );
bool mysqli_multi_query ( mysqli $link , string $query );
mysqli_stmt mysqli_prepare ( mysqli $link , string $query );
bool mysqli_stmt_bind_param ( mysqli_stmt $stmt , string $types , mixed &$var1 [, mixed &$... ] );
参数string $types说明:表示后面多个可选参数变量的数据类型,一一对应.
i:int类型
d:double或者float类型
s:字符串类型
b:二进制数据类型(BLOB、二进制字符串)
bool mysqli_stmt_execute ( mysqli_stmt $stmt );
上述三步骤举例
$query='insert into t1(id,info,content,filed1) values(?,?,?,?)';
//准备要执行的SQL语句
$stmt=mysqli_prepare($link, $query);
//为?绑定变量
mysqli_stmt_bind_param($stmt,'issd',$val1,$val2,$val3,$val4);
$val1=1;
$val2='第五代青蛙';
$val3='的武器大全我带我去';
$val4=60.5;
//执行准备好的SQL语句
var_dump(mysqli_stmt_execute($stmt));
如果是select之类的语句需要具体的结果;bool mysqli_stmt_bind_result ( mysqli_stmt $stmt , mixed &$var1 [, mixed &$... ] );
bool mysqli_stmt_fetch ( mysqli_stmt $stmt );
mysqli_result mysqli_stmt_result_metadata ( mysqli_stmt $stmt );
①mysqli_fetch_field();
②mysqli_fetch_fields();
bool mysqli_stmt_store_result ( mysqli_stmt $stmt );
取回之后可以使用int mysqli_stmt_num_rows ( mysqli_stmt $stmt );返回语句结果集中的行数
void mysqli_stmt_free_result ( mysqli_stmt $stmt );
bool mysqli_stmt_close ( mysqli_stmt $stmt );
面向对象关键字:基于面向对象开发时,所用到的一些关键字,用来表明不同的结构或类型。
类:class,是定义面向对象主体的外层结构,用来包裹主体的数据和功能(函数)。类是一类具有共性事务的代表,代表是事务的共性。
对象:object,是某类事务的具体代表,也是实际数据和功能操作的具体单元,也被称之为实例。
实例化:new,从一个抽象概念得到一个符合抽象概念的具体实例的过程。
类成员:member,指类class结构中的所有内容,类成员里有三种。
方法:method,本质是在类class结构中创建的函数,也称之为成员方法或成员函数
属性:property,本质是在类class结构中创建的变量,也称之为成员变量
类常量:const,本质是在类class结构中创建的常量。
类:根据对象分析后得到的一种通用结构(分类)
权限修饰符 class 类名[可选属性]{
//…………
}
/*
权限修饰符是可选项,
常见的修饰符包括 public、private 和 protected
创建类时,可以省略权限修饰符,
默认为public
*/
类名的要求:
以字母或下划线开头
后面跟着若干字母,数字或下划线;new 类名;
new 类名(); #使用较多$object = new 类名();class Nothing{
}//实例化,并将产生的对象保存在变量中
$n = new Nothing();
//打印对象
var_dump($n);
//打印结果分析
object(Nothing)#1(0){}
object:对象
(Nothing):所属类名
//对象编号,与类无关,是整个脚本中对象的序号,从1开始
(0):成员变量(属性)个数
{ }:具体成员变量信息(键值对)//直接打印类名
var_dump(Nothing); #错误,提示未定义 的常量#有效类名
class My1{}
class My_1{}
class _My{}
#无效类名
class 1My{}
class 1_my{}
class MyClass{}类是对象的模板,对象是类的实例。

成员变量(属性):给对象存储数据的变量
成员函数(方法):给对象调用解决问题的函数
类常量:属于类内部的常量,使用const关键字定义
class 类名{
#类常量(可以多个)
const 产量名 = 值;
#属性(可以多个)
public $属性名 [ = 值 ];#可以赋值也可以不赋值,只声明
#方法(可以有多个)
[public] function 方法名([形参列表]){
#方法体(返回值)
$a=10;
}
}#实例化
$object = new 类名();
#属性访问
$object -> 属性名; #此时不带属性本身的¥符号(前面保存对象的变量带¥符号,object->属性名是整体)
#方法访问
$object -> 方法名([实参列表]);(1)声明类结构
(2)明确类产生的对象是否需要有数据的存储:确定属性
(3)明确类产生的对象是否需要函数实现功能:确定方法
(4)明确类是否需要定义常量:确定类常量
(5)对象实例化
(6)类成员访问(属性和方法)
#定义卖家类:卖家有姓名,有钱
class Buyer{
#属性声明
$name; #错误,类内部属性必须使用访问修饰限定符
public $name; #正确:没有赋值
public $money = 0; #正确:有赋值
#方法声明
function display(){
echo __CLASS__; #魔术常量,输出类名
}
#类常量声明
conset BIG_NAME = 'BUYER';
}#实例化对象
$b = new Buyer();
#访问属性
echo $b -> money;
#修改属性
$b -> money = 100;
#删除属性
unset($b -> name );
#新增属性
$b->age = 20;
#访问方法
$b->display(); //调用方法(1)删除属性和心中属性通常使用较少,更多的属性操作时访问和修改
(2)类常量不是有对象来进行访问
(3)属性和方法的使用都必须确保类中已经定义(属性可以新增)
class Buyer{
echo __CLASS__; #错误
define('PI',3.14); #错误
if(true){
echo 'hello world'; #错误
}
}
/*
以上都不可行,但是可以在function内
*/访问修饰限定符:用在属性或者方法前的修饰关键字,是用来控制属性或方法的访问位置。
public | 公有,可以在任何地方被访问 |
private | 私有的类,成员只能被其定义所在的类访问 |
protected | 受保护的类,成员只可以被其子类和父类访问 |
readyonly | 声明属性,防止初始化后修改属性 |
static | 声明类属性,就可以不实例化直接访问 |
(1)声明类结构
(2)确定类成员
(3)确定类成员的访问位置限定,使用对应访问修饰限定符
(4)只能在对于位置访问被修饰的成员
class Saler{
#属性
public $count = 100; //公有的可在内部/外部访问Saler
#方法
public function getCount(){
echo __METHOD__; #魔术常量,显示当前方法名(包含类名)
}
function setCount(){
echo __METHOD__;
}
}
//上述均为公有
#实例化对象
$s = new Saler(); //
#访问(类外)
echo $s->count; //在外部访问
$s->getCount(); //在外部调用
$s->setCount(); //在外部设置class Buyer{
#属性
protected $money = 10; //money是受保护的
private $account = '622600000000001'; //account是私有的
#方法
protected function getMoney(){ //方法getMoney是受保护的
echo __METHOD__;
}
private function getAccount(){ //方法getAccount是私有的
echo __METHOD__;
}
}
#实例化
$b=new Buyer();
echo $b->money; #错误:当前属于类外部,不能访问
echo $b->account; #错误:当前属于类外部,不能访问
$b->getMoney(); #错误:当前属于类外部,不能访问
$b->getAccount(); #错误:当前属于类外部,不能访问
三种访问修饰限定符public、protected和private,访问权限以此降低(类对成员控制权限依次增加)
访问修饰限定符限定的是成员到底在哪里能被访问,私有和受保护都只能在类部访问,公有可
以在任何地方访问(但都必须是对象去访问)
属性必须写清楚访问修饰限定符,方法若不写,则默认为upublic
内部对象:$this,方法内部内置的一个对象,会自动只想来调用方法的对象
1)可以访问任意访问修饰限定符修饰的成员
2)私有成员都是通过公有方法来实现访问(公有方法可以在类外部访问)
(1)声明类结构
(2)明确私有成员
(3)私有成员需要在某种情况下被访问:增加方法,在方法里使用$his访问
class Saler{
#属性
public $count = 100; //属性公有
protected $discount = 0.8; //属性受保护等同于私有
private $money = 100; //属性是私有
public function getAll(){ //方法是公有
echo $count,$discount,$money; #全部错误:提示未定义的变量
}
}
$s = new Saler();
$s->getAll();注意:方法本质是定义在类内部的函数,因此受之于作用域的问题,在方法内部访问的变量系统认定为局部变量(必须内部定义或参数传入),否则就会提示未定义
class Saler{
#属性
public $count = 100;
protected $discount = 0.8;
private $money = 100;
public function getAll(){
#需要获取到对象的名字:因为方法本身就是函数,访问外部全局变量可以通过global引入实现
global $s;
echo $s->count,$s->discount,$s->money; #正确输入
}
}
$s = new Saler();
$s->getAll();注意:上述代码规定死了以后对象只能是$s,不能有其他对象或其他命名,所以非常不友好
class Saler{
#属性
public $count = 100;
protected $discount = 0.8;
private $money = 100;
public function getALl(){
var_dump($this);
echo $this->count,$this->discount,$this->money; #正确输出
}
}
$s = new Saler();
$s->getAll();注意:$this代表的是对象,而$this所在环境为类内部的方法内部,所以$this对象是在类内部访问,因此可以访问所有的属性和方法,不受访问修饰限定符限制
$this的本质是函数内部的一个局部变量,只是系统自动对其进行赋值,而且一定是调用方法的对象本身
开发规范:开发者约定俗称的开发设计方式
1)属性是类对于同类事物所抽离出来的共性数据,本身在类结构中没有价值,是当具体对象产生之后,属于对象本身的
2)进行类中定义属性的时候,通常不会对属性进行初始化,除非属性本身的值也具有共性
3)属性如果没有初始化数据,那么在产生对象后应该对属性完成初始化(有的属性是在操作过程中被初始化)
1)设定好的类成员本身不会被外部用到,那么应该使用private或protected
2)设定好的类成员一定会给外部访问,使用public
3)属性通常private居多,如果需要外部访问属性,通常会定义相关方法来实现小户型的查看和修改,因为可以在方法内对数据逻辑进行代码控制,安全
4)尽可能增加类对成员的控制(尽可能多使用private,少使用public)
class Saler{
#属性
public $count;
#某个卖家拥有的商品数量,每位具体卖家对象拥有的不可能一样,所以没必要初始化
protected $discount;
#某个卖家针对销售的折扣,同样没有统一的价值
private $money = 0;
#某个卖家的账户余额,任何一位卖家一开始做生意的时候账户余额都为0,所以可以初始化
#业务初始化属性
public function setDiscount($discount = 1){
#可以进行逻辑控制
$this->discount = $discount;
}
}
#实例化对象,初始化属性
$s = neew Saler();
$s->count = 100;
#打折促销:业务初始化
$s->setDiscount(0.8);class Saler{
#属性
public $count;
private $money = 0;
#增加方法操作私有属性money
public function getMoney(){
return $this->money;
}
public function setMoney($money){
#可以对逻辑进行修改,对数据进行安全判断,保证数据的安全性
$this->money = $monry;
#$this->money是属性,$money是外部传入的参数,二者同名但是性质完全不同
}
}构造方法:__construct( ),是一种类结构特有的特殊方法,有了构造方法的类在实例话对象之后,对象就会自动调用。
1)对象实例化之后会自动调用
2)构造方法通常是为了实现对象所需要资源的初始化(属性、资源)
1)受访问修饰限定符控制
2)对象可以选择调用(一般不会)
1)属性初始化
2)资源初始化
3)其他内置方法调用
class Saler{
#构造方法
public function __construct(){
echo __CLASS__;
}
}#实例化
new Saler(); #输出Salerclass Saler{
#属性
public $count;
private $money;
#构造方法:初始化属性
public function __construct(){
$this->count = 100;
$this->money = 100;
}
}class Saler{
#属性
public $count;
public $money;
#构造方法
public function __construct($count,$money){ //传参count,money
echo __CLASS__;
#初始化
$this->count = $count; //
$this->money = $money;
}
}
#实例化
new Saler(100,100);
class Saler{
#属性
public $count;
public $money;
#构造方法
public function __construct($count,$money){ //传参count,money
echo __CLASS__;
#初始化
$this->count = $count; //
$this->money = $money;
}
}
#实例化现象
$s1 = new Saler(100,100);
$s2 = new Saler(1000,1000);
$s3 = new Saler; #错误:因为此时类有构造方法且要求传入参数,所以必须使用()并传入数据
var_dump($s1,$s2);注意:之前所说的new类名和new类名( )没有区别是因为没有构造方法,或者构造方法没有参数限定,一旦构造方法有了参数,那么new类名就不能直接使用了。
class Saler{
#属性
public $count;
private $money;
#构造方法:初始化属性
public function __construct($count,$money){
$this->count = $count;
$this->money = $money;
}
}
#实例化
$s = new Saler(100,100); #系统在new Saler(100,100)好之后,会自动调用依次
$s->__construct(1000,1000); #允许手动调用
析构方法:__destruct( ),也是一种类结构中魔术方法,对象在被销毁时会自动调用
1)对象无变量指向(变量指向其他数据)
2)对象被主动销毁(unset销毁对象变量)
3)脚本执行结束(自动释放资源)
(1)定义类结构
(2)确定需要在对象销毁时释放资源
(3)使用析构方法释放资源
class Saler{
#析构方法
public function __destruct(){
echo __FUNCTION__;
}
}#实例化对象
$s = new Saler();
#对象变量指向其他数据
$s = 1;
#主动销毁对象变量
unset($s);
#脚本执行结束自动释放#换析构方法实现代码
$s = new Saler();
#主动调用析构方法
$s->__destruct(); #此时对象被销毁注意:
(1)析构方法是一种对象销毁时自动调用的方法
(2)析构方法用来对象销毁自身所占用的资源
(3)PHP中脚本执行结束,系统会自动回收所有资源,因此一般PHP中很少使用析构方法
对象传值:将保存对象的变量赋值给另外一个变量
在PHP中,对象的传值是引用传递的:即一个对象变量赋值给另外一个变量,两个变量指向同一个对象的内存地址,即只有一个对象。
(1)定义类结构
(2)实例化产生对象,保存在变量中
(3)将保存对象的变量赋值给另外一个变量
class Saler{}
$s1 = new Saler();
$s2 = $s1;#证明
var_dump($s1,$s2); #同一个对象
$s1->name = 'Saler'; #更改一个变量所存对象的属性
echo $s2->name; #输出Saler注意:
(1)对象传值方式是引用传值,不论对象如何被赋值给其他变量,始终只有一个对象
范围解析操作符:由两个冒号组成“ :: ”,是专门用于类实现类成员操作的,可以实现类直接访问类成员
类名::类成员$对象名::类成员(1)定义类结构
(2)确定成员需要由类进行管理:类常量
(3)在需要访问类常量的时候使用范围解析操作符访问
class Saler{
#类常量
const PI = 3.14;
}
$s1 = new Saler();
echo $s->PI; #无法访问 错误:$s1->PI最终转换的访问方式为:$PI ,这个在类中并不存在#类+范围解析操作符访问类常量
echo Saler::PI; #输出3.14$s = new Saler();
echo $s::PI; #输出3.14 #范围解析操作符兼容对象:找到对象所属类最终进行访问注意:以上方式能访问,但不建议使用(以上方式也能看出,成员谁来访问,关键用什么符号:①使用范围解析操作符::就是类访问;②使用对象操作符号->就是对象访问)
类常量是固定的,而对象的属性是不同对象而不太的,成员方法简单的理解也是为属性本身进行加工的。因此有一些东西是专属于类的,而有部分内容是专门为对象提供的,所以就会有不同的成员拥有不同的访问方式
静态成员:使用static关键字修饰的类成员,表示该成员属于类访问
1)静态属性
2)静态方法
clas Saler{
#属性
public $money = 0;
public static $count = 0; #静态属性
}
#静态成员可以直接使用类访问,而不需要先实例化对象 //静态属性
echo Saler::$count;class Saler{
#方法
public static function showClass(){
echo __CLASS__;
}
}
#类直接访问 //静态方法
Saler::showClass();class Saler{
#属性
private static $count = 0; #私有,不允许外部直接访问
#方法
public static function showClass(){
echo Saler::$count;
}
}
#类直接访问
Saler::showClass();#对象访问静态方法
$s = new Saler();
echo $s->money;
//echo $s->count; #对象不能访问静态属性
$s->showClass(); //输出0class Saler{
public function testStatic(){
echo __FUNCTION__;
}
}
#类访问普通成员方法
Saler::testStatic(); //输出testStatic,但是报错,当前访问的不是静态方法
class Saler{
public function testStaticThis(){
var_dump($this); //致命错误:$this放到了不该放的位置
}
}(1)为了保障类能直接访问数据和操作数据,可以在属性和方法前增加static关键字变成静态属性和静态方法
(2)类通过类名+范围解析操作符+静态成员的方式进行访问
(3)静态成员也受访问修饰限定符的限定,访问权限与普通属性和方法的限制一样
(4)对象可以无条件访问静态方法,而类只能访问不带$this的普通方法(不建议)
(5)静态成员是给类访问的,非静态成员是给对象访问的
1)静态属性和方法(静态和非静态)都是保存在类结构中(代码段)
2)普通属性保存在对象生成的对象空间里(堆)
(6)静态成员的访问效率比非静态成员高,因此有种说法是能用静态的时候就不用非静态
self关键字:在类的内部(方法里面)使用,代替类名的写法
(1)self 如同 $this 代表内部对象一样,能够在方法内部代替当前类名
(2)能够保障用户方便修改类名字
(3)self 关键字是代替类名,所以需要配合范围解析操作符::
(1)定义类结构
(2)方法内部需要使用类名来进行成员访问(类常量、静态成员)
(3)使用 self 关键字代替类名
::一起使用的class Saler{
#静态属性
private static $count = 0; //私有,不允许外部直接访问
#静态方法
public static function showClass(){
echo Saler::$count;
echo self::$count; //代替类名
}
}
Saler::showClass(); //输出0
//静态方法配合静态属性可以不需要对象class Saler{
#属性
private static $count = 0; //私有,不允许外部直接访问
private function __construct(){} //私有,不允许外部实例化(因为对象不能外部调用)
#方法
public static function getInstance(){
return new Saler(); //使用类名实例化
#可以使用self 代替类名进行内部实例化
return new self(); //使用self关键字实例化
}
}
$s = Saler::getInstance; 注意:
(1)self 是一种在类内部用来代替类名的关键词
(2)self 可以用来在类内部访问静态成员
(3)self 也可以在类内部用来实例化对象