PHP学习笔记

PHP学习笔记

函数参考手册:https://php.golaravel.com/extensions.membership.html

整体参考手册:https://secure.php.net/manual/zh/langref.php

CodeIgniter参考手册:http://codeigniter.org.cn/user_guide/

安装配置略

PHP弱类型语言,可以放在任何地方,脚本以<?php 开始,以 ?>结束

默认扩展名 .php

$变量名,可以创建变量。数字变量可以通过 $a + $b进行合并。字符串变量通过$a . $b进行合并。

PHP有四种不同的变量作用域

local、global、static、parameter

局部和全局作用域

函数声明外叫全局变量,函数声明内叫局部变量

global关键字可以访问全局变量。

<?php
$x=5;
$y=10;

function myTest()
{
global $x,$y;
$y=$x+$y;
}

myTest();
echo $y; // 输出 15
?>

static函数会保留变量,不会再函数执行完后删除

function myTest()
{
static $x=0;
echo $x;
$x++;
}

myTest();
myTest();
myTest();

echo 可以输出一个或多个字符串,加不加括号无所谓 

基础类型 

String(字符串)、Integer(整型)、Float(浮点)、Boolean(布尔)、Array(数组)、Object(对象)、NULL(空值)

//Array
$cars=array("Volvo","BMW","Toyota");

//Object
class Car
{
    var $color;
    function Car($color="green") {
      $this->color = $color;
    }
    function what_color() {
      return $this->color;
    }
}

常量 

常量是一个简单值的标识符,值在脚本中不能改变,常量不需要使用$修饰符

设置常量使用 define 函数,bool define(string $name,mixed $value,[, bool $case_insensitive = false])

name:必须参数,常量名称

value:必须参数,常量的值

case_insensitive:可选参数,如果设置为TRUE,该常量则大小写不敏感,默认是敏感的。

<?php
// 不区分大小写的常量名
define("GREETING", "欢迎访问 php.cn", true);
echo greeting;  // 输出 "欢迎访问 php.cn"
?>

常量是全局的

定义后,默认是全局变量,可以在整个运行脚本的任何地方使用。

即使常量定义在函数外也可以正常使用常量。

define("GREETING", "欢迎访问 php.cn");

function myTest() {
    echo GREETING;
}
 
myTest();    // 输出 "欢迎访问 php.cn"

并置运算符 (.)

在PHP中只有一个字符串运算符,并置运算符(.)用于把两个字符串值连接起来。

$A = "H";
$B = "I";
echo $A . $B;

strlen() 长度函数

echo strlen($A . $B);

strpos() 查找函数

用于在字符串内查找一个字符或一段指定的文本,如果找到返回字符位置,未找到匹配,返回FALSE

count() 获取数组长度 

关联数组

关联数组是使用您分配给数组的指定的键的数组。

$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
or:
$age['Peter']="35";
$age['Ben']="37";
$age['Joe']="43";

分配后,可以根据指定键来进行获取。

$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
echo "Peter is " . $age['Peter'] . " years old.";

遍历关联数组foreach

遍历并打印关联数组中的所有值,可以使用foreach循环

$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");

foreach($age as $x=>$x_value)
{
echo "Key=" . $x . ", Value=" . $x_value;
echo "<br>";
}

数组排序函数

  • sort() - 对数组进行升序排列

  • rsort() - 对数组进行降序排列

  • asort() - 根据关联数组的值,对数组进行升序排列

  • ksort() - 根据关联数组的键,对数组进行升序排列

  • arsort() - 根据关联数组的值,对数组进行降序排列

  • krsort() - 根据关联数组的键,对数组进行降序排列

<?php
$cars=array("Volvo","BMW","Toyota");
sort($cars);
print_r($cars);
?>

PHP超级全局变量

PHP 超级全局变量列表:

  • $GLOBALS:包含全部变量的全局组合数组,变量的名字就是数组的键

  • $_SERVER:包含服务信息的数组,由Web服务器创建

$_SERVER['PHP_SELF']:当前文件完整路径和文件名

$_SERVER['GATEWAY_INTERFACE']:服务器使用的CGI规范的版本

$_SERVER['SERVER_ADDR']:脚本所在服务器的IP地址

$_SERVER['SERVER_NAME']:脚本所在服务器的主机名

$_SERVER['SERVER_SOFTWARE']:服务器标识字符串,响应请求时的头部信息

$_SERVER['SERVER_PROTOCOL']:请求页面时的通信协议名称和版本

$_SERVER['REQUEST_METHOD']:访问页面使用的请求方法:例如:GET\HEAD\POST\PUT

$_SERVER['REQUEST_TIME']:请求开始时间戳

$_SERVER['QUERY_STRING']:查询字符串,如果有可以通过它进行页面访问

$_SERVER['HTTP_ACCEPT']:请求头的Accept项内容

$_SERVER['HTTP_ACCEPT_CHARSET']:请求头的Accept-Charset项内容

$_SERVER['HTTP_HOST']:请求地址:localhost:81

$_SERVER['HTTP_REFERER']:引导用户代理到当前页的前一页地址

$_SERVER['HTTPS']:如果脚本是通过HTTPS协议被访问,则被设为一个非空的值

$_SERVER['REMOTE_ADDR']:浏览当前页面的用户的IP地址

$_SERVER['REMOTE_HOST']:浏览当前页面的用户的主机名

$_SERVER['REMOTE_PORT']:用户机器上链接到Web服务器所使用的端口号

$_SERVER['SCRIPT_FILENAME']:当前执行脚本的绝对路径

$_SERVER['SERVER_ADMIN']:Apache服务器配置文件中的SERVER_ADMIN参数

$_SERVER['SERVER_PORT']:Web服务器使用的端口,默认为80

$_SERVER['SERVER_SIGNATURE']:包含服务器版本和虚拟主机名的字符串

$_SERVER['PATH_TRANSLATED']:当前脚本所在的文件系统的基本路径

$_SERVER['SCRIPT_NAME']:包含当前脚本的路径,在页面需要指向自己的时候用

$_SERVER['SCRIPT_URI']:指定要访问的页面,例如"/"

  • $_REQUEST:用于收集HTML表单提交的数据

<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
Name: <input type="text" name="fname">
<input type="submit">
</form>

<?php 
$name = $_REQUEST['fname']; 
echo $name; 
?>
  • $_POST:接收POST请求数据,

    $_POST['fname']; 
  • $_GET:接收URL中发送的数据,

     $_GET['subject']
  • $_FILES

  • $_ENV

  • $_COOKIE

  • $_SESSION

PHP函数

PHP內建函数

  • Array 函数:运行访问并操作数组,支持简单的数组和多维数组

  • Calendar 函数:日历扩展包含了简化不同日历格式之间的转换函数

  • cURL 函数:允许你与各种的服务器使用各种类型的协议进行连接和通讯

  • Date 函数:允许在运行服务器上获取时间

  • Directory 函数:允许获取关于目录及其内容的信息

  • Error 函数:Error和Loggin函数允许对错误进行处理和记录

  • Filesystem 函数:允许您访问和操作文件系统

  • Filter 函数:过滤器用于对来自非安全来源的数据(比如用户输入)进行验证和过滤

  • FTP 函数:通过文件传输协议(FTP)提供文件服务器的客户端访问

  • HTTP 函数:允许您在其他输出被发送之前,对由Web服务器发送的浏览器的信息进行操作

  • LibXML 函数:与SimpleXML、XSLT以及DOM函数一起使用

  • Mail 函数:允许您从脚本中直接发送电子邮件

  • Math 函数:能处理integer和float范围内的值

  • Misc 函数:把不属于其他类别的函数归纳到杂项函数类别

  • MySQLi 函数:允许访问MySql数据库服务器

  • SimpleXML 函数:提供一种获取XML元素的名称和文本的简单方式,转换XML文档到SimpleXMLElement对象

  • String 函数:操作字符串的相关函数

  • XML Parser 函数:允许解析XML文档

  • Zip 函数:允许读取压缩文件

  • 杂项函数:把不属于其他类别的函数归纳到这个页面

创建函数

function functionName()
{
要执行的代码;
}

PHP魔术变量

__LINE__:返回在文件中的行号

__FILE__:返回文件的完整路径和文件名

__DIR__:文件所在的目录,如果用在包括文件中,则返回被包括的文件所在目录

__FUNCTION__:返回该函数被定义时的名字,如果不在函数内则返回NULL

__CLASS__:常量返回该类被定义时的名字(区分大小写),调用类里面的函数需要->的方式

$class = new FunctionClass();
$class->FunctionName();

class FunctionClass
{
    function FunctionName()
    {
        echo '类名为:' . __CLASS__ . "<br>";
        echo '函数名为:' . __FUNCTION__;
    }
}

__TRAIT__:包括其被声明的作用区域,从基类继承的成员被插入SayWorld,会先执行父类再执行trait覆盖的方法

