PHP基础入门-程序员宅基地

技术标签: php  服务器  mysql  

1.2 PHP简介

1.2.1 概述

PHP是Hypertext Preprocessor的缩写,(超文本预处理器)是一种在服务器端运行的开源的脚本语言。

LAMP组合(Linux,Apache,MySQL,PHP),这四个产品都是公开源代码的产品

1559265599338

php是一门语言,用来做业务逻辑
apache为PHP提供了运行环境
linux为Apache的运行提供了平台
mysql数据库用来存储数据

多学一招:什么是wamp组合

windows+apche+mysql+php
1.2.2 五个基本概念

1、静态页面和动态页面

静态页面:服务器不执行的页面
动态页面:服务器执行的页面

问题:动态网站中是否可以存放静态页面

答:可以

2、客户端和服务器端

浏览者这段是客户端
服务器端:给浏览者提供服务

1559266315114

3、端口和端口号 端口号的范围: 0-65535

1559266671894

4、BS架构和CS架构

BS:通过浏览器去访问服务器

b:browser(浏览器)
s:sever(服务器)
优点:
1、只要有浏览器就可以访问
2、开发低
缺点:
2、开发的代码都放在服务器上    胖服务器-瘦客户端

所有的web都是BS架构的

CS:通过客户端软件去访问服务器

c:client(客户端)
s:server(服务器)
优点:
1、可以开发客户端和服务器端,这时候就可以实现负载的均衡
缺点:
1、必须要安装一个软件才能去访问
2、开发成本高

例如:QQ、炒股软件

5、前台和后台

前台:浏览器看到的界面
后台:管理员看到的界面
1.2.3 PHP的优点
  1. 跨平台,既能在windows上运行,也能在linux上运行
  2. 源码开放:不会涉及到版权问题
  3. 语法简单:PHP入门简单
  4. 运行在服务器端,只要在服务器部署环境就可以了。

1.3 Web介绍

1.3.1 web时代的变迁

从互联网开始崛起到现在,经历了从web1.0、2.0到web3.0的过程

Web1.0(信息共享)的主要特点在于用户单纯的获取信息
Web2.0(信息共建)更注重用户的交互作用,用户既是网站内容的浏览者,也是网站内容的制造者。
Web3.0(信息传承)通过第三方信息平台对多家网站的信息进行整合,用户在互联网上拥有自己的数据,并能在不同网站上使用

举例:

Web1.0:来到一个餐馆,老板给你上了一盘番茄炒蛋;
Web2.0:来到一个餐馆,你跟老板主动点了一份番茄炒蛋;
Web3.0:来到一个餐馆,老板见到你就问,老规矩,还要番茄炒蛋?
1.3.2 Web服务原理

静态网站原理(浏览器-服务器)

动态网站原理(浏览器-服务器-数据库)

智能网站原理(浏览器-服务器【分析推荐】-数据库)

1.4 搭建Web服务器

1.4.1 安装phpstudy

直接解压即可

1559269647246

1.4.2 目录结构

1559269842937

启动服务

1559269958106

1.4.3 访问服务器

在www目录下创建demo.php页面

<?php
   phpinfo();

访问服务器

访问规则:http://服务器ip地址/php页面
比如:
http://localhost/demo.php
http://127.0.0.1/demo.php

1559270241230

1.4.4 常用的命令

补充DOS命令

切换盘符	盘符+冒号
进入目录	cd 目录地址

Apache的命令

httpd -v   查看apache版本号   version
httpd -t   检测运行环境  test

1559270648665

PHP的命令

php -v  PHP版本号

1559270788210

1.4.5 互联网通讯原理

本质一台电脑访问另外一台电脑资源、寻址过程(IP地址、端口、域名、DNS)

在互联网上,IP地址是用来区分每台计算机的标识,但是IP记忆不友好,我们将IP地址取一个名字,一个IP对应一个名字,这个名字就称为域名。

访问过程:

1559271776966

步骤:

1、客户端输入域名(网址),在最近的机房做DNS解析(Domain Name Server),DNS解析就是将域名转化成IP地址

2、通过IP地址访问服务器

1.4.6 DNS解析

目标:ip地址访问服务器不方便,通过域名来访问。

1559273427400

hosts文件

1559273446652

测试

1559273470555

小结:

hosts文件用来做DNS解析

1.5 服务器配置

1.5.1 虚拟目录配置

1、更改虚拟目录

要更改虚拟目录的位置,需要到apache的配置文件中更改(conf/httpd.conf)

在phpstudy中,httpd.conf和vhost.conf都有配置虚拟目录的指令,并且两个配置文件中都有配置虚拟目录的指令,为了测试,我们注释掉vhost.conf的引入

1559302864933

更改虚拟目录

1559284320932

提醒:项目上线以后,不可以显示目录结构

权限的练习

例题一:

Order allow,deny
Allow from all
# 允许所有请求访问

例题二:

Order allow,deny
Allow from all
Deny from all
# 拒绝所有请求访问

练习三:

Order allow,deny
Deny from all
Allow from all
#  拒绝所有请求访问

练习四:

<Directory "C:/PHP/Apache/htdocs">
   Order deny, allow
   Allow from 192.168.101.50
   Deny from 192.168
</Directory>
# 拒绝192.168开头,但除去(192.168.101.50)的IP的访问

练习五:

<Directory "C:/PHP/Apache/htdocs">
    Order deny, allow
    Allow from 192.168.101.50
   Deny from all
</Directory>
# 只允许192.168.101.50访问

练习六:

<Directory "C:/PHP/Apache/htdocs">
   Order allow,deny
   Allow from 192.168
   Deny from 192.168.101.50
</Directory>
# 只允许192.168开头的,但要去除192.168.101.50 的IP访问

2、更改默认首页

在httpd.conf配置文件中

1559302972798

默认首页的查找顺序,从前往后。

3、更改监听端口

在httpd.conf配置文件中设置

通过Listen指令设置监听的端口

可以设置多个监听端口

1559286449920

访问:

http://域名:端口号/demo.php

1559286541343

补充:查看端口的占用情况

在命令行下使用 netstat -ano查看

1559286766399

在结果中查找字符串

1559287048517

1.5.3 虚拟主机配置

需求:

输入www.baidu.com	打开web1的网站
输入www.sina.com打开web2的网站

配置过程:

要配置虚拟主机,需要在httpd.conf中引入虚拟主机的培训文件(vhosts.conf)

1559287562047

vhosts.conf配置如下

<VirtualHost _default_:80>
  DocumentRoot "C:\web1"       #指定虚拟目录路径
  ServerName www.baidu.com     # 虚拟目录绑定的域名
  DirectoryIndex aa.php        # 默认首页
  <Directory "C:\web1">
    Options -Indexes -FollowSymLinks +ExecCGI
    AllowOverride All
    Order allow,deny
    Allow from all
    Require all granted
  </Directory>
</VirtualHost>


<VirtualHost _default_:80>
DocumentRoot "C:\web2"
 ServerName www.sina.com
 DirectoryIndex bb.php
  <Directory "C:\web2">
    Options -Indexes -FollowSymLinks +ExecCGI
    AllowOverride All
    Order allow,deny
    Allow from all
    Require all granted
  </Directory>
</VirtualHost>

在host文件中做dns解析

1559287727859

访问结果

1559288139327

1559288155844

补充:站点、虚拟目录、虚拟主机的区别

站点:站点就是一个文件夹,用来保存与网站有关的所有素材

虚拟目录:站点+权限

虚拟主机:虚拟目录+域名

1.6 PHP语法入门

1.6.1 PHP是编译型语言

编译语言和解释语言的区别在于是否保存最终的可执行程序。

1559289941751

PHP执行过程 1559290125048

1.6.2 PHP定界符

因为PHP是脚本语言,所以需要定界符

1、标准风格(推荐使用)

<?php

?>

例题

<?php
	echo 'i am a boy!';
?>

提醒,如果整个页面都是PHP代码,PHP结束符是可以省略的(推荐)

<?php
	echo 'i am a boy!';

2、短标记风格(默认情况下不支持,需要在php配置文件中开启支持段标记)

1559290933277

<?
?>

例题:

<?
	echo '锄禾日当午';
?>

小结:

httpd.conf是apache的配置文件

php.ini是php的配置文件

1.6.3 注释

单行注释: //和#

多行注释: /* */

1559291216221

1.6.4 PHP输出语句
echo:输出
print:输出,输出成功返回1
print_r():输出数组
var_dump():输出数据的详细信息,带有数据类型和数据长度

<?php
	var_dump('abc');	//string(3) "abc" 
?>

1.7 变量

变量的本质就是内存中的一段空间

1.7.1 变量的命名规则
  1. 变量必须以 开 头 , 开头, 符不是变量的一部分,仅表示后面的标识符是变量名。
  2. 除了$以外,以字母、下划线开头,后面跟着数字、字母、下划线
  3. 变量名区分大小写, a a 和 aa和 aaAa是两个空间

下列变量是否合法

$a		合法
$a1		合法
$1a		不合法
$_1a	合法

注意:PHP语句必须以分号结尾

<?php
	$a=10;
	$name='Tom';
?>
1.7.2 可变变量

变量名可以变,将变量名存储在另外一个变量中

例题

<?php
$a=10;
$b='a';
echo $$b;	//10

例题

<?php
	$name1='tom';
	$name2='berry';
	if(rand(1,10)%2){
     
		$name='name1';	//将变量名存储在$name中
	}else{
    
		$name='name2';
	}
	echo $$name;   

小结:

1、rand(1,10):获取1-10的随机整数

1.7.3 变量传递

变量的传递有值传递和地址传递(引用传递)

<?php
//值传递
$num1=10;	//将10付给$num1
$num2=$num1;	//将$num1的值付给$num2
$num2=20;		//更改$num2
echo $num1;		//10

1559294061120

//地址传递
$num1=10;		//将10付给$num1
$num2=&$num1;	//将$num1的地址付给$num2
$num2=20;		//更改$num2
echo $num1;		//20

1559294198689

小结:

1、参数的传递有两种,值传递和地址传递

2、&表示获取变量的地址

3、值传递中,一个变量变了,另一个变量没有影响,因为是两个空间

4、地址传递中,一个变量变了,另一个也变了,因为两个变量指向同一个空间

1.7.4 销毁变量

