PHP碎碎念(一)——开始入门!
依旧是无可救药的一天……在开始正文之前请容我小小的吐槽一下。
CTF吧,真的是个巨坑。
一开始选的web和misc,结果选这个方向的人太多找不到其他方向的人组队……形势所迫,只好自己看看能不能全栈或者换个方向下手。一开始想试试pwn,结果pwn要求有逆向基础,又想去试试逆向,结果逆向又要求有汇编语言基础,好巧不巧的是汇编语言的书籍刚好给人借走了……好了,毫无疑问这也是个坑,不过汇编早晚都得学,倒也不是什么大问题。但是现在又只能暂时转向web了,无奈,先从之前的SQL注入入手吧。但是没有MySQL基础去学注入实在是看天书,那去学学MySQL?巧了,MySQL要求PHP基础,PHP又要求HTML/CSS基础(所幸上学期已经学过前端三件套了),于是乎,又得先从PHP开始学起,还有一大堆协议等着,又是个巨坑……
实在是……受不了一点
好了,闲话到此打住,先来归纳一下今天学习PHP的一些笔记吧,姑且当做我的碎碎念好了。
那么,正文开始。
我参考的书是《PHP和MySQL Web开发》,同时参考了部分菜鸟驿站的内容PHP 教程 | 菜鸟教程 (runoob.com)。有兴趣的可以自行查看,适合快速预习。
开始之前
首先我们先对PHP做一个大概的综述,方便更好的理解这门语言。
在开发一个网站时,一般都是先用HTML搭建起一个大致的框架,然后用CSS美化网页属性,最后用JavaScript实现一些更复杂的用户交互功能。但是,学会这些基本上只能搭建一个静态网页,也就是说,用户不能与网站产生任何互动(也许JS除外?),每一次网页的更新都必须依靠与重写其底层的HTML代码。那么我们要如何搭建起一个动态页面来实现更加丰富的网页功能呢?答案是使用PHP。
PHP是一个服务器端脚本代码,它能接收网页传递给服务器的数据,并在后端处理数据并将其发送到网页来实现内容的更新。最经典的操作就是处理表单,比如,处理一个在线购物的购物车订单。
PHP的学习其实并不难(至少书上是这么说的),如果你有过C/C++、Python等其他编程语言基础,要上手PHP其实挺快的。PHP存在大量的函数和语句功能和C相同,基本上就是一通百通的道理(果然C是万物之母)。这里主要介绍一些PHP语言特有的属性,和C雷同的地方就略过了,也就是说,阅读这篇文章已经默认了你已经有了一定的C语言基础,不过要求也没那么高,只要掌握一些最基本的C语法就可以上手。
那么介绍到此为止,我们开始讲解PHP的语法。
万物源头之hello world
这里在书中给出了一个HTML制作的静态订单网站搭配PHP进行讲解,但是很遗憾我没有这本书的电子书资源,而且我也不想手撸一个HTML网页,所以这里我选择介绍菜鸟教程的内容。
在编程中,每每开始学习一门新语言,先输出一个hello world是传统,比如C的printf("Hello, world");
。那么,在PHP中我们要怎么发扬传统呢?下面是我们编写的第一个PHP语句。
|
这里就有许多需要讲解的地方了。
PHP语句的格式
如你所见,在执行输出函数的主体外,套着一个< ?php … ?>,以小于号开始,以大于号结束。这是PHP代码块的标志,即使是在PHP文件中,在标志外的代码仍然会被识别为HTML,只有代码块内的PHP语言才能被正确解释。所以,所有的PHP语句都必须在标志内编写。
值得一提的是这种风格有它自己的名字,叫做XML风格,是最为推荐也是最通用的风格。简短风格则是可以省开头的‘php’,但是不推荐。
echo是什么?
在PHP中一般使用echo来回显内容,使用方法如上。在echo后接你想要回显的值,如果是字符串需要加上双引号,且末尾用分号表示语句结束(这一点很像C语言)。
当然用print也能实现同样的功能,区别在于echo无返回值且速度更快,而print会返回1且不支持输出多条语句。在使用echo和print时,可以加括号也可以不加括号,因为echo和print都不是真正的函数。
关于空格
可以看到,echo前自动加上了一段缩进。
但是需要声明的是,不同于Python,PHP和HTML一样对空格和缩进不敏感。也就是说,PHP解释器会自动删掉语句间的空格和缩进,这些对语句的执行没有影响。但我们还是推荐在编程时使用缩进和空格,因为这可以提高代码可读性。
关于注释
PHP的注释有几种形式,基本是C和Python的大糅合。你可以使用//
或者/**/
来进行注释,也可以使用Python风格的#
来注释,这些注释都不会被执行。
来添加一个动态内容吧
上面我们用PHP实现了计算机界的祖传手艺,但这还是静态的啊,和我们一开始说好的不一样啊。所以我们现在尝试用PHP实现一个动态内容,我们将调用date()函数,来显示当前的时间。
|
小朋友,你是否有很多问号?别急,让我们来逐步探索它背后的真相。
date()函数?!
在这个代码中,我们是这样调用date()函数的date('H:i, jS F Y')
。很明显,我们向函数传递了一个格式化字符串变量。这个变量中,H代表小时,i是分钟,j代表该月的日期,s表示顺序后缀(在这里也就是‘th’),F代表月份,Y则是年份。
如果你发现运行代码给出的时间与现在不一致,大概率是你没有调整时区,如何设置时区,请自行上网询问度娘。
为什么等价?
在PHP中,(.)是连接操作符,通过使用 . ,我们可以连接起不同的语句和变量,将他们一起输出。
怎么还有奇怪的<p>?
学过HTML的小朋友都知道,这个是段落的标志。没错,PHP会自动渲染HTML语言并把它显示在网页上,配合的相当不错。
如何访问表单变量
好了,前面我们提到PHP最常用来做的事就是实现订单,那么我们要如何操作呢?
为了详细解释这个知识点,我不得不花了两分钟去网上找到了这本书的电子版资源……(太痛苦了),然后把表单的HTML代码粘贴如下。
|
最后我们得到了一个小小的可爱的订单。
显然,这个表单的目的是接收用户输入的值,然后将其提交给processorder.php文件(也就是表单的action属性指向的那个)。那么,我们要如何用PHP文件处理接受的值呢?
闲话少说,上代码!
|
打住,这里又出现了新情况,让我们细细道来。
关于奇怪的$
在PHP中,我们一般要在声明的变量前加$,不仅如此,在使用变量时也必须要加上$来告诉服务器这是个变量而非什么奇奇怪怪的东西。除此之外,还需要强调的一点是,PHP是一门弱类型语言,即不需要专门指定变量的类型而交给服务器自动匹配,与之相反的则是C语言的强类型。
关于声明变量,需要注意的是PHP区分变量大小写(但不区分函数的大小写),且变量名只能以下划线和字母开头,由下划线、字母和数字组成。
PHP有以下数据类型:
- String 字符串
- Integer 整数
- Float 浮点数
- Boolean 布尔值
- Array 数组
- Object 对象
- NULL 空
- Resource 资源(一种特殊变量,保存了到外部资源的一个引用,比如MySQL)
关于奇怪的_POST
我们注意到有$_POST['tireqty']
,这东西很厉害,可是要怎么去理解它呢。
我们最开始的设想是用PHP去处理用户提交的表单信息,且其中一个文本框的名字就叫做’tireqty’。显然,这个代码的作用就是访问’tireqty’文本框的内容。_POST
是一个数组,它包含了HTTP通过POST提交的所有数据,也就是文本框的method被设置为POST的情况。除此之外,我们还有_GET
与_REQUEST
。前者用于处理以GET形式提交的数据,而后者则用来处理POST和GET提交的数据总和。一般情况下,数据都可以通过_REQUEST
来获得。
我们把通过这种方法获得的数组称为超级全局数组。
类似的超级全局数组还有以下几种:
- $GLOBALS,可以访问所有全局变量
- $_SERVER,服务器环境变量数组
- $_COOKIE,cookie变量数组
- $_FILES,文件上传相关的变量数组
- $_REQUEST,所有用户输入的变量数组,包括$_POST、$_GET、$_COOKIE所包含的输入内容(但是不包含$FILES)
- $_ENV,环境变量数组
题外话:GET与POST
网页向服务器提交数据通常有两种方法,一种是将数据直接附加在链接后面发送给服务器,即GET。例如https://adam8en.github.io?id=1
就是向网页传递了一个id=1的数据。而POST数据则是将数据单独发出去,具体细节可以用burp suit抓包查看,通常不涉及到复杂的操作时用hackbar就可以很好的使用POST发送数据。
如何回显收到的数据
一般来说,使用我们前文提到的输出hello world的方法就可以回显表单中提交的数据,即:
echo $tireqty.'tires<br />'; |
但是我们并不推荐这种方式,因为我们没有对用户输入的数据进行检验,这可能会导致恶意用户输入恶意语句而引发安全性问题(终于有点安全的知识了),你应该对数据进行过滤,这里我们先使用另一种方法,即调用htmlspecialchars()
函数。
echo htmlspecialchars($tireqty).'tires<br />'; |
这样做也可以获得可视化结果,且更加安全。如果你现在在浏览器中载入这个脚本,正常来说就可以看到回显的内容。
然而如果你真的这么做了而且和我一样都是小白,那么你大概率看到的不是正常的结果,而是PHP文件的源代码……
因为你没有给自己的主机配置服务器,从而网页不知道该如何去解析PHP代码。至于如何去配置服务器……抱歉,你这个问题我还真不知道lol。
变量和字面量
经历过一些不愉快的小插曲后,我们再次回到例题本身。有关echo htmlspecialchars($tireqty).'tires<br />';
这一行代码本身,关于(.)的字符串连接符我们已经讲过,而后面所跟的单引号却又是另一个重点。
在PHP中,双引号和单引号存在区别。其实这一点在C语言中也有类似的情况,在C中单引号常量被视为字符常量,哪怕单引号中包含的字符不止一个;而双引号下的常量则被解释为字符串,末尾默认有一个’\0’占位符存在。而在PHP中,使用双引号会被认为是字符串,此时PHP会解析双引号中的变量,而单引号则会被纯粹的当做是一个字面量,换句话说PHP会直接输出变量名而不会对其进行解析。
例如下面这一串代码
|
可以预见到的是,用双引号包裹的变量将会echo出变量的值,而下面的单引号变量则只会打印出变量名。
在日常使用中,单引号的运行速度比双引号更快,因为单引号不需要经过解析步骤。
声明和使用常量
上面我们介绍了如何定义和给变量赋值,那么我们要如何定义常量呢?
在C语言中,我们一般使用#define
定义常量。比如:
在实际编程中,我们就可以用常量’BIRTHDAY’来代替整数77。
在PHP中,我们仍然需要使用define去定义常量,但是使用方式有所不同,具体形式如下:
define('BIRTHDAY',77); |
这时我们就定义了一个新常量。
除了我们自己定义的常量外,PHP还自己定义了许多常量,我们可以用函数phpinfo()来查看。
注意函数phpinfo(),今后在安全方面我们还会遇到它。
就到这里
好了,通过表单这个例子我们阐述了大部分PHP语言不同于C语言的新特性,接下来我会快速介绍一些PHP和C语言类似的语法知识点,并简单的指出他们之间的细微不同(如果有的话),一些我认为不重要的知识点可能会被我略过(比如转换变量类型的函数),现在让我们快起来吧。
变量作用域
和C语言类似,分为局部作用域、全局作用域、静态作用域、本地作用域,唯一不同的超级全局作用域在前文中已经有过具体介绍。
使用操作符
PHP也可以直接使用四则运算符合取余符号来对变量进行操作。如果对字符串使用操作符,PHP会尝试把字符串转化为数字。比如把带‘e’或‘E’的字符串视为使用了科学计数法,并将其转化为相应的浮点数。除此之外,PHP还会在字符串开头处寻找数字作为字符串的值,否则把字符串视为0。(C语言会直接报错)
字符串操作符
PHP可以直接实现字符串的加法,通过连接符(.)来实现。
$fname="Adam"; |
递减和递增操作符
PHP允许使用诸如++
的形式去递增变量的值,和C相同。
引用操作符
PHP可以通过“&”来引用变量的值。它的用法和效果类似于C语言的指针,但是它实际上并不是指针,只是一个别名。
$a=5; |
如果想要破坏掉变量之间的引用关系,使用unset()函数重置。
比较操作符
除了==
等于操作符外,PHP还有===
恒等操作符。区别在于前者只判断数值是否相等,而后者要求类型也要一致。
比如0和’0’,在==
下是相等的,而===
是不等的。因为前者是整数,后者是字符串。
逻辑操作符
除了和C相同的&& || !
操作符外,PHP还支持类Python的and or
逻辑操作符,但是优先级比前面的略低。PHP还支持xor
异或操作符。
位操作符
这一部分PHP和C完全相同。
其他操作符
操作符new
和->
分别用来初始化类的实例和访问类的成员。看起来有点像C++的分配内存符和C的访问结构指针变量操作符。
PHP和C都支持三元操作符condition ? value if true : value if false
。
错误抑制符
错误抑制符@
可以对任何表达式使用,它将抑制可能产生的警告而使程序不中断运行。例如:
$a=@(50/0); |
执行操作符
执行操作符是一对反向双引号``,它的作用是把反双引号中间的内容当成服务器端的命令来执行。比如在windows端:
$out=`dir c:`; |
这串代码会得到一个目录列表保存在out中,然后在浏览器上显示。
数组操作符
PHP也支持用[]访问数组元素,除此之外还有其他操作符。比如可以用+来连接两个数组。
类型操作符
PHP只有一个类型操作符instanceof,用于判断一个对象是否是指定的类。
其他
剩下的诸如if、while、for、switch1等代码块均与C规则相同,不一一介绍了。唯一注意的地方是除了使用C经典的花括号控制结构外,还可以使用PHP特色的控制方法。
if ($a==0){ |
小结
这一章我们快速的入门了PHP的知识,如果你已经有过C语言的基础,相信这个过程并不难。
再学一点PHP,直到能入门MySQL为止(勿忘初心)。