<?php
class Base {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait SayWorld {
    public function sayHello() {
        parent::sayHello();
        echo 'World!';
    }
}

class MyHelloWorld extends Base {
    use SayWorld;
}

$o = new MyHelloWorld();
$o->sayHello();
?>

__METHOD__:返回该方法被定义时的名字

<?php
function test() {
echo  '函数名为:' . __METHOD__ ;
}
test();
?>

__NAMESPACE__:当前命名空间的名称

<?php
namespace MyProject;
echo '命名空间为:"', __NAMESPACE__, '"'; // 输出 "MyProject"
?>

定义命名空间:namespace MyProject; 

定义子命名空间:namespace MyProject\Sub\Level;

导入命名空间:use blah\blah

导入命名空间并赋别名:use My\Full\Classname as Another;

全局空间:在名称前加上前缀“\”,\fopen(...)表示函数名,是全局空间中的名称如果没有定义命名空间则这样使用

PHP定义类

<?php
class phpClass {
  var $var1;
  var $var2 = "constant string";
  
  function myfunc ($arg1, $arg2) {
     [..]
  }
  [..]
}
?>

解析如下:

  • 类使用 class 关键字后加上类名定义。

  • 类名后的一对大括号({})内可以定义变量和方法。

  • 类的变量使用 var 来声明, 变量也可以初始化值。

  • 函数定义类似 PHP 函数的定义,但函数只能通过该类及其实例化的对象访问。

实例

<?php
class Site {
  /* 成员变量 */
  var $url;
  var $title;
  
  /* 成员函数 */
  function setUrl($par){
     $this->url = $par;
  }
  
  function getUrl(){
     echo $this->url . PHP_EOL;
  }
  
  function setTitle($par){
     $this->title = $par;
  }
  
  function getTitle(){
     echo $this->title . PHP_EOL;
  }
}
?>

变量$this代表自身的对象,PHP_EOL代表换行符

构造函数:_construct()

function __construct( $par1, $par2 ) {
   $this->url = $par1;
   $this->title = $par2;
}

析构函数:_destruct() 

class MyDestructableClass {
   function __construct() {
       print "构造函数\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "销毁 " . $this->name . "\n";
   }
}

$obj = new MyDestructableClass();

继承:extends 

方法重写:可以直接在子类定义相同名称的函数来重写父类方法

访问控制:PHP对属性、方法的访问控制,是通过关键字public\protected\private来实现的 。如果用var定义,视为公有

接口:interface定义,使用implements继承,可以使用逗号继承多个接口

类中保持不变的称为常量:const constant = "常量值",读取常量值使用"::":MyClass::constant 

抽象类:abstract定义,使用extends继承

静态类:static定义可以不实例化类直接访问 

class Foo {
  public static $my_static = 'foo';
  
  public function staticValue() {
     return self::$my_static;
  }
}

print Foo::$my_static . PHP_EOL;
$foo = new Foo();

print $foo->staticValue() . PHP_EOL;

密封类:final,无法覆盖该方法 

class BaseClass {
   public function test() {
       echo "BaseClass::test() called" . PHP_EOL;
   }
   
   final public function moreTesting() {
       echo "BaseClass::moreTesting() called"  . PHP_EOL;
   }
}

调用父类构造: parent::__construct();

isset()

验证变量是否进行过设置。

变量不存在返回FALSE

变量存在且值为NULL,返回FALSE

变量存在且值不为NULL,返回TRUE

empty()

检查一个变量是否为空。

若变量不存在则返回TRUE

若变量存在且其值为""、0、"0"、NULL、FALSE、array()则返回TRUE

若变量存在且其值不为上面数据,则返回FALSE

PHP表单

PHP中的$_GET和$_POST变量用于检索表单中的信息,比如用户输入

有一点很重要的事情,当处理HTML表单时,PHP能把来自HTML页面中的表单元素自动变成可供PHP脚本使用

实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="welcome.php" method="post">
        <span>名字:</span><input type="text" name="txtName" />
        <span>年龄:</span><input type="number" name="txtOld" />
        <input type="submit" value="提交" />
    </form>
</body>
</html>



echo "欢迎" . $_POST["txtName"] . "年龄" . $_POST["txtOld"];

表单验证

可以通过$_SERVER["REQUEST_METHOD"]来判断获取请求类型,然后对请求进行验证

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>php.cn</title>
    <style>
        .error {color: #FF0000;}
    </style>
</head>
<body>

<?php
// 定义变量并默认设置为空值
$nameErr = $emailErr = $genderErr = $websiteErr = "";
$name = $email = $gender = $comment = $website = "";

if ($_SERVER["REQUEST_METHOD"] == "POST")
{
    if (empty($_POST["name"]))
    {
        $nameErr = "名字是必需的";
    }
    else
    {
        $name = test_input($_POST["name"]);
        // 检测名字是否只包含字母跟空格
        if (!preg_match("/^[a-zA-Z ]*$/",$name))
        {
            $nameErr = "只允许字母和空格";
        }
    }

    if (empty($_POST["email"]))
    {
        $emailErr = "邮箱是必需的";
    }
    else
    {
        $email = test_input($_POST["email"]);
        // 检测邮箱是否合法
        if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email))
        {
            $emailErr = "非法邮箱格式";
        }
    }

    if (empty($_POST["website"]))
    {
        $website = "";
    }
    else
    {
        $website = test_input($_POST["website"]);
        // 检测 URL 地址是否合法
        if (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i",$website))
        {
            $websiteErr = "非法的 URL 的地址";
        }
    }

    if (empty($_POST["comment"]))
    {
        $comment = "";
    }
    else
    {
        $comment = test_input($_POST["comment"]);
    }

    if (empty($_POST["gender"]))
    {
        $genderErr = "性别是必需的";
    }
    else
    {
        $gender = test_input($_POST["gender"]);
    }
}

function test_input($data)
{
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}
?>

<h2>PHP 表单验证实例</h2>
<p><span class="error">* 必需字段。</span></p>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
    名字: <input type="text" name="name" value="<?php echo $name;?>">
    <span class="error">* <?php echo $nameErr;?></span>
    <br><br>
    E-mail: <input type="text" name="email" value="<?php echo $email;?>">
    <span class="error">* <?php echo $emailErr;?></span>
    <br><br>
    网址: <input type="text" name="website" value="<?php echo $website;?>">
    <span class="error"><?php echo $websiteErr;?></span>
    <br><br>
    备注: <textarea name="comment" rows="5" cols="40"><?php echo $comment;?></textarea>
    <br><br>
    性别:
    <input type="radio" name="gender" <?php if (isset($gender) && $gender=="female") echo "checked";?>  value="female"><input type="radio" name="gender" <?php if (isset($gender) && $gender=="male") echo "checked";?>  value="male"><span class="error">* <?php echo $genderErr;?></span>
    <br><br>
    <input type="submit" name="submit" value="Submit">
</form>

<?php
echo "<h2>您输入的内容是:</h2>";
echo $name;
echo "<br>";
echo $email;
echo "<br>";
echo $website;
echo "<br>";
echo $comment;
echo "<br>";
echo $gender;
?>

</body>
</html>

$_SERVER["PHP_SELF"]会存在SQL注入的风险,可以通过htmlspecialchars()函数来避免被利用

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

多维数组:包含一个或多个数组的数组

<?php
// 二维数组:
$cars = array
(
    array("Volvo",100,96),
    array("BMW",60,59),
    array("Toyota",110,100)
);
print_r($cars); 

date()格式化日期

date函数的第一个必需参数format规定了如何格式化日期/时间

可用字符:d-代表月中的天01-31、m-代表月01-12、y代表年(四位数) 

echo date("Y/m/d"); //2016/05/11
echo date("Y.m.d"); //2016.05.11
echo date("Y-m-d"); //2016-05-11

include和require语句

可以在服务执行php之前在该文件插入一个文件的内容。

include和require除了处理错误的方式不一样,其他方面都是相同的