用unset()来销毁变量,销毁的是变量名,变量值由PHP垃圾回收机制销毁

<?php
$num1=10;
$num2=&$num1;
unset($num1);	//销毁的是变量名
echo $num2;		//10

没有变量引用的值是垃圾。

1.8 作业

phpstudy安装完毕后,有一个phpmyadmin的管理数据库软件,默认情况下,放在虚拟目录下,这样不合理,请重新配置虚拟主机访问phpmyadmin

输入phpmyadmin.com打开phpmyadmin管理软件

1.2 常量

在整个运行过程中,固定不变的值

1.2.1 定义常量

1、用define()函数定义常量

define(常量名,值,[是否区别大小写])  true表示不区分大小写,默认是false

常量名前没有$符
常量名推荐使用大写

例题:

<?php
define('NAME','tom');		//定义常量
define('PI',3.14,true);		//定义常量,不区分大小写
echo NAME,'<br>',Pi;
//true表示不区分大小写,默认是区分大小写的。

2、定义常量可以用特殊字符,但是在调用的时候必须用constant关键字调用

define('%-%','tom');
echo constant('%-%');		//通过constant获取特殊字符作为常量名的常量

3、判断常量是否定义,通过defined()判断常量是否已经定义

if(!defined('NAME')){
    	
	define('NAME','berry');
}
echo NAME;	//berry

4、还可以使用const关键字定义常量

const NAME='tom';
echo NAME;		//tom

小结:

1、定义常量有两种方式,define()和const

2、常量在整个运行过程中值保持不变,常量不能重新定义

3、使用constant获取特殊字符做的常量名的值

4、defined()用来判断常量是否被定义

1.2.2 预定义常量

PHP预先定义好的常量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KekuV6zj-1669803084213)(C:/Users/SUNJIANSONG/AppData/Roaming/Typora/typora-user-images/1559355891156.png)]

例题

echo PHP_VERSION,'<br>';		//PHP版本号
echo PHP_OS,'<br>';				//PHP操作系统
echo PHP_INT_MAX,'<br>';		//PHP中整型的最大值	
1.2.3 魔术常量

魔术常量它们的值随着它们在代码中的位置改变而改变

echo __LINE__,'<br>';		//获取当前行号
echo __FILE__,'<br>';		//文件的完整路径和文件名
echo __DIR__,'<br>';		//文件所在的目录

1.3 数据类型

数据类型有两种:强类型和弱类型

PHP是弱类型

1.3.1 基本类型(标量类型)

1、整型

存整数,PHP_INT_MAX获取整形最大值

PHP支持8、10、16机制的整数

<?php
$num1=10;		//十进制
$num2=010;		//八进制(数字前面加0)
$num3=0x10;		//十六进制(数字前面加0x)

echo $num1,'<br>';		//10
echo $num2,'<br>';		//8
echo $num3;				//16

进制转换

机制 缩写 单词
十进制 dec decimalist
二进制 bin binary
八进制 oct octonary
十六进制 hex hexdecimalist

例题

PHP提供了进制转换函数

echo decbin(123),'<br>';   //十进制转二进制
echo bindec(1111011),'<br>';	//二进制转十进制
echo dechex(123),'<br>';		//十进制转十六进制
echo hexdec('7b'),'<br>';		//十六进制转十进制
echo decoct(123);				//十进制转八进制

2、浮点型

浮点数在内存中保存的是近似值

浮点数不能参与比较

var_dump(0.9==(1-0.1));		//bool(true) 
echo '<br>';
var_dump(0.1==(1-0.9));		//bool(false) 

如果浮点数要比较,必须确定比较的位数

var_dump(0.9==(1-0.1));		//bool(true) 
echo '<br>';
var_dump(0.1==(1-0.9));		//bool(false) 
echo '<br>';
var_dump(bccomp(0.1,1-0.9,5));	//比较小数点后面5位   int(0)   0表示相等

提醒:如果一个整数超出了整形的范围,会自动的转成浮点型

3、布尔型

不能使用echo 和print输出布尔型,要使用var_dump()输出

$flag=false;
var_dump($flag);	//bool(false) 

4、字符串型

在PHP中单引号字符串和双引号字符串是有区别的

单引号字符串是真正的字符串

双引号字符串要解析字符串中的变量

例题

$name='tom';
echo '我的名字叫$name','<br>';	//我的名字叫$name
echo "我的名字叫$name",'<br>';	//我的名字叫tom

例题:{ }取变量值

$name='tom';
echo '$name是我的名字','<br>';	//$name是我的名字
echo "{
      $name}是我的名字",'<br>';	//{}表示获取变量的值(tom是我的名字)
echo "${name}是我的名字",'<br>';	//$和{只要挨着一起就可以(tom是我的名字)

输出特殊字符

echo '毛主席说:\'上课不要睡觉\'','<br>';	//转义字符   毛主席说:'上课不要睡觉'
echo '文件保存在c:\\';   //文件保存在c:\

字符串定界符

1、有<<<开头,后面跟的是标识符
2、字符串定界符的结束符必须顶格写,前面不能有任何的空白字符
3、字符串定界符分为两种,heredoc(双引号),nowdoc(单引号)

1559360839293

1.3.2 复合类型

1、数组

在PHP中数组有两种形式,索引数组和关联数组

索引数组:用整数做下标,默认从0开始,后面依次加一

关联数组:用字符串做下标,通过=>符号将下标和值关联起来

例题:数组的声明

<?php
//1、索引数组的声明
$stu=array('tom','berry','ketty');   //索引数组
print_r($stu);	//输出数组  Array ( [0] => tom [1] => berry [2] => ketty ) 
echo '<hr>';
echo $stu[0],'<br>';	//tom
echo $stu[1],'<br>';	//berry
echo $stu[2],'<hr>';	//ketty
------------------------------------------
//2、关联数组
$emp=array('name'=>'李白','sex'=>'男','age'=>22);
print_r($emp);	//Array ( [name] => 李白 [sex] => 男 [age] => 22 ) 
echo '<hr>';
echo $emp['name'],'<br>';	//李白
echo $emp['sex'],'<br>';	//男
echo $emp['age'];			//22

练习:写出数组的下标

$array=array(1=>'a','b','c','d');
print_r($array);   //Array ( [1] => a [2] => b [3] => c [4] => d ) 
echo '<br>';
--------------------------
$array=array('a',2=>'b','c',5=>'d');
print_r($array);  //Array ( [0] => a [2] => b [3] => c [5] => d ) 
echo '<br>';
----------------------------
$array=array('a','name'=>'b','c','sex'=>'d');
print_r($array); //Array ( [0] => a [name] => b [1] => c [sex] => d ) 
echo '<br>';
------------------------------
$array=array(1=>'a',1=>'b',1=>'c','d');
print_r($array);	//Array ( [1] => c [2] => d ) 

数组的下标只能是正整数和字符串

思考如下下标

$stu[true]='tom';		//转成1
$stu[false]='berry';	//转成0
$stu[12.9]='aa';		//转成12(取整数部分)
$stu[-10]='bb';			//负数可以做下标
$stu[-12.3]='cc';		//取负整数
$stu['10']='dd';		//字符串数字转成数字
$stu['']='ee';			//空字符串也可以做下标
$stu[null]='ff';		//转成空字符串做下标
print_r($stu);

短数组语法,可以直接通过中括号声明数组

$stu=['tom','berry','ketty'];
print_r($stu);  //Array ( [0] => tom [1] => berry [2] => ketty ) 

多学一招:在PHP7.1中可以支持数组的赋值

//例题,两个数交换
$num1=10;
$num2=20;
[$num1,$num2]=[$num2,$num1];
echo $num1,'<br>',$num2;

二维数组的声明

$stu=[
	['name'=>'tom','sex'=>'男','age'=>22],
	['name'=>'berry','sex'=>'女','age'=>23]
];
echo '<pre>';
print_r($stu);
//运行结果
Array
(
    [0] => Array
        (
            [name] => tom
            [sex] =>[age] => 22
        )

    [1] => Array
        (
            [name] => berry
            [sex] =>[age] => 23
        )

)

多学一招:字符串可以通过数组的方式去调用

echo 'abc'[0],'<br>';		//a  
echo 'abc'[-1],'<br>';		//c,从右边开始取第一个  7.1开始支持

小结:

1、数组在内存中一段连续的空间

2、如果要保存同一类型的多个数据就使用数组

2、对象

对象在后面专门讲解(面向对象编程)

1.3.3 特殊类型

1、资源

2、null

1559372246359

提醒:在PHP中 null和NULL是一样的,不区分大小写

1.3.4 类型转换

1、自动类型转换:当提供的类型和需要的类型不一致的时候会自动进行类型转换

$num=10;
if($num){
       //自动将数字转成布尔型
	echo 'aa';
}else{
    
	echo 'bb';
}
---------------------------------
echo '20'-10;	//自动的将字符串转成数字

2、强制类型转换

语法:(数据类型)数据

<?php
$num1='12';
var_dump($num1,(int)$num1,(float)$num1);   //string(2) "12" int(12) float(12) 

其他类型和布尔之间的转换

规则:0、空为假,非0非空为真

<?php
var_dump((bool)'abc');	echo '<br>';		//bool(true)  
var_dump((bool)'');		echo '<br>';		//bool(false) 
var_dump((bool)'0');	echo '<br>';		//bool(false) 
var_dump((bool)'0.0');	echo '<br>';		//bool(true) 
var_dump((bool)'00');	echo '<br>';		//bool(true) 
var_dump((bool)'false');	echo '<br>';	//bool(true) 
var_dump((bool)'null');	echo '<br>';		//bool(true) 
var_dump((bool)1);		echo '<br>';		//bool(true) 
var_dump((bool)0);		echo '<br>';		//bool(false) 
var_dump((bool)-10);		echo '<br>';	//bool(true) 
var_dump((bool)0.0);		echo '<br>';	//bool(false) 
var_dump((bool)array());	echo '<br>';	//bool(false) 
var_dump((bool)array(1));	echo '<br>';	//bool(true) 
var_dump((bool)array(false));	echo '<br>';//bool(true) 
var_dump((bool)null);	echo '<br>';			//bool(false) 

1.4 运算符

1.4.1 算术运算符
一元运算符 二元运算符
++ +
-
*
/
% (取模)

注意:在PHP中,算术运算符只能做数学运算。