  • include:生成一个警告(E_WARNING),在错误发生脚本会继续执行
  • require:生成一个致命错误(E_COMPILE_ERROR),在错误发生脚本后会停止执行

因此,如果希望不管丢没丢失都继续执行,选择include,否则请始终使用require,有助于提高应用程序的完整性和安全性

语法

include 'filename';

或者

require 'filename';

fopen() 打开文件

此函数的第一个参数是打开文件的名称,第二个参数规定了使用哪种模式来打开文件

<?php
$file=fopen("welcome.txt","r");
?>

完整模式如下

模式描述
r只读。在文件的开头开始。
r+读/写。在文件的开头开始。
w只写。打开并清空文件的内容;如果文件不存在,则创建新文件。
w+读/写。打开并清空文件的内容;如果文件不存在,则创建新文件。
a追加。打开并向文件末尾进行写操作,如果文件不存在,则创建新文件。
a+读/追加。通过向文件末尾写内容,来保持文件内容。
x只写。创建新文件。如果文件已存在,则返回 FALSE 和一个错误。
x+读/写。创建新文件。如果文件已存在,则返回 FALSE 和一个错误。

 

 

 

 

 

 

 

 

 

异常抛出

使用exit可以在不能打开文件时,抛出一段消息

$file=fopen("welcome.txt","r") or exit("Unable to open file!");

关闭文件

<?php
$file = fopen("test.txt","r");
fclose($file);
?>

检测文件末尾(EOF) 

feof()函数可以检测是否已到达文件末尾(EOF)

在循环遍历未知长度的数据时,feof()函数很有用。

在w、a、x模式下,您无法读取打开的文件!

if (feof($file)) echo "文件结尾";

逐行读取文件

fgets() 函数用于从文件中逐行读取文件,在调用该函数后,文件指针会移动到下一行

$file = fopen("welcome.txt", "r") or exit("无法打开文件!");
// 读取文件每一行,直到文件结尾
while(!feof($file))
 {
    echo fgets($file). "<br>";
 }
fclose($file);

逐字符读取文件

fgetc() 函数用于从文件中逐字符的读取文件,调用该函数后,文件指针会移动到下一个字符

$file=fopen("welcome.txt","r") or exit("无法打开文件!");
while (!feof($file))
 {
    echo fgetc($file);
 }
fclose($file);

PHP文件上传

首先创建一个前台页面HTML页面用来接收表单。

<form action="upload_file.php" method="post" enctype="multipart/form-data">
    <label for="file">文件名:</label>
    <input type="file" name="file" id="file" />
    <input type="submit" name="submit" value="提交" />
</form>

将以上代码保存到form.html文件中,需要注意的点如下:

<form>标签的enctype属性规定了在提交表单时要使用哪种内容类型,在表单需要二进制数据时(文件内容)

请使用"multipart/form-data"

<input>标签的type="file"属性规定了应该把输入作为文件来处理,当浏览器中预览时,会看到输入框旁边有一个浏览按钮。

创建上传脚本

<?php
//判断是否有上传错误代码
if ($_FILES["file"]["error"] > 0)
    echo "错误:" . $_FILES["file"]["error"] . "<br>";
else {
    echo "上传文件名:" . $_FILES["file"]["name"] . "<br>";
    echo "文件类型:" . $_FILES["file"]["type"] . "<br>";
    echo "文件大小:" . $_FILES["file"]["size"] . "<br>";
    echo "文件临时存储位置:" . $_FILES["file"]["tmp_name"] . "<br>";
}

通过使用PHP的全局数组$_FILES,可以从客户计算机向远程服务器上传文件。

第一个参数是表单的input name,第二个下标可以是如下内容

  • $_FILES["file"]["name"] - 上传文件的名称

  • $_FILES["file"]["type"] - 上传文件的类型

  • $_FILES["file"]["size"] - 上传文件的大小,以字节计

  • $_FILES["file"]["tmp_name"] - 存储在服务器的文件的临时副本的名称

  • $_FILES["file"]["error"] - 由文件上传导致的错误代码

上传限制

显示用户只能上传txt文件,大小必须小于200kb

<?php
$allowedExts = array("txt");
$temp = explode(".",$_FILES["file"]["name"]);
$extension = end($temp);
if($_FILES["file"]["size"] > 204800 || !in_array($extension,$allowedExts))
    return;
//判断是否有上传错误代码
if ($_FILES["file"]["error"] > 0)
    echo "错误:" . $_FILES["file"]["error"] . "<br>";
else {
    echo "上传文件名:" . $_FILES["file"]["name"] . "<br>";
    echo "文件类型:" . $_FILES["file"]["type"] . "<br>";
    echo "文件大小:" . $_FILES["file"]["size"] . "<br>";
    echo "文件临时存储位置:" . $_FILES["file"]["tmp_name"] . "<br>";
}

保存上传文件 

我们需要把文件拷贝到另一个位置

<?php
$allowedExts = array("txt");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);
if ($_FILES["file"]["size"] > 204800 || !in_array($extension, $allowedExts)) {
    echo "错误:文件类型不正确";
    return;
}
//判断是否有上传错误代码
if ($_FILES["file"]["error"] > 0) {
    echo "错误:" . $_FILES["file"]["error"] . "<br>";
} else {
    echo "上传文件名:" . $_FILES["file"]["name"] . "<br>";
    echo "文件类型:" . $_FILES["file"]["type"] . "<br>";
    echo "文件大小:" . $_FILES["file"]["size"] . "<br>";
    echo "文件临时存储位置:" . $_FILES["file"]["tmp_name"] . "<br>";
}
if (file_exists("tem/" . $_FILES["file"]["name"])) {
    echo $_FILES["file"]["name"] . " 文件已经存在";
} else {
    move_uploaded_file($_FILES["file"]["tmp_name"], "tem/" . $_FILES["file"]["name"]);
    echo "文件保存成功";
}

创建Cookie

setcookie() 函数用于设置 cookie

setcookie(name, value, expire, path, domain);

比如创建一个名为"user"的cookie,并为它赋值"php",在一个小时后过期。

setcookie("user","php",time()+60*60)

取回Cookie

$_COOKIE变量用于取回cookie的值,print_r可查看所有Cookie

<?php
// 输出 cookie 值
echo $_COOKIE["user"];

// 查看所有 cookie
print_r($_COOKIE);
?>

验证Cookie

使用isset()函数可以确认是否已设置cookie

if (isset($_COOKIE["user"]))
    echo "欢迎 " . $_COOKIE["user"] . "!<br>";
else
    echo "普通访客!<br>";

删除Cookie

// 设置 cookie 过期时间为过去 1 小时
setcookie("user", "", time()-3600);

Session

session_start()函数必须位于<html>标签之前,会向服务器注册用户的会话,以便保存用户信息

<?php session_start(); ?>

<html>
<body>

</body>
</html>

存储Session变量

session_start();
// 存储 session 数据
$_SESSION['views']=1;

echo "浏览量:". $_SESSION['views'];

检测Session变量

if(isset($_SESSION['views']))
{
$_SESSION['views']=$_SESSION['views']+1;
}

销毁Session变量

session_start();
if(isset($_SESSION['views']))
{
unset($_SESSION['views']);
}

Email

<?php
$to = "someone@example.com";         // 邮件接收者
$subject = "参数邮件";                // 邮件标题
$message = "Hello! 这是邮件的内容。";  // 邮件正文
$from = "someonelse@example.com";   // 邮件发送者
$headers = "From:" . $from;         // 头部信息设置
mail($to,$subject,$message,$headers);
echo "邮件已发送";
?>

防止E-mail注入

<html>
<head>
    <meta charset="utf-8">
    <title>php中文网(php.cn)</title>
</head>
<body>
<?php
function spamcheck($field)
{
// filter_var() 过滤 e-mail
// 使用 FILTER_SANITIZE_EMAIL
    $field = filter_var($field, FILTER_SANITIZE_EMAIL);

//filter_var() 过滤 e-mail
// 使用 FILTER_VALIDATE_EMAIL
    if (filter_var($field, FILTER_VALIDATE_EMAIL)) {
        return TRUE;
    } else {
        return FALSE;
    }
}

if (isset($_REQUEST['email'])) {
// 如果接收到邮箱参数则发送邮件

// 判断邮箱是否合法
    $mailcheck = spamcheck($_REQUEST['email']);
    if ($mailcheck == FALSE) {
        echo "非法输入";
    } else {
// 发送邮件
        $email = $_REQUEST['email'];
        $subject = $_REQUEST['subject'];
        $message = $_REQUEST['message'];
        mail("someone@example.com", "Subject: $subject",
            $message, "From: $email");
        echo "Thank you for using our mail form";
    }
} else {
// 如果没有邮箱参数则显示表单
    echo "<form method='post' action='mailform.php'>
Email: <input name='email' type='text'><br>
Subject: <input name='subject' type='text'><br>
Message:<br>
<textarea name='message' rows='15' cols='40'>
</textarea><br>
<input type='submit'>
</form>";
}
?>

</body>
</html>

在上面代码中,使用了PHP过滤器来对输入进行验证:

FILTER_SANITIZE_EMAIL过滤器从字符串中删除电子邮件的非法字符

FILTER_VALIDATE_EMAIL过滤器验证电子邮件地址的值

PHP Error

在php中,默认的错误处理,就是把错误信息发送到浏览器,这条消息带有文件名、行号以及描述错误的消息

die()函数

可以重定义错误信息,类似于new Error

<?php
if(!file_exists("welcome.txt"))
{
die("文件不存在");
}
else
{
$file=fopen("welcome.txt","r");
}
?>

Exception

Try、catch、throw、new Excetption。与C#一样

过滤器

如果需要过滤变量,请使用下面的过滤器函数之一

函数描述PHP
filter_has_var()检查是否存在指定输入类型的变量。5
filter_id()返回指定过滤器的 ID 号。5
filter_input()从脚本外部获取输入,并进行过滤。5
filter_input_array()从脚本外部获取多项输入,并进行过滤。5
filter_list()返回包含所有得到支持的过滤器的一个数组。5
filter_var_array()获取多项变量,并进行过滤。5
filter_var()获取一个变量,并进行过滤。

 

 

 

 

 

 

 

 

参考手册:http://www.w3school.com.cn/php/php_ref_filter.asp

<!DOCTYPE html>
<html>
<body>
<?php
    $message = "";
    if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $int = $_POST["txtNumber"];
    if (!filter_var($int, FILTER_VALIDATE_INT)) {
        $message = "不是合法的整数";
    } else {
        $message = "是合法的整数";
    }
}
?>
<h1>My first PHP page</h1>
<form action="index.php" method="post">
    <input type="text" name="txtNumber" />
    <input type="submit" value="验证" />
    <label style="color:red"><?php echo $message; ?></label>