<?php
echo '10'+'20','<br>';		//30
echo '10ab'+'20cd','<br>';	//30
echo 'ab10'+'cd20','<br>';	//0

++前置:先自增再运算

++后置:先运算再自增

练习

$num=10;
$num++;
echo $num;	//11
-------------------------
$num=10;
echo $num++;   //10
------------------------
$num=10;
echo ++$num;   //11

练习

<?php
$num=5;
echo (++$num)+(++$num)+(++$num);	//21
-------------------------
<?php
$num=5;
echo ($num++)+($num++)+($num++);	//18
1.4.2 关系运算符(比较运算符)
>
>=
<
<=
==
!=
===
!==

比较运算符的运算结果是布尔值

1.4.3 逻辑运算符
&	与:运算符两边的表达式都要计算
|	或:运算符两边的表达式都要计算

&&	短路与:如果前面的条件不满足,后面的条件就不用计算了
||	短路或
!	非

例题

<?php
$a=5;
$b=10;
if($a>10 && ++$a>20)
	echo '你好吗';
echo $a;		//5
//分析:$a>10为false, 与中只要有一个是false,另一个不用计算结果肯定是false,所以短路与++a就不计算了,结果是5
----------------------------
<?php
$a=5;
$b=10;
if($a<10 || ++$a>20)
	echo '你好吗';

echo $a;		//5
//分析:短路或只要有一个为true,结果肯定是true,$a<10结果是true,后面++$a就不用计算了。
1.4.4 赋值运算符
=	//赋值
+=			//a+=b   a=a+b
-=
*=
/=
%=
1.4.5 字符串连接符(.)
echo 'aa'.'bb';		//字符串链接	aabb
1.4.6 错误抑制符(@)

错误抑制符只对表达式有效

<?php
echo @($aa+$bb);	//错误抑制
1.4.7 三元运算符(?

语法:

表达式?值1:值2
//表达式的值为true,返回值1,否则返回值2

练习

<?php
$num=11;
echo $num%2?'奇数':'偶数';
1.4.8 null合并运算符(??)

PHP7.0以后才支持

例题

<?php
echo $name??'姓名不详';		//姓名不详

多学一招:两个用来判断的函数

isset():判断变量是否被设置,并且设置的不是null
empty():检查一个变量是否为空,能转成false全部是空,['',0,0.0,array(),null]

例题

echo isset($name)?$name:'姓名不详';		//姓名不详
echo '<hr>';

$stu=array();
echo empty($stu)?'空':'非空';		//空

1.5 判断

1.5.1 语法

单分支

if(条件){
    
    
}

双分支

if(条件){
    
    //代码块1
}else{
    
    //代码块2
}

多分支

if(条件){
    
    
}elseif(条件){
        //注意:elseif之间没有空格
    
}else{
    
    
}

多路选择

switch(表达式){
    
        case 常量:
            //代码块
            break;
        case 常量:
            //代码块
            break;
   		default:
        	//代码块
}
1.5.2 例题

例题一、判断闰年(练习双分支)

步骤:

1、创建表单
2、提交数据
3、在服务器获取提交的数据,并判断

代码实现

<body>
<?php
if(!empty($_POST)){	//$_POST不为空说明有post提交的数据
	//var_dump($_POST);
	$year=$_POST['year'];	//获取年份
	if($year==''){
		echo '您没有输入年份';
	}else{
		if(is_numeric($year)){	//判断$year是否是数字或字符串数字
			$year+=0;		//将字符串数字转成数字型  
			if(is_int($year)){	//is_int用来检测变量是否是整型
				if($year<1){
					echo '年份必须正整数';
				}else{
					if($year%4==0 && $year%100!=0 || $year%400==0)
						echo "{$year}是闰年";
					else
						echo "{$year}是平年";
				}
			}else{
				echo '您输入的不是整数';
			}
		}else{
			echo '您输入的不是数字';
		}
	}
}	
?>
<form method="post" action="">
	请输入年份: <input type="text" name="year"> <br />
	<input type="submit" name="button" value="判断闰年">
</form>
</body>

运行结果

1559378795674

小结:

1、$_POST是一个变量,用来保存post提交的数据

2、action=''表示将数据提到本页面

3、is_numeric()判断变量是否是数字或字符串数字

4、is_int()判断变量是否是整型

5、if、else后面如果只是一句代码,大括号可以省略

例题二:判断成绩(练习多分支)

目标:输入语文和数学,判断等级

代码实现

<body>
<?php
if(isset($_POST['button'])){	//点击了提交按钮
	$ch=$_POST['ch'];		//获取语文成绩
	$math=$_POST['math'];	//获取数学成绩
	if($ch=='' || !is_numeric($ch) || $ch<0 || $ch>100){
		echo '语文成绩必须在0-100之间';
	}
	elseif($math=='' || !is_numeric($math) || !($math>=0 && $math<=100)){
		echo '数学成绩必须在0-100之间';
	}else{
		$avg=($ch+$math)/2;		//求平均值
		echo "您的平均分是:{$avg}<br>";
		if($avg>=90)
			echo 'A';
		elseif($avg>=80)
			echo 'B';
		elseif($avg>=70)
			echo 'C';
		elseif($avg>=60)
			echo 'D';
		else
			echo 'E';
	}
}
?>
<form method="post" action="">
	语文: <input type="text" name="ch"> <br />
	数学: <input type="text" name="math"> <br />
	<input type="submit" name="button" value="判断成绩">
</form>
</body>

运行结果

1559380062929

例题三:更改颜色(switch-case)

目标:将文字的颜色改成选择的颜色

<body>
<?php
if(isset($_POST['button'])) {
	switch($_POST['color']){
		case '1':
			$color='#FF0000';	//红色
			break;
		case '2':
			$color='#009900';	// 绿色
			break;
		case '3':
			$color='#0000FF';	//蓝色
			break;
		default:
			$color='#000000';	//黑色
	}
	echo <<<str
	<script type="text/javascript">
	window.οnlοad=function(){
		document.getElementById('shi').style.color='$color';
	}
	</script>
str;
}
?>

<div id="shi">
	锄禾日当午, <br />
	
汗滴禾下土。 <br />
	
谁知盘中餐, <br />
	
粒粒皆辛苦。 <br />
</div>
<form method="post" action="">
	<select name="color">
		<option value="0">请选择颜色</option>
		<option value="1">红色</option>
		<option value="2">绿色</option>
		<option value="3">蓝色</option>
	</select>
	<input type="submit" name="button" value="更改颜色">
</form>
</body>

运行结果

1559380886299

1.6 作业

计算器

1559381546116

1.2 循环

1.2.1 for
for(初始值;条件;增量){
    
	//循环体
}

注意:循环中千万不能出现死循环

思考:如下代码输出什么

例题一:

<?php
for($i=1;$i<=10;$i+=2){
    
	echo "{
      $i}:锄禾日当午<br>";
}
/*
1:锄禾日当午
3:锄禾日当午
5:锄禾日当午
7:锄禾日当午
9:锄禾日当午
*/

例题二:

<?php
for($i=1;$i<=10;){
    
	
}
//死循环,$i永远等于1,1永远小于10,条件永远为true

例题三

<?php
for($i=1;;$i++){
    
}
//死循环,只要没有条件都是死循环

例题四

<?php
for(;;){
    
}
//这是一个经典的死循环
1.2.3 思考题

1、如下代码循环了几次?

for($i=1;$i!=5;$i++){
    
    
}
//循环了4次

2、在循环N次循环体中,初始值执行了几次?条件执行了几次?增量执行了几次?

初始值执行了1次
条件执行了N+1次
增量执行了N次

3、在循环执行完毕后,$i的值是存在的。

<?php
for($i=1;$i<=3;$i++){
    
}
echo $i;		//4
1.2.4 while、do-while

语法

while(条件){
    
}
-------------------------
do{
    
    
}while(条件)

小结:

1、for、while、do-while可以相互替换

2、如果明确知道循环多少次首先for循环,如要要循环到条件不成立为止选while或do-while

3、先判断再执行选while,先执行再判断选do-while

4、while循环条件不成立就不执行,do-while至少执行一次

1.2.5 例题

1、使用三种循环实现从1加到100

<?php
//1、for循环实现
$sum=0;
for($i=1;$i<=100;$i++){
    
	$sum+=$i;	//$sum=$sum+$i;
}
echo $sum;

//分析
/**
*
$i			$sum
1			1
2			1+2
3			1+2+3	
4			1+2+3+4
...
100			1+2+3+++100
*/
-------------------------------------------------
//2、while循环
$i=1;
$sum=0;		//保存和
while($i<=100){
    
	//方法一
	/*
	$sum+=$i;
	$i++;
	*/

	//方法二
	$sum+=$i++;
}
echo $sum;
--------------------------------------------------
    
//3、do-while循环
$i=1;
$sum=0;
do{
    
	$sum+=$i;
	$i++;
}while($i<=100);
echo $sum,'<br>';	//5050

//可以有如下更改
$i=1;
$sum=0;
do{
    
	$sum+=$i++;      //++后置
}while($i<=100);
echo $sum,'<br>';	//5050

//可以做如下更改
$i=1;
$sum=0;
do{
    
	$sum+=$i;
}while(++$i<=100);    //++前置
echo $sum,'<br>';		//5050

小结:

1、for、while、do-while可以相互替换

2、结合++前置和++后置考虑逻辑

1.2.6 多语句表达式

初始值、增量可以由多条语句组成

例题:数字分解

<?php
for($i=1,$j=9;$i<=$j;$i++,$j--){
    
	echo "10可以分成{
      $i}{
      $j}<br>";
}
//运行结果
/*
10可以分成1和9
10可以分成2和8
10可以分成3和7
10可以分成4和6
10可以分成5和5
*/

小结:初始值、增量可以写多个表达式,但是条件一般只写一个,如果条件写多个,只是最后一个条件起作用

1.2.7 双重循环

1、打印阶梯数字

<?php
for($i=1;$i<=9;$i++){
    	//循环行
	for($j=1;$j<=$i;$j++){
    	//循环列
		echo $j,'&nbsp;';
	}
	echo '<br>';
}
//运行结果
1 
1 2 
1 2 3 
1 2 3 4 
1 2 3 4 5 
1 2 3 4 5 6 
1 2 3 4 5 6 7 
1 2 3 4 5 6 7 8 
1 2 3 4 5 6 7 8 9 

2、打印九九乘法表

<style type="text/css">
	table{
		width:980px;
	}
	table,td{
		border:solid 1px #0000FF;
		border-collapse:collapse;
	}
	td{
		height:40px;	
	}
</style>

<table>
<?php
for($i=1;$i<=9;$i++){	//行
	echo '<tr>';
	for($j=1;$j<=$i;$j++){	//列
		echo "<td>{$j}*{$i}=".($j*$i).'</td>';
	}
	echo '</tr>';
}
?>
</table>

运行结果

1559532760670

小结:规则:当前列*当前行

1.28 foreach

foreach循环是用来遍历数组

语法

//语法一
foreach(数组 as){
    
}
//语法二
foreach(数组 as=>){
    
}

例题

<?php
$stu=['tom','berry','ketty'];
foreach($stu as $v){
    
	echo $v,'<br>';
}
/**
tom
berry
ketty
*/
echo '<hr>';
-----------------------------------------------------------
foreach($stu as $k=>$v){
    
	echo "{
      $k}:{
      $v}<br>";
}
/**
0:tom
1:berry
2:ketty
*/

1.3 跳转语句

1.3.1 语法

break:中断循环

continue:中断当前循环,进入下一个循环

例题:

<?php
for($i=1; $i<=10; $i++) {
    
	if($i==5)
		break;  //中断循环
	echo "{
      $i}:锄禾日当午<br>";
}
//结果
1:锄禾日当午
2:锄禾日当午
3:锄禾日当午
4:锄禾日当午
--------------------------------------------------
<?php
for($i=1; $i<=10; $i++) {
    
	if($i==5)
		continue;  //跳出5,进入6循环
	echo "{
      $i}:锄禾日当午<br>";
}
1:锄禾日当午
2:锄禾日当午
3:锄禾日当午
4:锄禾日当午    //注意,没有打印第5句
6:锄禾日当午
7:锄禾日当午
8:锄禾日当午
9:锄禾日当午
10:锄禾日当午    
1.3.2 中断多重循环

break和continue默认中断、跳出1重循环,如果调中断、跳出多重循环,在后面加一个数字。

<?php
for($i=1; $i<=10; $i++) {
    
	for($j=1;$j<=$i;$j++){
    
		echo $j.'&nbsp;';
		if($j==5){
    
			break 2;   //中断2重循环
		}
	}	
	echo '<br>';
}
//运行结果
1 
1 2 
1 2 3 
1 2 3 4 
1 2 3 4 5 

练习

<?php
for($i=1; $i<=10; $i++) {
    
	switch($i){
    
		case 5:
			break 2;
	}
	echo $i,'<br>';
}
//结果
1
2
3
4

小结:switch的本质是循环了一次的循环

1.4 替代语法

php中除了do-while以外,其他的语法结构都有替代语法

规则:左大括号变冒号,右大括号变endXXX

//if的替代语法
    if():

    elseif():

    else:

    endif;
//switch替代语法
    switch():

    endswitch;
//for
    for():

    endfor;
//while
    while():

    endwhile;
//foreach
    foreach():

    endforeach;

例题:在混编的时候用替代语法

<body>
<?php
for($i=1;$i<=10;$i++):
	if($i%2==0):
?>
	<?php echo $i;?>:锄禾日当午<br>
<?php
	endif;
endfor;
?>
</body>
//运行结果
2:锄禾日当午
4:锄禾日当午
6:锄禾日当午
8:锄禾日当午
10:锄禾日当午

小结:可以通过替代语法证明else if之间如果有空格是嵌套if语句。

<?php
$score=80;
if($score>=90):
	echo 'A';
elseif($score>=80):    //elseif之间没有空格,如果有空格是嵌套if语句
	echo 'B';
else:
	echo 'C';
endif;
----------------------------------------
<?php
$score=80;
if($score>=90):
	echo 'A';
else:
	if($score>=80):
		echo 'B';
	
	else:
		echo 'C';
	endif;
endif;

1.5 函数

1、函数就是一段代码块

2、函数可以实现模块化编程

1.5.1 函数定义
function 函数名(参数1,参数2...){
    
    //函数体
}

通过函数名()调用函数

<?php
//定义函数
function show() {
    
	echo '锄禾日当午<br>';
}
//调用
show();		//锄禾日当午
SHOW();		//锄禾日当午  函数名不区分大小写

小结:

1、变量名区分大小写

2、关键字、函数名不区分大小写

1.5.2 可变函数

将函数名存储到变量中

<?php
function show($args) {
    
	echo $args,'<br>';
}
$str='show';	//将函数名保存到变量中
$str('锄禾日当午');

例题:随机调用函数

<?php
 //中文显示
function showChinese() {
    
	echo '锄禾日当午<br>';
}
//英文显示
function showEnglish() {
    
	echo 'chu he re dang wu<br>';
}
//测试
$fun=rand(1,10)%2?'showChinese':'showEnglish';   //可变变量
$fun();
1.5.3 匿名函数

匿名函数就是没有名字的函数

<?php
//匿名函数
$fun=function(){
    
	echo '锄禾日当午<br>';
};
//匿名函数调用
$fun();
1.5.4 参数传递

函数的参数有形式参数和实际参数

形式参数是定义函数时候的参数,只起形式的作用,没有具体的值

实际参数的调用函数时候的参数,有具体的值

<?php
function fun($num1,$num2) {
    
	echo $num1+$num2;
}
fun(10,20);		//30

默认情况下,参数的传递是值传递

<?php
$num=10;
function fun($args) {
    
	$args=100;
}
fun($num);
echo $num;		//10

地址传递

<?php
$num=10;
//地址传递
function fun(&$args) {
       //&符表示取地址
	$args=100;
}
fun($num);
echo $num;		//100

小结

1、函数的参数默认是值传递

2、如果要传递地址,在参数前面加&

3、如果是地址传递,不能直接写值

function fun(&$args) {
    
	$args=100;
}
fun(10);   //Fatal error: Only variables can be passed by reference (只有变量才能传递引用)
1.5.5 参数默认值

1、在定义函数的时候给形参赋值就是参数的默认值

<?php
//参数的默认值
function fun($name,$add='地址不详') {
    
	echo '姓名:'.$name,'<br>';
	echo '地址:'.$add,'<hr>';
}
//测试
fun('tom','北京');
fun('berry');

1559548982814

2、默认值必须是值,不能用变量代替

<?php
$str='地址不详'
function fun($name,$add=$str) {
       //错误,默认值可以使用变量
	echo '姓名:'.$name,'<br>';
	echo '地址:'.$add,'<hr>';
}

3、默认值可以使用常量

<?php
define('ADD','地址不详');
function fun($name,$add=ADD) {
        //默认值可以使用常量
	echo '姓名:'.$name,'<br>';
	echo '地址:'.$add,'<hr>';
}
//测试
fun('berry');

4、有默认值的写在后面,没有默认值的写在前面

<?php
//没有默认值的写在前面,有默认值写在后面
function fun($name,$age='未知',$add='地址不详') {
    
	echo "姓名:{
      $name}<br>";
	echo "年龄:{
      $age}<br>";
	echo "地址:{
      $add}<br>";
}
fun('tom');
//运行结果
姓名:tom
年龄:未知
地址:地址不详
1.5.6 参数个数不匹配
<?php
function fun($num1,$num2) {
    
	echo $num1,'<br>';
	echo $num2,'<br>';
}
 //fun(10);	//实参少于形参(报错)
fun(10,20,30); //实参多于形参,只取前面对应的值

获取所有传递的参数

<?php
function fun() {
    
	//echo func_num_args(),'<br>';	//获取参数的个数
	$args=func_get_args();	//获取参数数组
	print_r($args);
}
fun(10);
fun(10,20);
fun(10,20,30); 
1.5.7 参数约束

1、定义变长参数(了解)

<?php
// ...$hobby包含了除了前面两个参数以外的所有参数
function fun($name,$age,...$hobby) {
    
	echo '姓名:'.$name,'<br>';
	echo '年龄:'.$age,'<br>';
	print_r($hobby);
	echo '<hr>';
}
fun('tom',22);
fun('berry',25,'读书','睡觉');

运行结果

1559550261505

多学一招:

function fun(...$args) {
    
	print_r($args);
	echo '<br>';
}
$num=[10,20];
echo '<pre>';
fun(...$num);   //将数组中的参数展开
//运行结果
/*
Array
(
    [0] => 10
    [1] => 20
)
*/

2、参数类型约束

//类型约束
function fun(string $name,int $age) {
    
	echo "姓名:{
      $name},'<br>'";
	echo "年龄:{
      $age}<br>";
}
fun('tom',22);
//约束$name是字符串型,$age是整型

3、返回值约束

function fun(int $num1,int $num2):int {  //必须返回整型
	return $num1+$num2;
}
echo fun(10,20);		//30

可以约束:string、int、float、bool、数组

//约束返回类型是数组
function fun():array {
}
//约束return后面不能有返回值  必须在7.1以后的版本中才支持
function fun():void {    //void是空的意思
	return;
}
fun();

1.6 return

1.6.1 终止脚本执行
<?php
echo '锄禾日当午<br>';
return;			//终止脚本执行
echo '汗滴禾下土<br>';	//不执行

提醒:return只能中断当前页面,如果有包含文件,只能中断包含文件

例题:

6-demo.php

<?php
echo '锄禾日当午<br>';
require './test.php';    //包含文件
echo '汗滴禾下土<br>';

test.php

<?php
echo 'aaa<br>';
return;   //只能中断test.php
echo 'bbb<br>';

运行结果

1559552969636

如果要完全终止脚本执行,使用exit()、或die()

echo 'aaa<br>';
exit();  //die()
echo 'bbb<br>';
1.6.2、返回页面结果

test.php

<?php
return array('name'=>'tom','sex'=>'男');

6-demo.php

<?php
$stu=require './test.php';
print_r($stu);  //Array ( [name] => tom [sex] => 男 ) 

小结:在项目中引入配置文件就使用这种方法

1.6.3 函数的返回和终止

return在函数中使用作用有二
1、终止函数执行

2、返回值

function fun() {
    
	echo 'aaa';
	return ;		//终止函数执行
	echo 'bbb';
}
fun();   //aaa
----------------------------------
function fun() {
    
	return 10;	//返回值
}
echo fun();		//10