</form>

</body>
</html>

验证输入

现在email变量通过Get类型,传入到php页面

<?php
if(!filter_has_var(INPUT_GET, "email"))
{
echo("没有 email 参数");
}
else
{
if (!filter_input(INPUT_GET, "email", FILTER_VALIDATE_EMAIL))
{
echo "不是一个合法的 E-Mail";
}
else
{
echo "是一个合法的 E-Mail";
}
}
?>

过滤多个输入 

$filters = array
(
    "name" => array
    (
        "filter" => FILTER_SANITIZE_STRING
    ),
    "age" => array
    (
        "filter" => FILTER_VALIDATE_INT,
        "options" => array
        (
            "min_range" => 1,
            "max_range" => 120
        )
    ),
    "email" => FILTER_VALIDATE_EMAIL
);

$result = filter_input_array(INPUT_GET, $filters);

if (!$result["age"]) {
    echo("年龄必须在 1 到 120 之间。<br>");
} elseif (!$result["email"]) {
    echo("E-Mail 不合法<br>");
} else {
    echo("输入正确");
}
?>

JSON

json_enode:对变量进行JSON编码

//数组转换
$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
echo json_encode($arr); //{"a":1,"b":2,"c":3,"d":4,"e":5}

//对象转换
class Emp {
    public $name = "sachin";
public $hobbies = "sports";
}
$e = new Emp();
echo json_encode($e); //{"name":"sachin","hobbies":"sports"}

json_decode:对JSON格式的字符串进行解码,转换为PHP变量

语法:mixed json_decode ($json [,$assoc = false [, $depth = 512 [, $options = 0 ]]])

参数:

  • json: 待解码的 JSON 字符串,必须是 UTF-8 编码数据

  • assoc: 当该参数为 TRUE 时,将返回数组,FALSE 时返回对象。

  • depth: 整数类型的参数,它指定递归深度

  • options: 二进制掩码,目前只支持 JSON_BIGINT_AS_STRING 。

<?php
   $json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';

   var_dump(json_decode($json));
   var_dump(json_decode($json, true));
?>

json_last_error:返回最后发生的错误

MySql链接

建议使用以下两种方式链接MySql:MySqlLi extension / PDO

PDO应用在12种不同数据库中,MySQLi只针对MySql数据库

如果需要多数据库切换,使用PDO,否则使用MySQLi

链接MySql

<?php
$serverName = "localhost";
$userName = "root";
$passWord = "1111aaaa";
$conn = new mysqli($serverName, $userName, $passWord, "ibo");
if ($conn->connect_error) {
    dir("链接失败:" . $conn->connect_error);
}
echo "链接成功";
?>

关闭链接 

$conn->close() 

执行SQL

$serverName = "localhost";
$userName = "root";
$passWord = "1111aaaa";
$conn = mysqli_connect($serverName, $userName, $passWord, "ibo");
if (!$conn) {
dir("链接失败:" . mysqli_connect_error());
}
echo "链接成功" . PHP_EOL;
$sql = "insert into ibo.act_id_info(ID_) values(1)";
if(mysqli_query($conn,$sql)){
echo "执行成功" . PHP_EOL;
}else{
echo "执行失败" . mysqli_error($conn);
}
mysqli_close($conn);

读取数据

<?php
$serverName = "localhost";
$userName = "root";
$passWord = "1111aaaa";
$conn = mysqli_connect($serverName, $userName, $passWord, "ibo");
if (!$conn) {
    dir("链接失败:" . mysqli_connect_error());
}
echo "链接成功" . PHP_EOL;
$sql = "select * from ibo.act_id_info;";
$result = mysqli_query($conn, $sql);
foreach ($result as $item) {
    echo "<br>" . $item["ID_"];
}
mysqli_close($conn);
?>

SimpleXML

提供了一种获取XML元素的名称和文本的简单方式

//加载XML
$xmlDoc = simplexml_load_file("node.xml");

//输出所有XML
print_r($xmlDoc);

//输出每个项
echo "<br>" . $xmlDoc->to . PHP_EOL . "<br>";

//输出全部项
foreach ($xmlDoc->children() as $child) {
    echo $child->getName() . "-" . $child . PHP_EOL;
}

http://www.php.cn/php/php-file-upload.html

CodeIgniter

CodeIgniter是一套PHP网站开发使用的应用框架和工具包,目标是让你能够快速的开发

提供了日常任务中所需的大量类库,以及简单的接口和逻辑结构。

安装

解压安装包

将CodeIgniter文件上传到服务器

打开application/config/config.php文件设置根URLhttp://localhost:81

打开application/config/database.php文件设置数据库参数

如果想隐藏文件位置,可以修改system、application目录路径,位置在index.php中的$system_path、$application_folder两个变量

CodeIgnter默认在每个目录下都包含.htaccess文件,阻止直接访问。

通过ENVIRONMENT常量可以禁用PHP错误报告以及开发环境使用的功能

CodeIgniter概览

一个应用程序框架

为php开发人员提供的一套应用程序工具包,提供了丰富的类库、提供简单的接口和逻辑来调用这些类库。

免费的

CodeIgniter通过MIT开源许可协议授权

轻量级的

核心系统只需要一些非常小的库,库都是根据请求动态加载,核心系统非常轻快

快速的

真正的快速,很难找到一个比CodeIgniter性能更好的框架

使用MVC架构

很好的讲逻辑层和表示层分离,特别对于模板问你件的项目来说更好,减少代码量

生成干净的URL

生成URL非常干净,对搜索引擎友好

功能强大

拥有全面的类库,能满足大多数Web开发任务的需要

可扩展的

非常简单的通过你自己的类库和辅助函数来扩展,可以通过类扩展或系统钩子来实现

不需要模板引擎

自带了一个非常简单的可选模板解析器,但是不推荐使用,因为会影响性能。

拥有全面的文档

拥有友好的用户社区

应用程序流程图

index.php作为前端控制器,初始化运行CodeIgniter所需的基本资源

Routing检查HTTP请求,已确认如何处理请求

如果存在缓存文件,将直接输出到浏览器中,不用走下面的正常流程

加载应用呢程序控制器之前,对HTTP请求以及任何用户提交的数据进行安全检查。

控制器加载模型、核心类库、辅助函数以及其他所有处理请求所需的资源

渲染函数并发送到浏览器,如果开启缓存,视图被先缓存起来用于后续的请求

MVC

CodeIgniter的MVC与传统不一样

M模型代表你的数据结构,包含帮助你对数据库进行增删改查的方法(也就是DLL和DAL)

V视图展示给用户的信息,一个视图通常就是一个网页

C控制器模型视图以及其他任何处理HTTP请求所必须的资源之间的中介

URL

默认情况你的URL会包含index.php文件,如果你的Apache服务器启用了mod_rewrite,可以通过一个

.htaccess文件再加上一些简单的规则就可以移出index.php了,下面是这个文件的一个例子,其中使用了否定条件,来排除不需要重定向的系项目

//.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]

上面例子中除了已存在的目录,其他HTTP请求都会经过你的index.php文件

而往往仅排除index.php还不够,我们还需要排除.txt或者images

RewriteCond $1 !^(index\.php|images|robots\.txt)

添加URL后缀

你可以指定一个后缀,CodeIgniter生成URL时会自动添加上它。

需要修改conig/config.php文件中的

$config['url_suffix'] = '';

控制器

一个控制器就是一个类文件,是一种能够和URI关联在一起的方式来命名的

控制器文件名必须大写字母开头,例如:Blog.php

类名必须以大写字母开头,例如:class Blog extends CI_Controller

控制器的类必须要继承父控制器 CI_Controller

方法

如果URI的第二段为空时会默认调用index(),如果不为空则调用该方法

通过URI分段向你的方法传递参数,如果URI多于两个段,多余的段将作为参数传递到你的方法中

假设你的URI是:localhost/products/shoes/sandals/123

那么就会收到第三段和第四段的两个参数

class Products extends CI_Controller {

    public function shoes($sandals, $id)
    {
        echo $sandals;
        echo $id;
    }
}

默认控制器

CodeIgniter可以设置一个默认的控制器,当URI没有分段参数时被加载

$route['default_controller'] = 'blog';

其中Blog是你想加载的控制器类名,如果你现在通过不带任何参数的地址,你就看到这个信息

重映射方法

URI的第二段通常决定控制器的那个方法被调用,CodeIgniter允许你使用_remap()方法来重写规则

如果你的控制器包含一个_remap()方法,那么无论URI中包含什么参数都会调用该方法

它允许你定义你自己的路由规则,重写默认的使用URI中的分段来决定调用那个方法

public function _remap($method, $params = array())
{
    $method = 'process_'.$method;
    if (method_exists($this, $method))
    {
        return call_user_func_array(array($this, $method), $params);
    }
    show_404();
}

处理输出

CodeIgniter有一个输出类可以自动将最终数据发送到你的浏览器

允许你向你的控制器添加一个_output方法,可以接受最终的输出数据

如果你的控制器含有一个_output方法,输出类将会调用该方法来显示数据,而不是直接显示

public function _output($output)
{
    echo $output;
}

私有方法

使用provate或者protected就不会被URI访问到

构造函数 

如果你打算在你的控制器中使用构造函数,必须将下面代码放在里面

你的构造函数将会覆盖父类的构造函数,所以我们要手工调用它

class Blog extends CI_Controller {
    public function __construct()
    {
        parent::__construct();
        // Your own constructor code
    }
}

视图

一个视图其实就是一个Web页面或者页面的一部分,向页头、页脚、侧边等

实际上视图可以很灵活的钳在另一个视图里,然后这个视图在镶嵌等等

如果想用这种层次结构的话,可以这样做。视图不能直接被调用,必须通过控制器来加载。

加载视图

$this->load->view('name');

name参数为你的视图文件名,如果视图放在子目录中需要添加"目录名称/文件名"。

文件的扩展名.php可以省略,除非使用了其他的扩展名

加载多个视图

可以智能的处理在控制器中多次调用$this->load->view()方法。

如果出现了多次调用,视图会被合并到一起。

如果你希望有一个页头、一个菜单、一个内容、一个页脚。可以写成如下形式

public function index()
    {
        $data['page_title'] = 'Your title';
        $this->load->view('header');
        $this->load->view('menu');
        $this->load->view('content', $data);
        $this->load->view('footer');
    }

添加动态数据 

通过视图加载方法的第二个参数可以动态传入数据,参数可以是数组或者对象

$data = array(
    'title' => 'My Title',
    'heading' => 'My Heading',
    'message' => 'My Message'
);

$this->load->view('blogview', $data);
------------------------------------------------
$data = new Someclass();
$this->load->view('blogview', $data);

当你使用对象时,对象中的变量会转换为数组元素

那么在视图中就可以直接使用

<html>
<head>
    <title><?php echo $title;?></title>
</head>
<body>
    <h1><?php echo $heading;?></h1>
</body>
</html>

将视图作为数据返回

加载视图方法有一个可选的第三个参数可以让你修改它的默认行为

让视图作为字符串返回而不是显示到浏览器中,这在你想对视图数据做有些处理时很有用哦个。

如果你将参数设置为TRUE,该方法返回字符串。默认为FALSE,视图将显示到浏览器中

如果你需要返回的数据,将它赋值给一个变量

$string = $this->load->view('myfile', '', TRUE);

模型

模型是专门用来和数据库打交道的PHP类,用于存放SQL操作类。

class Blog_model extends CI_Model {
    public $title;
    public $content;
    public $date;

    public function get_last_ten_entries()
    {
        $query = $this->db->get('entries', 10);
        return $query->result();
    }

    public function insert_entry()
    {
        $this->title    = $_POST['title']; // please read the below note
        $this->content  = $_POST['content'];
        $this->date = time();

        $this->db->insert('entries', $this);
    }

    public function update_entry()
    {
        $this->title    = $_POST['title'];
        $this->content  = $_POST['content'];
        $this->date = time();

        $this->db->update('entries', $this, array('id' => $_POST['id']));
    }
}

剖析模型

模型类位于你的application/models目录下,如果你愿意也可以创建子目录

class Model_name extends CI_Model {
    public function __construct()
    {
        parent::__construct();
        // Your own constructor code
    }
}

其中Model_name是类的名字,类名的第一个字母必须大写,其余小写。确保你的类继承CI_Model基类

加载模型

你的模型一般会在你的控制器方法中加载并调用,可以使用下面的方法来加载模型

$this->load->model('model_name');

如果你的模型位于一个子目录下,那么加载时要带上你的模型所在目录的相对路径。

例如:$this->load->model('blog/queries')

加载之后,就可以通过一个和你的类同名的对象访问模型中的方法了

$this->load->model('model_name');
$this->model_name->method();

如果你想将你的模型对象赋值给一个不同名字的对象,你可以使用$this->load->model()方法的第二个参数

$this->load->model('model_name', 'foobar');
$this->foobar->method();

模型自动加载 

如果你有一个模型需要在整个应用程序中使用,你可以让CodeIgniter在系统初始化时自动加载它

打开application/config/autoload.php并将该模型添加到autoload数组中

链接数据库

当模型加载后,并不会自动去连接你的数据库,有三种办法可以链接数据库

1. 你可以在控制器或模型中使用标准的数据库方法链接数据库

$this->load->database();

2.你可以设置第三个参数为TRUE让模型在加载时自动链接数据库,会使用你的数据库配置文件中的配置

$this->load->model('model_name', '', TRUE);

3.你还可以通过第三个参数传一个数据库链接配置

$config['hostname'] = 'localhost';
$config['username'] = 'myusername';
$config['password'] = 'mypassword';
$config['database'] = 'mydatabase';
$config['dbdriver'] = 'mysqli';
$config['dbprefix'] = '';
$config['pconnect'] = FALSE;
$config['db_debug'] = TRUE;

$this->load->model('model_name', '', $config);

辅助函数

帮助我们完成特定任务的函数,每个辅助函数文件都是某一类函数的集合。

辅助函数没有使用面向对象的方式来实现的,只是简单的过程式函数,每个函数处理一个特定的任务

不依赖与其他函数。

CodeIgniter默认不会自己加载函数,所以使用函数的第一步就是加载它。

一旦加载,就可以在你的控制器和视图中全局访问了。

辅助函数位于system/helpers或application/helpers目录下

加载辅助函数

$this->load->helper('name')

name参数为辅助函数的文件名,去掉.php文件后缀以及_helper部分

例如:要加载URL辅助函数,它的文件名叫做url_helper.php,你可以这样加载它

$this->load->helper('url');

辅助函数可以在你的控制器方法的任何地方加载,只要确保在使用之前加载它就可以了。

你可以在你的控制器的构造函数中加载它,这样就可以在该控制器的任何方法中使用

也可以在某个需要它的函数中单独加载它

加载多个辅助函数

如果需要加载多个辅助函数,可以使用一个数组

$this->load->helper( array('helper1', 'helper2', 'helper3') );

自动加载辅助函数

设置application/config/autolaod.php

使用辅助函数

一旦辅助函数被加载,你就可以像使用标准的PHP函数一样使用它们

<?php echo anchor('blog/comments', 'Click Here');?>

扩展辅助函数

为了扩展辅助函数,需要在application/helper/目录下新建一个文件,文件名和已存在的辅助函数一样

但是要加载MY_前缀。如果只是想往现有类中添加一些功能,这种时候最好的办法就是扩展类

例如:要扩展数组辅助函数,需要创建application/helpers/MY_array_helper.php然后重写函数

// any_in_array() is not in the Array Helper, so it defines a new function
function any_in_array($needle, $haystack)
{
    $needle = is_array($needle) ? $needle : array($needle);

    foreach ($needle as $item)
    {
        if (in_array($item, $haystack))
        {
            return TRUE;
        }
        }

    return FALSE;
}

// random_element() is included in Array Helper, so it overrides the native function
function random_element($array)
{
    shuffle($array);
    return array_pop($array);
}

设置自定义前缀

要自定义前缀,可以在application/config/config.php中找到

$config['subclass_prefix'] = 'MY_';

注意:不要使用CI_开头

使用CodeIgniter类库

所有的系统类库都位于system/libraries/目录下,大多数情况,需要在使用之前先初始化它

$this->load->library('class_name');

‘class_name’是你想要调用的类库名称,例如,要加载表单验证类库,可以这样做

$this->load->library('form_validation');

一旦类库被载入,就可以根据类库的用户指南中介绍的方法去使用它了

另外,多个类库可以通过一个数组来同时加载

$this->load->library(array('email', 'table'));

创建类库

类库通常位于libraries这个目录下

你可以创建一个全新的类库

你可以扩展原生的类库

你可以替换掉原生的类库

存储位置

你的类库文件应该放置在application/libraries目录下,当你初始化类时CodeIgniter会在这个目录下寻找

命名约定

文件名首字母必须大写

类名和文件名必须一致

defined('BASEPATH') OR exit('No direct script access allowed');

class Someclass {

    public function some_method()
    {
    }
}

使用类

$this->load->library('someclass');

其中someclass为文件名,不包括.php文件扩展名

文件名首字母大写,也可以写成全小写

一旦加载,你就可以使用小写字母名称来访问你的类

$this->someclass->some_method();

初始化类时传入参数

加载类库的时候,可以通过第二个参数动态的传递一个数组数据

该数组将被传到你的类的构造函数中

$params = array('type' => 'large', 'color' => 'red'); $this->load->library('someclass', $params);

类库中使用CodeIgniter资源

通常你的控制器中使用$this来调用所有可用的CodeIgniter方法

$this->load->helper('url');
$this->load->library('session');
$this->config->item('base_url');

但是$this只能在控制器、模型或视图中直接使用,如果你想在类库中使用

需要将CodeIgntier对象赋值给一个变量,然后用这个变量代替$this

$CI =& get_instance();

$CI->load->helper('url');
$CI->load->library('session');
$CI->config->item('base_url');

替换原生类库

将你的类文件名改为和原生的类库文件一致,CodeIgniter就会使用它替换掉原生的类库

例如:要替换掉原生的Email类的话,需要创建一个application/libraries/Email.php

class CI_Email {

}

加载方式一致:

$this->load->library('email');

注意:数据库类不能被替换

扩展原生类库