1.7 作业讲解

计算器

<body>
<?php
$num1='';	//$num1的初始值
$num2='';	//$num2的初始值
$op='';		//操作符
$result='';	//结果
if(!empty($_POST)) {
	$num1=$_POST['num1'];
	$num2=$_POST['num2'];
	$op=$_POST['op'];		//操作符
	switch($op){
		case '+':
			$result=$num1+$num2;
			break;
		case '-':
			$result=$num1-$num2;
			break;
		case '*':
			$result=$num1*$num2;
			break;
		case '/':
			$result=$num1/$num2;
			break;
	}
}
?>
<form method="post" action="">
	<input type="text" name="num1" value='<?php echo $num1?>'>
	<select name="op">
		<option value="+" <?php echo $op=='+'?'selected':''?>>+</option>
		<option value="-" <?php echo $op=='-'?'selected':''?>>-</option>
		<option value="*" <?php echo $op=='*'?'selected':''?>>*</option>
		<option value="/" <?php echo $op=='/'?'selected':''?>>/</option>
	</select>
	<input type="text" name="num2" value='<?php echo $num2?>'>
	<input type="submit" name="button" value="=">
	<input type="text" name="result" value='<?php echo $result?>'>
</form>
</body>

运行结果

1559526848995

1.8 作业

1、 通过for循环将数组中值求和、求平均值

2、数组翻转

3、遍历二维数组

4、 循环输出1-100,其中3的倍数输出A,5的倍数输出B,15输出C。

5、 打印水仙花数

6、 打印100以内的斐波那契数(迭代法) 1 1 2 3 5 8 13 21 …

7、 打印星星

1559302397252

8、 生成颜色面板

1559553900215

1.2 作用域

1.2.1 变量作用域

1、全局变量:在函数外面

2、局部变量:在函数里面,默认情况下,函数内部是不会去访问函数外部的变量

3、超全局变量:可以在函数内部和函数外部访问

1559615291159

<?php
$num=10;   
function fun() {
	echo $num;     //Notice: Undefined variable: num  
}
fun();
//函数内部默认不能访问函数外部的值
---------------------
<?php
$_POST['num']=10;   //将值付给超全局变量
function fun() {
	echo $_POST['num'];    //获取超全局的值   10
}
fun();
----------------------------
<?php
function fun() {
	$_GET['num']=10;  //将值付给超全局变量
}
fun();
echo $_GET['num'];  //打印超全局变量的值  10

在函数内部访问全局变量

<?php
$num=10;  //全局变量
function fun() {
    
	echo $GLOBALS['num'];	//输出全局的$num
}
fun();

练习:如下代码输出什么

<?php
function fun() {
    
	$GLOBALS['num']=10;  //将值付给全局的$num
}
fun();
echo $num;   //10

global关键字

<?php
$num=10;
function fun() {
    
	global $num;   //将全局变量的$num的地址引入到函数内部  相当于$num=&GLOBALS['num']
	echo $num;	//10
	$num=100;
}
fun();
echo '<br>';
echo $num;    //100
-----------------------------------
<?php
$num=10;
function fun() {
    
	global $num;
	unset($num);  //销毁的是引用,不是具体的值
}
fun();
echo $num;    //10  

小结:

1、$GLOBALS保存的是全局变量的所有的值

<?php
$a=10;
$b=20;
function show() {
    
	echo '<pre>';
	var_dump($GLOBALS);   //是一个数组,保存的是全局变量的所有的值
}
show();

2、global用于创建一个全局变量的引用

注意:常量没有作用域的概念

<?php
/*
define('PI',3.14);
function fun() {
	echo PI;   //3.14
}
fun();
echo '<br>';
*/
-------------------------------------
function fun() {
    
	define('PI',3.14);
}
fun();
echo PI;   //3.14
1.2.2 静态变量(static)

静态变量一般指的是静态局部变量。

静态变量只初始化一次

<?php
function fun() {
    
	$num=10;	//普通变量每调用一次初始化一次,调用完毕销毁
	$num++;
	echo $num,'<br>';
}
fun();	//11
fun();	//11
--------------------------------
<?php
function fun() {
    
	static $num=10;	//静态变量只初始化一次,调用完毕吧不销毁,第二次调用的时候就不再初始化
	$num++;
	echo $num,'<br>';
}
fun();	//11
fun();	//12

常量和静态变量的区别

1、常量和静态变量都是初始化一次

2、常量不能改变值,静态变量可以改变值

3、常量没有作用域,静态变量有作用域

<?php
function fun1() {
    
	define('num',10);
}
function fun2() {
    
	echo num;   //10
}
fun1();
fun2();
------------------------------------------------------------
<?php
function fun1() {
    
	static $num=10;
}
function fun2() {
    
	echo $num;  //Notice: Undefined variable: num 因为静态变量是有作用域的
}
fun1();
fun2();
1.2.3 匿名函数use()

默认情况下,函数内部不能访问函数外部的变量,但在匿名函数中,可以通过use将外部变量引入匿名函数中

<?php
$num=10;
$fun=function() use($num) {
      //将$num引入到匿名函数中
	echo $num;	
};
$fun();   //10

思考:如何在函数内部访问函数外部变量

1、使用超全局变量

2、$GLOBALS

3、global

4、use将函数外部变量引入到匿名函数内部

练习:如果代码输出什么

<?php
$num=10;
function test() {
    
	$num=20;
	$fun=function() use($num) {
       //只能引入一层
		echo $num;
	};
	$fun();
}
test();    //20

多学一招:use可以引入值,也可以引入地址

<?php
$num=10;
$fun=function()use(&$num){
       //use可以传地址
	$num=100;
};
$fun();
echo $num;  //100

1.3 递归

函数内部自己调用自己

递归有两个元素,一个是递归点(从什么地方递归),第二递归出口

例题1:输出9 8 7 6 …

<?php
function printer($num) {
    
	echo $num,'&nbsp;';
	if($num==1)	//递归出口
		return;
	printer($num-1);	//递归点
}
printer(9);	//9 8 7 6 5 4 3 2 1 

例题2:从1加到100

function cal($num) {
    
	if($num==1)
		return 1;
	return $num+cal($num-1);
}
echo cal(100);
//分析
/**
第$i次执行			结果
cal(100)			100+cal(99)
=					100+99+cal(98)
=					100+99+98+cal(97)
=					100+99+98+++++cal(1)
=					100+99+98++++1
*/

例题:打印前10个斐波那契数列

//打印第5个斐波那契数
function fbnq($n) {
    
	if($n==1 || $n==2)
		return 1;
	return fbnq($n-1)+fbnq($n-2); //第n个斐波那契数等于前两个数之和
}
echo fbnq(5),'<br>';
/**
*分析:
fbnq(5)	=fbnq(4)+fbnq(3)
		=fbnq(3)*2+fbnq(2)
		=(fbnq(2)+fbnq(1))*2+fbnq(2)
		=(1+1)*2+1
		=5
*/
//打印前10个斐波那契数
for($i=1;$i<=10;$i++)
	echo fbnq($i),'&nbsp;';   //1 1 2 3 5 8 13 21 34 55 

小结:递归尽量少用,因为递归需要用到现场保护,现场保护是需要消耗资源的

1.4 包含文件

场景:

1559630150559

1.4.1 包含文件的方式

1、require:包含多次

2、include:包含多次

3、require_once: 包含一次

4、include_once: 包含一次

1559630561486

1559630588666

小结:

1、require遇到错误抛出error类别的错误,停止执行

2、include遇到错误抛出warning类型的错误,继续执行

3、require_once、include_once只能包含一次

4、HTML类型的包含页面中存在PHP代码,如果包含到PHP中是可以被执行的

5、包含文件相当于把包含文件中的代码拷贝到主文件中执行,魔术常量除外,魔术常量获取的是所在文件的信息。

6、包含在编译时不执行、运行时加载到内存、独立编译包含文件

1.4.2 包含文件的路径
./		当前目录
../		上一级目录

区分如下包含:

require './head.html';   //在当前目录下查找
require 'head.html';	  //受include_path配置影响

1559631648089

include_path的使用场景:

如果包含文件的目录结构比较复杂,比如:在c:\aa\bb\cc\dd中有多个文件需要包含,可以将包含的路径设置成include_path,这样包含就只要写文件名就可以了

<?php
set_include_path('c:\aa\bb\cc\dd');  //设置include_path
require 'head1.html';	  //受include_path配置影响
require 'head2.html';

include_path可以设置多个,路径之间用分号隔开

set_include_path('c:\aa\bb\cc\dd;d:\\');

多学一招:

正斜(/) web中目录分隔用正斜  http://www.sina.com/index.php
反斜(\)物理地址的分隔用反斜,(windows中物理地址正斜和反斜都可以)  c:\web1\aa

1.5 错误处理

1.5.1 错误的级别
  1. notice:提示
  2. warning:警告
  3. error:致命错误

notice和warning报错后继续执行,error报错后停止执行

1.5.2 错误的提示方法

方法一:显示在浏览器上

方法二:记录在日志中

1.5.3 与错误处理有关的配置

在php.ini中

1. error_reporting = E_ALL:报告所有的错误
2. display_errors = On:将错误显示在浏览器上
3. log_errors = On:将错误记录在日志中
4. error_log=’地址’:错误日志保存的地址

在项目开发过程中有两个模式,开发模式,运行模式

开发模式:错误显示在浏览器上,不要记录在日志中
运行模式:错误不显示在浏览器上,记录是日志中

例题

<?php
$debug=false;		//true:开发模式  false:运行模式
ini_set('error_reporting',E_ALL);	//所有的错误有报告
if($debug){
    
	ini_set('display_errors','on');	//错误显示是浏览器上
	ini_set('log_errors','off');	//错误不显示在日志中
}else{
    
	ini_set('display_errors','off');
	ini_set('log_errors','on');
	ini_set('error_log','./err.log');	//错误日志保存的地址
}

//测试
echo $num;

提示:ini_set()设置PHP的配置参数

1.5.4 自定义错误处理(了解)

通过trigger_error产生一个用户级别的 error/warning/notice 信息