如果你想往现有类库中添加一些功能,这个时候就要扩展类库

类在定义时必须继承自父类

你的新类名和文件名必须以MY_为前缀

例如,要扩展原生的Email类你需要新建一个文件命名为application/libraries/MY_Email.php

class MY_Email extends CI_Email {
    public function __construct($config = array())
    {
        parent::__construct($config);
    }
}

加载和使用与普通类一致即可。

自定义前缀

$config['subclass_prefix'] = 'MY_';

CodeIgniter驱动器

一种特殊的类库,有一个父类和多个子类。子类可以访问父类,但不能访问兄弟类

我们可以在控制器中初始化父类,然后直接通过父类调用其他子类即可。

驱动器位于system/libraries目录,每个驱动器都有一个独立的目录,目录名和驱动器父类一致

该目录下还有一个子目录,命名为drivers,用于存放所有子类文件

要使用一个驱动器,可以在控制器中使用下面的方法来进行初始化

$this->load->driver('class_name');

然后就可以像下面这样调用该类的方法

$this->some_parent->some_method();

而对于那些子类,我们也不用初始化,可以直接通过父类调用了

$this->some_parent->child_one->some_method(); $this->some_parent->child_two->another_method();

钩子-扩展框架核心

钩子特性提供了一种方法来修改框架的内部运作流程,而无需修改核心文件。

启用钩子

application/config/config.php设置下面参数

$config['enable_hooks'] = TRUE;

定义钩子

钩子是在application/config/hooks.php文件中被定义的,每个钩子可以定义为下面的数组格式

$hook['pre_controller'] = array(
    'class'    => 'MyClass',
    'function' => 'Myfunction',
    'filename' => 'Myclass.php',
    'filepath' => 'hooks',
    'params'   => array('beer', 'wine', 'snacks')
);

数组的索引为想要使用的挂钩点名称pre_controller

钩子数组是一个关联数组,数组的键值可以是下面这些

class:希望调用的类名

function:希望调用的方法或函数名

filename:包含你的类或函数的文件名

filepath:包含你的脚本文件的目录名。filepath相对于application/目录的路径

params:你希望传递给你脚本的任何参数(可选)

或者也可以使用lamdba表达式作为钩子

$hook['post_controller'] = function() { /* do something here */ };

多次调用同一个挂钩点

如果想要同一个挂钩点添加多个脚本,只需要将钩子数组变成二维数组即可

$hook['pre_controller'][] = array(
    'class'    => 'MyClass',
    'function' => 'MyMethod',
    'filename' => 'Myclass.php',
    'filepath' => 'hooks',
    'params'   => array('beer', 'wine', 'snacks')
);

$hook['pre_controller'][] = array(
    'class'    => 'MyOtherClass',
    'function' => 'MyOtherMethod',
    'filename' => 'Myotherclass.php',
    'filepath' => 'hooks',
    'params'   => array('red', 'yellow', 'blue')
);

挂钩点

以下是所有可用挂钩点的一份列表:

pre_system:系统执行的早期调用,在执行路由或其他流程之前

pre_controller:控制器调用之前

post_controller_constructor:控制器实例化之后立即执行,方法之前

display_overried:覆盖_display方法,用于执行结束时向浏览器发送最终页面结果

cache_override:使用方法来替代输出类的方法,让你有自己的缓存显示机制

post_system:最终的页面发送到浏览器之后、在系统的最后期被调用

自动加载资源

自动加载特性可以允许系统每次运行时自动初始化类库、辅助函数和模型

如果需要在整个应用程序中全局使用某些资源,为方便起见可以考虑自动加载它们

支持自动加载的有下面这些:

libraries/目录下的核心类

helpers/ 目录下的辅助函数

config/ 目录下的自定义配置

system/language/ 目录下的语言文件

models/ 目录下的模型类

在application/config/autoload.php文件中添加到对应的autoload数组即可。添加时不用文件后缀

公共函数

定义了一些全局的函数,可以在任何地方使用它们,不需要加载任何类库或辅助函数

http://codeigniter.org.cn/user_guide/general/common_funct

兼容性函数

兼容性函数只有在高版本的PHP中才有,或者需要依赖其他的扩展才有。

http://codeigniter.org.cn/user_guide/general/compatibility_functions.html

URI路由

设置路由规则

规则定义在application/config/routes.php文件中,名为$route的数组,利用它可以设置你自己的路由规则

通配符

一个典型的使用通配符的路由规则如下:

$route['product/:num'] = 'catalog/product_lookup';

在一个路由规则中,数组的键表示要匹配的URI,值表示要重定向的位置。

URL第一段是product,第二段是数组,那么调用catalog类的product_lookup方法

也可以使用纯字符串匹配,或者使用下面两种通配符

(:num):匹配只含有数字的一段

(:any):匹配含有任何字符串的一段

例子:

$route['product/(:num)'] = 'catalog/product_lookup_by_id/$1';

URL第一段是product,第二段是数字的时候,重定向到catalog类的product_lookup_by_id方法

并将第二段的数组作为参数传递给它。$1表示第一个通配符匹配的内容

正则表达式

可以在路由规则中使用正则表达式。

$route['products/([a-z]+)/(\d+)'] = '$1/id_$2';

类似于products/shirts/123这样的URL将会重定向到shirts控制器的id_123方法

例如,登录页面重定向,就可以使用正则表达式来规定路由

$route['login/(.+)'] = 'auth/login/$1';

在路由中使用HTTP动词

可以在你的路由规则中使用HTTP动词,当你在创建RESTful应用时特别有用

可以使用标注你的HTTP动词(GET\PUT\POST\DELTE\PATCH)

$route['products']['put'] = 'product/insert';

当发送PUT请求到products这个URI时,将会调用Product::insert()方法

$route['products/(:num)']['DELETE'] = 'product/delete/$1';

当发送DELETE请求到第一段为products,第二段为数字这个URL时,将会调用Product::delete方法

保留路由

有三个保留路由,不能名称一致

$route['default_controller'] = 'welcome';

默认路由,当不加任何时调用的地址

$route['404_override'] = '';

表示当用户请求了一个不存在的页面时该加载那个控制器,将会覆盖默认的404错误页面

$route['translate_uri_dashes'] = FALSE;

可以自动的将URL中的控制器和方法中连字符转换为下划线

错误处理

可以通过下面介绍的方法来在你的应用程序中生成错误报告,另外还有一个错误日志类用来记录

错误函数是一个可以在整个应用程序中使用的简单接口,让你在使用该函数时不用担心类或方法的作用域的问题。

当任何一处核心代码调用exit()时,会返回一个状态码。

状态码用来通知其他程序PHP脚本是否成功运行,如果运行不成功,又是什么原因导致了脚本退出。

状态码的值被定义在application/config/constants.php文件中,状态码在CLI形式下非常有用,可以帮你的服务器跟踪并监控你的脚本

下面的函数用于生成错误信息:

show_error(message,status_code,heading)

该函数使用下面的错误模板来显示错误信息application/view/errors/html/error_general.php

show_404(page,log_error)

该函数使用下面的错误模板来显示404错误信息application/view/error/cli/error_404.php

log_message(level,message)

该函数用于向你的日志文件中写入信息,level有三种'error'\'debug'\'info'

为了保证日志文件被正确写入,logs/目录必须设置为可写的,此外必须要设置application/config/config.php

文件中的threshold参数

网页缓存

让你通过缓存页面来达到更好的性能

可以针对每个独立的页面进行缓存,并且你可以设置每个页面缓存的更新时间。

页面第一次加载时,缓存江北写入到application/cache目录下的文件中。

之后请求这个页面时,就可以直接从缓存文件中读取内容并输出到用户的浏览器。

如果缓存过期,会在输出之前被删除并重新刷新。

开启缓存 

将下面的代码放在任何一个控制器的方法内,你就可以开启缓存了。

$this->output->cache($n);

其中$n是缓存更新的事件(单位分钟)

上面代码可以放在方法的任何位置,出现的熟悉怒对缓存没有影响

删除缓存

删除代码后会在缓存过期时才会生效

如果需要手工删除,可以使用delete_cache()方法

$this->output->delete_cache();

程序分析

分析器类会在页面下方显示基准测试结果,运行过的SQL语句,自己$_POST数组,有助于调试和优化

启用分析器

$this->output->enable_profiler(TRUE);

当启用之后,将会生成一份报告插入到页面的最底部

使用下面的方法禁用分析器

$this->output->enable_profiler(FALSE);

启用禁用分析器中的字段

分析器中的每个字段都可以通过设置响应的控制变量为TRUE或FALSE来启用或禁用

在application/config/profiler.php设置全局的默认值

$config['config']          = FALSE; $config['queries'] = FALSE;

或者在控制器里通过调用输出类的set_profiler_sections函数来覆盖全局设置和默认设置

$sections = array(
    'config'  => TRUE, 'queries' => TRUE ); $this->output->set_profiler_sections($sections);

分析器字段如下

benchmarks:各个计时点话费的时间以及总时间

config:配置变量

controller_info:被请求的控制器类和调用的方法

get:请求中的所有GET数据

http_headers:本次请求的HTTP头部

memory_usage:本次请求消耗的内存

post:请求中的所有POST数据

queries:列出所有执行的数据库查询以及执行时间

uri_string:本次请求的URI

session_data:当前会话存储的数据

query_toggle_count:指定显示多少个数据库查询,剩下的默认折叠

PHP替代语法

如果你不使用模板引擎,那么你就只能在视图文件中使用纯PHP语法了

为了精简,推荐在写控制结构或echo语句的时候使用PHP替代语法。

如果你发现替代语法不能使用,那就是在php.ini文件中禁用了短标记

CodeIgniter可以动态的重写所有段标记,这样你的服务器不支持也可以使用段标记

这个特性可以再config/config.php文件中启用

Echo替代语法

<?=$variable?> 

控制结构替代语法 

像if、for、foreach、while这样的控制结构也可以写成精简版。

<ul>
<?php foreach ($todo as $item): ?>
    <li><?=$item?></li>
<?php endforeach; ?>
</ul>

注意,这里没有任何括号。所有的结束括号被替换成了endforeach

同样也就endif、endfor、endforeach、endwhile

注意,每个分支结构的后面都要跟一个冒号,而不是分号,这非常重要

<?php if ($username === 'sally'): ?>
    <h3>Hi Sally</h3>
<?php elseif ($username === 'joe'): ?>
    <h3>Hi Joe</h3>
<?php else: ?>
    <h3>Hi unknown user</h3>
<?php endif; ?>

URI安全

CodeIgniter严格限制URI中允许出现的字符,以此来减少恶意数据传到你的应用可能性

URI中只允许包含一些字符:

字母数字、~、%、句号、分号、下划线、连字号-、空格

输入类

输入类有两个用途

1.为了安全性,对输入数据进行预处理

2.提供了一些辅助方法来获取输入数据并处理

该类自动加载,无需手工加载

XSS过滤

输入类可以自动的对输入数据进行过滤,如果希望每次POST或COOKIE自动运行过滤,可以设置config.php中的参数

$config['global_xss_filtering'] = TRUE;

访问表单数据

提供了几个辅助方法来从POST、GET、COOKIE、SERVER数组中获取数据。

可以写成如下几个方法:

$this->input->post('')

$this->input->get('')

$this->input->cookie('') 

$this->input->server('')

Session

需要手动加载Session

$this->load->library('session');

 然后就可以直接使用session进行操作了

$this->session

获取Session:$_SESSION['item'],$this->session->item

添加Session:$this->session->set_userdata('some_name','some_value')

检查Session:isset($_SESSION['some_name']),$this->session->has_userdata('some_name');

删除Session:unset($_SESSION['some_name'])

标记Session时效:首先需要创建一个Session,然后$this->session->mark_as_temp('some_name',300)单位为秒

销毁Session:session_destroy();

单元测试

首先还是要初始化

$this->load->library('unit_test');

然后使用它

$this->unit->run('test', 'expected result', 'test name', 'notes');

test是测试的代码结果、expected result是期望返回的结果、test name是测试名称,notes是备注

生成测试报告

可以给每个测试单独生成报告

echo $this->unit->run($test, $expected_result);

或者显示一份完整报告

echo $this->unit->report();

也可以获取报告数组数据

echo $this->unit->result();

数据库

初始化数据库

$this->load->database();

多行结果查询

$query = $this->db->query('SELECT name, title, email FROM my_table');

//对象形式
foreach ($query->result() as $row)
{
    echo $row->title;
    echo $row->name;
    echo $row->email;
}
echo 'Total Results: ' . $query->num_rows();

//数组形式
foreach ($query->result_array() as $row)
{
    echo $row['title'];
    echo $row['name'];
    echo $row['email'];
}

单行结果查询,返回结果集$query

$query = $this->db->query('SELECT name FROM my_table LIMIT 1');

//对象
$row = $query->row(); //传递一个数字参数来返回特定行数据
echo $row->name;

//数组
$row = $query->row_array(); //传递一个数字参数来返回特定行数据
echo $row['name'];

标准插入方法,返回TRUE/FALSE

$sql = "INSERT INTO mytable (title, name) VALUES (".$this->db->escape($title).", ".$this->db->escape($name).")";
$this->db->query($sql);
echo $this->db->affected_rows();

查询构造器查询数据

$query = $this->db->get('table_name');

foreach ($query->result() as $row)
{
    echo $row->title;
}

查询构造器插入数据

$data = array(
    'title' => $title,
    'name' => $name,
    'date' => $date
);

//
// 生成这样的SQL代码:
//   INSERT INTO mytable (title, name, date) VALUES ('{$title}', '{$name}', '{$date}')
//
$this->db->insert('mytable', $data);

数据库配置

application/config/database.php用于存放数据库配置文件

$db['default'] = array(
    'dsn'   => '', //DSN连接字符串
    'hostname' => 'localhost', //数据库主机名
    'username' => 'root', //用户名
    'password' => '', //密码
    'database' => 'database_name', //数据库名
    'dbdriver' => 'mysqli', //数据库类型引擎
    'dbprefix' => '', //查询构造器前缀
    'pconnect' => TRUE, //是否使用持续连接
    'db_debug' => TRUE, //是否显示数据库错误信息
    'cache_on' => FALSE, //是否开启数据库查询缓存
    'cachedir' => '', //数据库查询缓存绝对路径
    'char_set' => 'utf8', //数据库通信时使用的字符集
    'dbcollat' => 'utf8_general_ci', //数据库通信时使用的字符规则
    'swap_pre' => '', //替换默认的dbprefix
    'encrypt' => FALSE, //是否使用加密连接
    'compress' => FALSE, //是否使用客户端压缩协议
    'stricton' => FALSE, //是否强制使用Strict Mode连接
    'failover' => array()
);

数据库端口号修改,需要手动添加配置

$db['default']['port'] = 5432;

这是默认的数据库配置,如果想指定数据库配置,将上面的数组建明改一下

然后修改配置文件中的

$active_group = 'test';

查询构造器 

通过数据库配置文件的$query_builder变量对查询构造器类进行全局设定,启用设成TRUE,禁用设成FALSE

$query_builder = TRUE;

转义查询

提交数据到你的数据库之前,确保先对其进行转义是个非常不错的做法

escape()这个函数会检测数据类型,仅转义字符串类型的数据。会自动用单引号将你的数据括起来

$sql = "INSERT INTO table (title) VALUES(".$this->db->escape($title).")";

escapse-like-str()这个函数用于处理LIKE语句中的字符串

$search = '20% raise';
$sql = "SELECT id FROM table WHERE column LIKE '%" . $this->db->escape_like_str($search)."%' ESCAPE '!'";

查询绑定 

可以简化查询语句,使用占位符来自动拼接

$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?";
$this->db->query($sql, array(3, 'live', 'Rick'));

 

也可以使用数组中的数组来进行IN语句的转换

$sql = "SELECT * FROM some_table WHERE id IN ? AND status = ? AND author = ?";
$this->db->query($sql, array(array(3, 6), 'live', 'Rick'));

错误处理

要获取最近一次发生的错误信息,可以使用error方法