<?php
$age=100;
if($age>80){
    
	//trigger_error('年龄不能超过80岁');  //默认触发了notice级别的错误
	//trigger_error('年龄不能超过80岁',E_USER_NOTICE);	//触发notice级别的错误
	//trigger_error('年龄不能超过80岁',E_USER_WARNING);
	trigger_error('年龄不能超过80岁',E_USER_ERROR);   //错误用户error错误
}

注意:用户级别的错误的常量名中一定要带有USER。

定义错误处理函数

function error() {
    
	echo '这是自定义错误处理';
}
set_error_handler('error');	//注册错误处理函数,只要有错误就会自动的调用错误处理函数
echo $num;

运行结果

1559635406021

处理处理函数还可以带有参数

/**
*自定义错误处理函数
*@param $errno int 错误类别
*@param $errstr string 错误信息
*@param $errfile string 文件地址
*@param $errline int 错误行号
*/
function error($errno,$errstr,$errfile,$errline) {
    
	switch($errno){
    
		case E_NOTICE:
		case E_USER_NOTICE:
			echo '记录在日志中,上班后在处理<br>';
			break;
		case E_WARNING:
		case E_USER_WARNING:	
			echo '给管理员发邮件<br>';
			break;
		case E_ERROR:
		case E_USER_ERROR:
			echo '给管理员打电话<br>';
			break;
	}
	echo "错误信息:{
      $errstr}<br>";
	echo "错误文件:{
      $errfile}<br>";
	echo "错误行号:{
      $errline}<br>";
}
set_error_handler('error');
echo $num;

//运行结果
记录在日志中,上班后在处理
错误信息:Undefined variable: num
错误文件:F:\wamp\www\4-demo.php
错误行号:50

1.6 文件编程

1.6.1 文件夹操作

**1 、**创建文件夹【mkdir(路径,权限,是否递归创建)

make:创建
directory:目录,文件夹

例题

<?php
//1、创建目录
//mkdir('./aa');	//创建aa文件夹
//mkdir('./aa/bb');	//在aa目录下创建bb(aa目录必须存在)
mkdir('./aa/bb/cc/dd',0777,true);	//递归创建

小结:

1、0777表示是文件夹的权限,在Linux中会详细讲解

2、true表示递归创建,默认是false

**2、**删除文件夹【rmdir()】

//remove:移除

rmdir('./aa/bb/cc/dd');	//删除dd文件夹

提醒:

1、删除的文件夹必须是空的
2、PHP基于安全考虑,没有提供递归删除。

**3、**重命名文件夹【rename(旧名字,新名字)】

rename('./aa','./aaa');	//将aa改为aaa

**4、**是否是文件夹【is_dir()】

echo is_dir('./aaa')?'是文件夹':'不是文件夹';

**5、**打开文件夹、读取文件夹、关闭文件夹

$folder=opendir('./');	//打开目录
//var_dump($folder);		//resource(3) of type (stream) 
while($f=readdir($folder)){
    	//读取文件夹
	if($f=='.' || $f=='..')
		continue;
	echo iconv('gbk','utf-8',$f),'<br>';  //将gbk转成utf-8
}
closedir($folder);		//关闭文件夹

小结:

1、opendir()返回资源类型
2、每个文件夹中都有.和..
3、iconv()用来做字符编码转换

1.7 作业讲解

1、 通过for循环将数组中值求和、求平均值

<?php
//1、求数组的和、平均值
$num=[1,20,53,23,14,12,15];
$sum=0;
for($i=0,$n=count($num);$i<$n;$i++){
	$sum+=$num[$i];
}
echo '和是:'.$sum,'<br>';		//和是:138
echo '平均值:'.number_format($sum/count($num),1);   //精确到小数点后面1位  平均值:19.7
echo '<hr>';

2、数组翻转

$stu=['tom','berry','ketty','rose','jake'];
for($i=0,$j=count($stu)-1;$i<$j;$i++,$j--){
    
	[$stu[$i],$stu[$j]]=[$stu[$j],$stu[$i]];   //元素交换
}
print_r($stu); //Array ( [0] => jake [1] => rose [2] => ketty [3] => berry [4] => tom ) 

3、遍历二维数组

$stu=[
	[1,2,3,4],
	[10,20,30,40]
];
for($i=0;$i<count($stu);$i++){
    	//循环第一列
	for($j=0;$j<count($stu[$i]);$j++){
       //循环第二列
		echo $stu[$i][$j],'&nbsp;';
	}
	echo '<br>';
}
//运行结果
1 2 3 4 
10 20 30 40 

4、 循环输出1-100,其中3的倍数输出A,5的倍数输出B,15输出C。

for($i=1; $i<=100; $i++) {
    
	if($i%15==0)   //先写%15,,因为可以%15的值一定可以%3和%5
		echo 'C';
	elseif($i%3==0)
		echo 'A';
	elseif($i%5==0)
		echo 'B';
	else
		echo $i;

	echo '&nbsp;';
}

5、 打印水仙花数

for($i=100;$i<=999;$i++){
    
	$a=(int)($i/100);		//百位数
	$b=(int)(($i%100)/10);	//十位数
	$c=$i%10;				//个位数
	if($i==pow($a,3)+pow($b,3)+pow($c,3))
		echo $i,'<br>';
}
//pow($a,3)  表示$a的三次方
//运行结果
153
370
371
407

6、 打印100以内的斐波那契数(迭代法)1 1 2 3 5 8 13 21 …

$num1=1;   //第一个数
$num2=1;    //第二个数
echo $num1,'&nbsp;',$num2,'&nbsp;';
while(true){
    
	$num3=$num1+$num2;   //第三个数是前面两个数的和
	if($num3>100)		 //超过100就终止循环
		break;
	echo $num3,'&nbsp;';
	$num1=$num2;		//将$num2移给$num1
	$num2=$num3;		//将$num3移给$num2
}
//1 1 2 3 5 8 13 21 34 55 89 

1.8 作业

1、一只猴子看守一堆桃子,第一天吃了一半后又多吃了1个,第二天一样,到第十天的时候就剩下一个桃子,请问原来有几个桃子?

2、递归遍历整个文件夹

1.2 文件操作

**1、**将字符串写入文件

<?php
$str="床前明月光,\r\n疑是地上霜。\r\n举头望明月,\r\n低头思故乡。";
file_put_contents('./test.txt',$str);  //将字符串写到文本中

小结:

1、 所有的“写”操作都是清空重写

2、在文本中换行是\r\n

\r:回车   光标移动到当前行的最前面
\n:换行	将光标下移动一行
按键盘的回车键做了两步,第一步将光标移动到当前行的最前面,第二步下移一行。

3、\r\n是特殊字符,必须放在双引号内

**2、**将整个文件读入一个字符串

//方法一:
echo file_get_contents('./test.txt');   //将整个文件读入一个字符串 
//方法二:
readfile('./test.txt');	//读取输出文件内容

//注意:echo file_get_contents()==readfile()

**3、**打开文件并操作

fopen(地址,模式)	打开文件
模式:
r:读		read
w:写		 write
a:追加	append

例题:

//3.1、打开文件写入
/*
$fp=fopen('./test.txt','w');    //打开文件返回文件指针(文件地址)
//var_dump($fp);		//resource(3) of type (stream) 
for($i=1;$i<=10;$i++)
	fputs($fp,'关关雎鸠'."\r\n");	//写一行
fclose($fp);	//关闭文件
*/

//3.2  打开文件读取
/*
$fp=fopen('./test.txt','r');	//打开文件读取
while($line=fgets($fp)){
	echo $line,'<br>';
}
*/

//3.3   打开文件追加
$fp=fopen('./test.txt','a');	//打开文件追加
fputs($fp,'在河之洲');			//在文件末尾追加

小结:

1、打开文件,返回文件指针(文件指针就是文件地址),资源类型

2、打开文件写、追加操作,如果文件不存在,就创建新的文件

3、打开文件读操作,文件不存在就报错

4、fputs()写一行,fgets()读一行,fclose()关闭文件

5、追加是在文件的末尾追加

**4、**是否是文件【is_file()】

echo is_file('./test.txt')?'是文件':'不是文件';

**5、**判断文件或文件夹是否存在【file_exists()】

echo file_exists('./test.txt')?'文件存在':'文件不存在';

**6、**删除文件【unlink】

$path='./test.txt';
if(file_exists($path)){
    		//文件存在
	if(is_dir($path))		//如果是文件夹用rmdir()删除
		rmdir($path);
	elseif(is_file($Path))	//如果是文件用unlink()删除
		unlink($path);
}else{
    
	echo '文件夹或文件不存在';
}

**7、**二进制读取【fread(文件指针,文件大小)】

文件的存储有两种:字符流和二进制流

二进制流的读取按文件大小来读的。

$path='./face.jpg';
$fp=fopen($path,'r');
header('content-type:image/jpeg');	//告知浏览器下面的代码通过jpg图片方式解析
echo fread($fp,filesize($path));	//二进制读取

多学一招:file_get_contents()也可以进行二进制读取

header('content-type:image/jpeg');
echo file_get_contents('./face.jpg');

小结:

1、文本流有明确的结束符,二进制流没有明确的结束符,通过文件大小判断文件是否读取完毕

2、file_get_contents()既可以进行字符流读取,也可以进行二进制读取。

1.3 表单提交数据的两种方式

1.3.1 两种方式

1、get

2、post

<form method="post" action=""></form>
<form method="get" action=""></form>
1.3.2 区别

1、外观上看

​ get提交在地址上可以看到参数

1559791997833

​ post提交在地址栏上看不到参数

1559792216632

2、安全性

​ get不安全

​ post安全

3、提交原理

​ get提交是参数一个一个的提交

​ post提交是所有参数作为一个整体一起提交

4、提交数据大小

​ get提交一般不超过255个字节

​ post提交的大小取决于服务器

// 在php.ini中,可以配置post提交的大小
post_max_size = 8M

5、灵活性

​ get很灵活,只要有页面的跳转就可以传递参数

​ post不灵活,post提交需要有表单的参与

1、 html跳转
   <a href="index.php?name=tom&age=20">跳转</a>

2、JS跳转
<script type="text/javascript">
	location.href='index.php?name=tom&age=20';
	location.assign('index.php?name=tom&age=20');
	location.replace('index.php?name=tom&age=20');
</script>

3、PHP跳转
header('location:index.php?name=tom&age=22')

小结:

GET POST
外观上 在地址上看到传递的参数和值 地址栏上看不到数据
提交数据大小 提交少量数据,不同的浏览器最大值不一样,IE是255个字符 提交大量数据,可以通过更改php.ini配置文件来设置post提交数据的最大值
安全性
提交原理 提交的数据和数据之间在独立的 将提交的数据变成XML格式提交
灵活性 很灵活,只要有页面的跳转就可以get传递数据 不灵活

1.4 服务器接受数据的三种方式

通过名字获取名字对应的值

$_POST:数组类型,保存的POST提交的值
$_GET:数组类型,保存的GET提交的值
$_REQUEST:数组类型,保存的GET和POST提交的值

例题:

HTML页面

<body>
<!--表单提交数据-->
<form method="get" action="./2-demo2.php">
	语文: <input type="text" name="ch"> <br />
	数学: <input type="text" name="math"> <br />
	<input type="submit" name="button" value="提交"> <br><br>
</form>
<!--超链接提交数据-->
<a href="2-demo2.php?ch=77&math=88">跳转</a> <br><br>
<!--js提交数据-->
<input type="button" value="点击" onclick="location.href='2-demo2.php?ch=66&math=55'"> <br><br>

<input type="button" value="点击" onclick="location.assign('2-demo2.php?ch=11&math=22')">
</body>

PHP页面

<?php
//post数组中不为空
if(!empty($_POST)) {
    
	echo '这是post提交的数据<br>';
	echo '语文:'.$_POST['ch'],'<br>';
	echo '数学:'.$_POST['math'],'<br>';
}
echo '<hr>';
//获取get提交的数据
if(!empty($_GET)){
    
	echo '这是get提交的数据<br>';
	echo '语文:'.$_GET['ch'],'<br>';
	echo '数学:'.$_GET['math'],'<br>';
}
echo '<hr>';
//既能获取get又能获取post提交的数据
echo $_REQUEST['ch'],'<br>';
echo $_REQUEST['math'];

思考题

在一个请求中,既有get又有post,get和post传递的名字是一样的,这时候通过$_REQUET获取的数据是什么?

答:结果取决于配置文件

request_order = "GP"  # 先获取GET,在获取POST值

例题

<?php
if(!empty($_POST)){
	echo '姓名:'.$_REQUEST['username'],'<br>';
}
?>
<form method="post" action="?username=berry">
	姓名: <input type="text" name="username"><br />
	<input type="submit" name="button" value="提交">
</form>
分析:先获取GET的username,再获取post的username,后面的将前面的值覆盖

小结:

1、在开发的时候,如果明确是post提交就使用$_POST获取,如果明确get提交就用$_GET获取

2、request获取效率低,尽可能不要使用,除非提交的类型不确定的情况下才使用。

1.5 参数传递

1.5.1 复选框值的传递

复选框的命名要注意带’[]'。

<body>
<?php
if(isset($_POST['button'])) {
	print_r($_POST['hobby']);
}
?>
<form method="post" action="">
	爱好: 
	<input type="checkbox" name="hobby[]" value='爬山'>爬山
	<input type="checkbox" name="hobby[]" value='抽烟'>抽烟
	<input type="checkbox" name="hobby[]" value='喝酒'>喝酒
	<input type="checkbox" name="hobby[]" value='烫头'>烫头
	<input type="submit" name="button" value="提交">
</form>
</body>

小结:

1、表单提交到本页面需要判断一下是否有post提交

2、数组的提交表单元素的名字必须带有[]。

1.5.2 例题
<body>
<?php
if(isset($_POST['button'])) {
	echo '姓名:'.$_POST['username'].'<br>';
	echo '密码:'.$_POST['pwd'].'<br>';
	echo '性别:'.$_POST['sex'].'<br>';
	echo '爱好:',isset($_POST['hobby'])?implode(',',$_POST['hobby']):'没有爱好','<br>';
	echo '籍贯:'.$_POST['jiguan'],'<br>';
	echo '留言:'.$_POST['words'];
}
?>
<form method="post" action="">
	姓名: <input type="text" name="username"> <br />
	密码: <input type="password" name="pwd"> <br />
	性别: <input type="radio" name="sex" value='1' checked>男
		   <input type="radio" name="sex" value='0'>女 <br />
	爱好: 
	<input type="checkbox" name="hobby[]" value='爬山'>爬山
	<input type="checkbox" name="hobby[]" value='抽烟'>抽烟
	<input type="checkbox" name="hobby[]" value='喝酒'>喝酒
	<input type="checkbox" name="hobby[]" value='烫头'>烫头 <br />
	籍贯:
	<select name="jiguan">
		<option value="021">上海</option>
		<option value="010">北京</option>
	</select> <br>
	留言: <textarea name="words" rows="5" cols="30"></textarea> <br />

	<input type="submit" name="button" value="提交">
</form>
</body>

运行结果

1559800993931

1.6 文件上传

开发中需要上传图片、音乐、视频等等,这种上传传递是二进制数据。

1.6.1 客户端上传文件

文件域

<input type="file" name="image">

表单的enctype属性

​ 默认情况下,表单传递是字符流,不能传递二进制流,通过设置表单的enctype属性传递复合数据。

enctype属性的值有:

  1. application/x-www-form-urlencoded:【默认】,表示传递的是带格式的文本数据。
  2. multipart/form-data:复合的表单数据(字符串,文件),文件上传必须设置此值
  3. text/plain:用于向服务器传递无格式的文本数据,主要用户电子邮件

单词

multipart:复合
form-data:表单数组
1.6.2 服务器接受文件

超全局变量$_FILES是一个二维数组,用来保存客户端上传到服务器的文件信息。二维数组的行是文件域的名称,列有5个。
1、$_FILES[][‘name’]:上传的文件名
2、$_FILES[][‘type]:上传的类型,这个类型是MIME类型(image/jpeg、image/gif、image/png)
3、$_FILES[][‘size’]:文件的大小,以字节为单位
4、$_FILES[][‘tmp_name’]:文件上传时的临时文件
5、$_FILES[][‘error’]:错误编码(值有0、1、2、3、4、6、7)0表示正确

1559802500855

$_FILES[][‘error’]详解

错误描述
0 正确
1 文件大小超过了php.ini中允许的最大值 upload_max_filesize = 2M
2 文件大小超过了表单允许的最大值
3 只有部分文件上传
4 没有文件上传
6 找不到临时文件
7 文件写入失败

1559803920217

注意:MAX_FILE_SIZE必须在文件域的上面。

只要掌握的错误号:0和4

1.6.3 将上传文件移动到指定位置

函数:

move_uploaded_file(临时地址,目标地址)

代码

<body>
<?php
if(!empty($_POST)) {
	if($_FILES['face']['error']==0){  //上传正确
        //文件上传
		move_uploaded_file($_FILES['face']['tmp_name'],'./'.$_FILES['face']['name']);
	}else{
		echo '上传有误';
		echo '错误码:'.$_FILES['face']['error'];
	}
}
?>
<form method="post" action="" enctype='multipart/form-data'>
	<input type="file" name="face">
	<input type="submit" name="button" value="上传">
</form>
</body>

小结:上传的同名的文件要给覆盖

1.6.4 与文件上传有关的配置

post_max_size = 8M:表单允许的最大值

upload_max_filesize = 2M:允许上传的文件大小

upload_tmp_dir =F:\wamp\tmp:指定临时文件地址,如果不知道操作系统指定

file_uploads = On:是否允许文件上传

max_file_uploads = 20:允许同时上传20个文件

1.7 优化文件上传

1.7.1 更改文件名

方法一:通过时间戳做文件名

<?php
$path='face.stu.jpg';
//echo strrchr($path,'.');	//从最后一个点开始截取,一直截取到最后
echo time().rand(100,999).strrchr($path,'.');   

方法二:通过uniqid()实现

$path='face.stu.jpg';
echo uniqid().strrchr($path,'.'),'<br>';   //生成唯一的ID
echo uniqid('goods_').strrchr($path,'.'),'<br>';   //带有前缀
echo uniqid('goods_',true).strrchr($path,'.'),'<br>';  //唯一ID+随机数
1.7.2 验证文件格式

方法一:判断文件的扩展名(不能识别文件伪装)

操作思路:将文件的后缀和允许的后缀对比

<body>
<?php
if(!empty($_POST)) {
	$allow=array('.jpg','.png','.gif');	//允许的扩展名
	$ext=strrchr($_FILES['face']['name'],'.');  //上传文件扩展名
	if(in_array($ext,$allow))
		echo '允许上传';
	else
		echo '文件不合法';
}
?>
<form method="post" action="" enctype='multipart/form-data'>
	<input type="file" name="face">
	<input type="submit" name="button" value="上传">
</form>
</body>

注意:比较扩展名不能防止文件伪装。

方法二:通过$_FIELS[]['type']类型(不能识别文件伪装)

<body>
<?php
if(!empty($_POST)) {
	$allow=array('image/jpeg','image/png','image/gif');	//允许的类别
	$mime=$_FILES['face']['type'];  //上传文件类型
	if(in_array($mime,$allow))
		echo '允许上传';
	else
		echo '文件不合法';
}
?>
<form method="post" action="" enctype='multipart/form-data'>
	<input type="file" name="face">
	<input type="submit" name="button" value="上传">
</form>
</body>

注意:比较$_FIELS[]['type']不能防止文件伪装。

方法三:php_fileinfo扩展(可以防止文件伪装)

​ 在php.ini中开启fileinfo扩展

extension=php_fileinfo.dll

注意:开启fileinfo扩展以后,就可以使用finfo_*的函数了

1559807821961

<body>
<?php
if(!empty($_POST)) {
	//第一步:创建finfo资源
	$info=finfo_open(FILEINFO_MIME_TYPE);
	//var_dump($info);		//resource(2) of type (file_info) 
	//第二步:将finfo资源和文件做比较
	$mime=finfo_file($info,$_FILES['face']['tmp_name']);
	//第三步,比较是否合法
	$allow=array('image/jpeg','image/png','image/gif');	//允许的类别
	echo in_array($mime,$allow)?'合法':'不合法';
}
?>
<form method="post" action="" enctype='multipart/form-data'>
	<input type="file" name="face">
	<input type="submit" name="button" value="上传">
</form>
</body>

小结:验证文件格式有三种方法

1、可以验证扩展名(不可以防止文件伪装)