if ( ! $this->db->simple_query('SELECT `example_field` FROM `example_table`')) { $error = $this->db->error(); // Has keys 'code' and 'message' }

结果辅助方法

num_rows方法:该方法返回查询结果的行数

$query = $this->db->query('SELECT * FROM my_table'); echo $query->num_rows();

num_fields方法:该方法返回查询结果列数

$query = $this->db->query('SELECT * FROM my_table'); echo $query->num_fields();

free_result方法:释放资源所占内存,在大量查询后调用即可

$query->free_result();

查询辅助函数

$this->db->insert_id():返回最近一次插入行的id

$this->db->affected_rows():当执行INSERT\UPDATE\DELETE返回受影响的行数

$this->db->last_query():返回上一次执行的查询语句

$this->db->count_all():用于获取数据表的总行数

echo $this->db->count_all('my_table');

$this->db->platform():用于输出正在使用的数据库平台

echo $this->db->platform();

$this->db->version():输出你正在使用的数据库版本

语法糖

$this->db->insert_string():简化INSERT语法书写,返回正确格式化的INSERT

$data = array('name' => $name, 'email' => $email, 'url' => $url); $str = $this->db->insert_string('table_name', $data);

注:所有的值都已经被自动转义了,是安全的值

$this->db->update_string():简化了UPDATE语法书写,返回正确格式化的UPDATE

$data = array('name' => $name, 'email' => $email, 'url' => $url);
$where = "author_id = 1 AND status = 'active'";
$str = $this->db->update_string('table_name', $data, $where);

查询构造器类

查询表所有数据

$query = $this->db->get('mytable'); // Produces: SELECT * FROM mytable

分页查询表数据

$query = $this->db->get('mytable', 10, 20);

生成结果

$query = $this->db->get('mytable'); foreach ($query->result() as $row) { echo $row->title; }

条件查询

$query = $this->db->get_where('mytable', array('id' => $id), $limit, $offset);

SELECT指定列,当字段包含子查询时,需要将第二个参数传递FALSE,意思是不保护字段类型

$this->db->select('title, content, date'); $query = $this->db->get('mytable');

MAX第二个参数可以给别名

$this->db->select_max('age'); $query = $this->db->get('members'); // Produces: SELECT MAX(age) as age FROM members $this->db->select_max('age', 'member_age'); $query = $this->db->get('members'); // Produces: SELECT MAX(age) as member_age FROM members

MIN

$this->db->select_avg('age'); $query = $this->db->get('members');

SUM

$this->db->select_sum('age'); $query = $this->db->get('members'); 

JOIN

$this->db->select('*');
$this->db->from('blogs');
$this->db->join('comments', 'comments.id = blogs.id');
$query = $this->db->get();

// Produces:
// SELECT * FROM blogs JOIN comments ON comments.id = blogs.id

如果查询中有多个链接,可以多次调用这个方法,可以传第三个参数指定链接类型

有这样几种选择:left,right,outer,inner,left outer 和 right outer 。

$this->db->join('comments', 'comments.id = blogs.id', 'left'); // Produces: LEFT JOIN comments ON comments.id = blogs.id

Where,一共提供四种方法编写查询语句

1.简单Key-Value

$this->db->where('name', $name); // Produces: WHERE name = 'Joe'

$this->db->where('name', $name);
$this->db->where('title', $title);
$this->db->where('status', $status);
// WHERE name = 'Joe' AND title = 'boss' AND status = 'active'

2.自定义Key-Value

$this->db->where('name !=', $name); $this->db->where('id <', $id); // Produces: WHERE name != 'Joe' AND id < 45

3.关联数组

$array = array('name' => $name, 'title' => $title, 'status' => $status);
$this->db->where($array);
// Produces: WHERE name = 'Joe' AND title = 'boss' AND status = 'active'

$array = array('name !=' => $name, 'id <' => $id, 'date >' => $date);
$this->db->where($array);

4.自定义字符串

$where = "name='Joe' AND status='boss' OR status='active'";
$this->db->where($where);

注意有一个可选的第三个参数,如果设置为FALSE,不保护表名和字段名

or_where

$this->db->where('name !=', $name); $this->db->or_where('id >', $id); // Produces: WHERE name != 'Joe' OR id > 50

where_in

$names = array('Frank', 'Todd', 'James'); $this->db->where_in('username', $names); // Produces: WHERE username IN ('Frank', 'Todd', 'James')

or_where_in

$names = array('Frank', 'Todd', 'James'); $this->db->or_where_in('username', $names); // Produces: OR username IN ('Frank', 'Todd', 'James')

where_not_in

$names = array('Frank', 'Todd', 'James'); $this->db->where_not_in('username', $names); // Produces: WHERE username NOT IN ('Frank', 'Todd', 'James')

or_where_not_in

$names = array('Frank', 'Todd', 'James'); $this->db->or_where_not_in('username', $names); // Produces: OR username NOT IN ('Frank', 'Todd', 'James')

like

$this->db->like('title', 'match'); $this->db->like('body', 'match'); // WHERE `title` LIKE '%match%' ESCAPE '!' AND `body` LIKE '%match% ESCAPE '!'

关联数组

$array = array('title' => $match, 'page1' => $match, 'page2' => $match); $this->db->like($array); // WHERE `title` LIKE '%match%' ESCAPE '!' AND `page1` LIKE '%match%' ESCAPE '!' AND `page2` LIKE '%match%' ESCAPE '!'

or_like

$this->db->like('title', 'match'); $this->db->or_like('body', $match); // WHERE `title` LIKE '%match%' ESCAPE '!' OR `body` LIKE '%match%' ESCAPE '!'

not_like

$this->db->not_like('title', 'match'); // WHERE `title` NOT LIKE '%match% ESCAPE '!'

or_not_like

$this->db->like('title', 'match'); $this->db->or_not_like('body', 'match'); // WHERE `title` LIKE '%match% OR `body` NOT LIKE '%match%' ESCAPE '!'

group_by

$this->db->group_by("title"); // Produces: GROUP BY title
$this->db->group_by(array("title", "date")); // Produces: GROUP BY title, date

distinct

$this->db->distinct(); $this->db->get('table'); // Produces: SELECT DISTINCT * FROM table

having

$this->db->having('user_id = 45'); // Produces: HAVING user_id = 45 $this->db->having('user_id', 45); // Produces: HAVING user_id = 45
$this->db->having(array('title =' => 'My Title', 'id <' => $id)); // Produces: HAVING title = 'My Title', id < 45

or_having

同上

order_by

$this->db->order_by('title', 'DESC');
// Produces: ORDER BY `title` DESC

$this->db->order_by('title DESC, name ASC'); // Produces: ORDER BY `title` DESC, `name` ASC

$this->db->order_by('title', 'DESC'); $this->db->order_by('name', 'ASC'); // Produces: ORDER BY `title` DESC, `name` ASC

limit,限制返回结果数量

$this->db->limit(10); // Produces: LIMIT 10
$this->db->limit(10, 20);

count_all_results获取符合条件的数量

echo $this->db->count_all_results('my_table');  // Produces an integer, like 25
$this->db->like('title', 'match');
$this->db->from('my_table');
echo $this->db->count_all_results(); // Produces an integer, like 17

count_all获取表总行数

echo $this->db->count_all('my_table'); // Produces an integer, like 25

insert()

$data = array(
    'title' => 'My title',
    'name' => 'My Name',
    'date' => 'My date'
);

$this->db->insert('mytable', $data);
// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date')

get_compiled_insert()

与insert一样,但是不执行SQL,返回SQL

insert_batch批量插入

$data = array(
    array(
        'title' => 'My title',
        'name' => 'My Name',
        'date' => 'My date'
    ),
    array(
        'title' => 'Another title',
        'name' => 'Another Name',
        'date' => 'Another date'
    )
);

$this->db->insert_batch('mytable', $data);

update

$data = array(
    'title' => $title,
    'name' => $name,
    'date' => $date
);

$this->db->where('id', $id);
$this->db->update('mytable', $data);
// Produces:
//
//  UPDATE mytable
//  SET title = '{$title}', name = '{$name}', date = '{$date}'
//  WHERE id = $id

或者也可以使用对象,包括insert也可以使用

/*
class Myclass {
    public $title = 'My Title';
    public $content = 'My Content';
    public $date = 'My Date';
}
*/

$object = new Myclass;
$this->db->where('id', $id);
$this->db->update('mytable', $object);
// Produces:
//
// UPDATE `mytable`
// SET `title` = '{$title}', `name` = '{$name}', `date` = '{$date}'
// WHERE id = `$id`

update_batch

$data = array(
   array(
      'title' => 'My title' ,
      'name' => 'My Name 2' ,
      'date' => 'My date 2'
   ),
   array(
      'title' => 'Another title' ,
      'name' => 'Another Name 2' ,
      'date' => 'Another date 2'
   )
);

$this->db->update_batch('mytable', $data, 'title');

// Produces:
// UPDATE `mytable` SET `name` = CASE
// WHEN `title` = 'My title' THEN 'My Name 2'
// WHEN `title` = 'Another title' THEN 'Another Name 2'
// ELSE `name` END,
// `date` = CASE
// WHEN `title` = 'My title' THEN 'My date 2'
// WHEN `title` = 'Another title' THEN 'Another date 2'
// ELSE `date` END
// WHERE `title` IN ('My title','Another title')

delete

$this->db->delete('mytable', array('id' => $id));  // Produces: // DELETE FROM mytable  // WHERE id = $id
$this->db->where('id', $id);
$this->db->delete('mytable');

// Produces:
// DELETE FROM mytable
// WHERE id = $id

如果想从多个表删除数据,可以将多个表明组成数组传递给delete

$tables = array('table1', 'table2', 'table3'); $this->db->where('id', '5'); $this->db->delete($tables);

truncate

$this->db->from('mytable');
$this->db->truncate();

// or

$this->db->truncate('mytable');

// Produce:
// TRUNCATE mytable

链式方法

通过将多个方法链接在一起,可以简化你的语法

$query = $this->db->select('title')
        ->where('id', $id)
        ->limit(10, 20)
        ->get('mytable');

事务

可以使用$this->db->trans_start()和complete()两个方法

$this->db->trans_start();
$this->db->query('AN SQL QUERY...');
$this->db->query('ANOTHER QUERY...');
$this->db->query('AND YET ANOTHER QUERY...');
$this->db->trans_complete();

在之间,可以运行任意多个查询,根据查询执行成功或失败,系统自动提交或回滚

数据库元数据

$this->db->list_table():列出数据库中所有的表

$tables = $this->db->list_tables();

foreach ($tables as $table)
{
    echo $table;
}

$this->db->table_exists():检查表是否存在

if ($this->db->table_exists('table_name'))
{
    // some code...
}

$this->db->list_fields():列出表的所有列

$fields = $this->db->list_fields('table_name');

foreach ($fields as $field)
{
    echo $field;
}

也可以从任何查询结果上获取

$query = $this->db->query('SELECT * FROM some_table');

foreach ($query->list_fields() as $field)
{
    echo $field;
}

$this->db->field_exists():检测表中是否存在某个字段

if ($this->db->field_exists('field_name', 'table_name'))
{
    // some code...
}

数据库缓存

http://codeigniter.org.cn/user_guide/database/caching.html

转载于:https://www.cnblogs.com/chenxygx/p/8384682.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值