2、通过$_FILES[]['type']验证(不可以防止文件伪装)

3、通过file_info扩展(可以防止文件伪装)

1.7.3 优化文件上传例题

步骤

第一步:验证是否有误

第二步:验证格式

第三步:验证大小

第四步:验证是否是http上传

第五步:上传实现

<body>
<?php
/**
*验证错误
*如果有错,就返回错误,如果没错,就返回null
*/
function check($file) {
	//1:验证是否有误
	if($file['error']!=0){
		switch($file['error']) {
			case 1:
				return '文件大小超过了php.ini中允许的最大值,最大值是:'.ini_get('upload_max_filesize');
			case 2:
				return '文件大小超过了表单允许的最大值';
			case 3:
				return '只有部分文件上传';
			case 4:
				return '没有文件上传';
			case 6:
				return '找不到临时文件';
			case 7:
				return '文件写入失败';
			default:
				return '未知错误';
		}
	}
	//2、验证格式
	$info=finfo_open(FILEINFO_MIME_TYPE);
	$mime=finfo_file($info,$file['tmp_name']);
	$allow=array('image/jpeg','image/png','image/gif');	//允许的类别
	if(!in_array($mime,$allow)){
		return '只能上传'.implode(',',$allow).'格式';
	}
	//3、验证大小
	$size=123456789;
	if($file['size']>$size){
		return '文件大小不能超过'.number_format($size/1024,1).'K';
	}
	//4、验证是否是http上传
	if(!is_uploaded_file($file['tmp_name']))
		return '文件不是HTTP POST上传的<br>';

	return null;  //没有错误
}

//表单提交
if(!empty($_POST)) {
	//上传文件过程中有错误就显示错误
	if($error=check($_FILES['face'])){
		echo $error;
	}else{
		//文件上传,上传的文件保存到当天的文件夹中
		$foldername=date('Y-m-d');		//文件夹名称
		$folderpath="./uploads/{$foldername}";	//文件夹路径
		if(!is_dir($folderpath))
			mkdir($folderpath);
		$filename=uniqid('',true).strrchr($_FILES['face']['name'],'.');	//文件名
		$filepath="$folderpath/$filename";	//文件路径
		if(move_uploaded_file($_FILES['face']['tmp_name'],$filepath))
			echo "上传成功,路径是:{$foldername}/{$filename}";
		else
			echo '上传失败<br>';
	}

}
?>
<form method="post" action="" enctype='multipart/form-data'>
	<input type="file" name="face">
	<input type="submit" name="button" value="上传">
</form>
</body>

运行结果

1559811953112

小结:

1、将时间戳转换格式

echo date('Y-m-d H:i:s',1231346),'<br>';		//将时间戳转成年-月-日 小时:分钟:秒
echo date('Y-m-d H:i:s'),'<br>';	//将当前的时间转成年-月-日 小时:分钟:秒

2、设置时区(php.ini)

1559811342514

PRC:中华人民共和国

3、PHP的执行可以不需要Apache的参与

1559809731518

1.8 作业

1、多文件上传

1559812126896

1.9 作业讲解

1、递归遍历文件夹

<?php
//获取文件夹的子级
function getFile($path) {
    
	$folder=opendir($path);		//打开文件夹
	echo '<ul>';
	while($f=readdir($folder)){
    	//读取文件夹
		if($f=='.' || $f=='..')
			continue;
		echo '<li>'.iconv('gbk','utf-8',$f).'</li>';
		$subpath="{
      $path}/{
      $f}";	
		if(is_dir($subpath))	//如果子级还是文件夹,继续打开并读取
			getFile($subpath);
	}
	
	echo '</ul>';
}
//测试
getFile('./');

运行结果

1559812920666

2、一只猴子看守一堆桃子,第一天吃了一半后又多吃了1个,第二天一样,到第十天的时候就剩下一个桃子,请问原来有几个桃子?

分析

f(n)-(f(n)/2+1)=f(n+1)
=>f(n)/2-1=f(n+1)
=>f(n)=(f(n+1)+1)*2

代码实现

<?php
function getTao($n) {
    
	if($n==10)
		return 1;
	return (getTao($n+1)+1)*2;
}
echo getTao(1);    //1534
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq331697853/article/details/128119745

智能推荐

稀疏编码的数学基础与理论分析-程序员宅基地

文章浏览阅读290次,点赞8次,收藏10次。1.背景介绍稀疏编码是一种用于处理稀疏数据的编码技术,其主要应用于信息传输、存储和处理等领域。稀疏数据是指数据中大部分元素为零或近似于零的数据,例如文本、图像、音频、视频等。稀疏编码的核心思想是将稀疏数据表示为非零元素和它们对应的位置信息,从而减少存储空间和计算复杂度。稀疏编码的研究起源于1990年代,随着大数据时代的到来,稀疏编码技术的应用范围和影响力不断扩大。目前,稀疏编码已经成为计算...

EasyGBS国标流媒体服务器GB28181国标方案安装使用文档-程序员宅基地

文章浏览阅读217次。EasyGBS - GB28181 国标方案安装使用文档下载安装包下载,正式使用需商业授权, 功能一致在线演示在线API架构图EasySIPCMSSIP 中心信令服务, 单节点, 自带一个 Redis Server, 随 EasySIPCMS 自启动, 不需要手动运行EasySIPSMSSIP 流媒体服务, 根..._easygbs-windows-2.6.0-23042316使用文档

【Web】记录巅峰极客2023 BabyURL题目复现——Jackson原生链_原生jackson 反序列化链子-程序员宅基地

文章浏览阅读1.2k次,点赞27次,收藏7次。2023巅峰极客 BabyURL之前AliyunCTF Bypassit I这题考查了这样一条链子:其实就是Jackson的原生反序列化利用今天复现的这题也是大同小异,一起来整一下。_原生jackson 反序列化链子

一文搞懂SpringCloud,详解干货,做好笔记_spring cloud-程序员宅基地

文章浏览阅读734次,点赞9次,收藏7次。微服务架构简单的说就是将单体应用进一步拆分,拆分成更小的服务,每个服务都是一个可以独立运行的项目。这么多小服务,如何管理他们?(服务治理 注册中心[服务注册 发现 剔除])这么多小服务,他们之间如何通讯?这么多小服务,客户端怎么访问他们?(网关)这么多小服务,一旦出现问题了,应该如何自处理?(容错)这么多小服务,一旦出现问题了,应该如何排错?(链路追踪)对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对每一个问题提供了相应的组件来解决它们。_spring cloud

Js实现图片点击切换与轮播-程序员宅基地

文章浏览阅读5.9k次,点赞6次,收藏20次。Js实现图片点击切换与轮播图片点击切换<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <script type="text/ja..._点击图片进行轮播图切换

tensorflow-gpu版本安装教程(过程详细)_tensorflow gpu版本安装-程序员宅基地

文章浏览阅读10w+次,点赞245次,收藏1.5k次。在开始安装前,如果你的电脑装过tensorflow,请先把他们卸载干净,包括依赖的包(tensorflow-estimator、tensorboard、tensorflow、keras-applications、keras-preprocessing),不然后续安装了tensorflow-gpu可能会出现找不到cuda的问题。cuda、cudnn。..._tensorflow gpu版本安装

随便推点

物联网时代 权限滥用漏洞的攻击及防御-程序员宅基地

文章浏览阅读243次。0x00 简介权限滥用漏洞一般归类于逻辑问题,是指服务端功能开放过多或权限限制不严格,导致攻击者可以通过直接或间接调用的方式达到攻击效果。随着物联网时代的到来,这种漏洞已经屡见不鲜,各种漏洞组合利用也是千奇百怪、五花八门,这里总结漏洞是为了更好地应对和预防,如有不妥之处还请业内人士多多指教。0x01 背景2014年4月,在比特币飞涨的时代某网站曾经..._使用物联网漏洞的使用者

Visual Odometry and Depth Calculation--Epipolar Geometry--Direct Method--PnP_normalized plane coordinates-程序员宅基地

文章浏览阅读786次。A. Epipolar geometry and triangulationThe epipolar geometry mainly adopts the feature point method, such as SIFT, SURF and ORB, etc. to obtain the feature points corresponding to two frames of images. As shown in Figure 1, let the first image be ​ and th_normalized plane coordinates

开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先抽取关系)_语义角色增强的关系抽取-程序员宅基地

文章浏览阅读708次,点赞2次,收藏3次。开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先关系再实体)一.第二代开放信息抽取系统背景​ 第一代开放信息抽取系统(Open Information Extraction, OIE, learning-based, 自学习, 先抽取实体)通常抽取大量冗余信息,为了消除这些冗余信息,诞生了第二代开放信息抽取系统。二.第二代开放信息抽取系统历史第二代开放信息抽取系统着眼于解决第一代系统的三大问题: 大量非信息性提取(即省略关键信息的提取)、_语义角色增强的关系抽取

10个顶尖响应式HTML5网页_html欢迎页面-程序员宅基地

文章浏览阅读1.1w次,点赞6次,收藏51次。快速完成网页设计,10个顶尖响应式HTML5网页模板助你一臂之力为了寻找一个优质的网页模板,网页设计师和开发者往往可能会花上大半天的时间。不过幸运的是,现在的网页设计师和开发人员已经开始共享HTML5,Bootstrap和CSS3中的免费网页模板资源。鉴于网站模板的灵活性和强大的功能,现在广大设计师和开发者对html5网站的实际需求日益增长。为了造福大众,Mockplus的小伙伴整理了2018年最..._html欢迎页面

计算机二级 考试科目,2018全国计算机等级考试调整,一、二级都增加了考试科目...-程序员宅基地

文章浏览阅读282次。原标题:2018全国计算机等级考试调整,一、二级都增加了考试科目全国计算机等级考试将于9月15-17日举行。在备考的最后冲刺阶段,小编为大家整理了今年新公布的全国计算机等级考试调整方案,希望对备考的小伙伴有所帮助,快随小编往下看吧!从2018年3月开始,全国计算机等级考试实施2018版考试大纲,并按新体系开考各个考试级别。具体调整内容如下:一、考试级别及科目1.一级新增“网络安全素质教育”科目(代..._计算机二级增报科目什么意思

conan简单使用_apt install conan-程序员宅基地

文章浏览阅读240次。conan简单使用。_apt install conan