php基礎-10
PHP日期函式
PHP date() 函式可把時間戳格式化為可讀性更好的日期和時間。
時間戳是一個字元序列,表示一定的事件發生的日期/時間。
語法
string date ( string $format [, int $timestamp ] )
引數 | 描述 |
---|---|
format | 必需。規定時間戳的格式。 |
timestamp | 可選。規定時間戳。預設是當前的日期和時間。 |
date() 函式的第一個必需引數 format 規定了如何格式化日期/時間。
這裡列出了一些可用的字元:
- d - 代表月中的天 (01 - 31)
- m - 代表月 (01 - 12)
- Y - 代表年 (四位數)
如需瞭解 format 引數中可用的所有字元列表,請查閱我們的 PHP Date 參考手冊,date() 函式。
可以在字母之間插入其他字元,比如 "/"、"." 或者 "-",這樣就可以增加附加格式了:
<?php echo date("Y/m/d") . "<br>"; echo date("Y.m.d") . "<br>"; echo date("Y-m-d"); ?> >>> 2016/10/21 2016.10.21 2016-10-21
PHP 包含檔案
PHP include 和 require 語句
在 PHP 中,您可以在伺服器執行 PHP 檔案之前在該檔案中插入一個檔案的內容。
include 和 require 語句用於在執行流中插入寫在其他檔案中的有用的程式碼。
include 和 require 除了處理錯誤的方式不同之外,在其他方面都是相同的:
- require 生成一個致命錯誤(E_COMPILE_ERROR),在錯誤發生後腳本會停止執行。
- include 生成一個警告(E_WARNING),在錯誤發生後腳本會繼續執行。
因此,如果您希望繼續執行,並向用戶輸出結果,即使包含檔案已丟失,那麼請使用 include。否則,在框架、CMS 或者複雜的 PHP 應用程式程式設計中,請始終使用 require 向執行流引用關鍵檔案。這有助於提高應用程式的安全性和完整性,在某個關鍵檔案意外丟失的情況下。
包含檔案省去了大量的工作。這意味著您可以為所有網頁建立標準頁頭、頁尾或者選單檔案。然後,在頁頭需要更新時,您只需更新這個頁頭包含檔案即可。
include 'filename';
或者
require 'filename';
1、假設您有一個標準的頁標頭檔案,名為 "header.php"。如需在同一個頁面中引用這個頁標頭檔案,請使用 include/require:
下面這個是.php檔案
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
</head>
<body>
<?php include 'header.php'; ?> <!--請使用 include/require-->
<h1>歡迎來到我的主頁!</h1>
<p>一些文字。</p>
</body>
</html>
輸出結果:
2、假設我們有一個在所有頁面中使用的標準選單檔案。
"menu.php":
echo '<a href="/">主頁</a>
<a href="/html">HTML 教程</a>
<a href="/php">PHP 教程</a>';
網站中的所有頁面均應引用該選單檔案。以下是具體的做法:
下面這個是.php檔案
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
</head>
<body>
<div class="leftmenu">
<?php include 'menu.php'; ?>
</div>
<h1>歡迎來到我的主頁!</h1>
<p>一些文字。</p>
</body>
</html>
PHP 檔案處理
fopen() 函式用於在 PHP 中開啟檔案。
開啟檔案
fopen() 函式用於在 PHP 中開啟檔案。
此函式的第一個引數含有要開啟的檔案的名稱,第二個引數規定了使用哪種模式來開啟檔案:
<html>
<body>
<?php
$file=fopen("welcome.txt","r");
?>
</body>
</html>
檔案可能通過下列模式來開啟:
模式 | 描述 |
---|---|
r | 只讀。在檔案的開頭開始。 |
r+ | 讀/寫。在檔案的開頭開始。 |
w | 只寫。開啟並清空檔案的內容;如果檔案不存在,則建立新檔案。 |
w+ | 讀/寫。開啟並清空檔案的內容;如果檔案不存在,則建立新檔案。 |
a | 追加。開啟並向檔案末尾進行寫操作,如果檔案不存在,則建立新檔案。 |
a+ | 讀/追加。通過向檔案末尾寫內容,來保持檔案內容。 |
x | 只寫。建立新檔案。如果檔案已存在,則返回 FALSE 和一個錯誤。 |
x+ | 讀/寫。建立新檔案。如果檔案已存在,則返回 FALSE 和一個錯誤。 |
註釋:如果 fopen() 函式無法開啟指定檔案,則返回 0 (false)。
例項
如果 fopen() 函式不能開啟指定的檔案,下面的例項會生成一段訊息:
<html>
<body>
<?php
$file=fopen("welcome.txt","r") or exit("Unable to open file!");
?>
</body>
</html>
>>>Warning: fopen(welcome.txt): failed to open stream: No such file or directory in E:\php_enviroment\PHPTutorial\WWW\1.php on line 4
Unable to open file!
關閉檔案
fclose() 函式用於關閉開啟的檔案:
<?php
$file = fopen("test.txt","r");
//執行一些程式碼
fclose($file);
?>
檢測檔案末尾(EOF)
feof() 函式檢測是否已到達檔案末尾(EOF)。
在迴圈遍歷未知長度的資料時,feof() 函式很有用。
注意:在 w 、a 和 x 模式下,您無法讀取開啟的檔案!
if (feof($file)) echo "檔案結尾"; 、// 如果出錯或者檔案指標到了檔案末尾(EOF)則返回 TRUE,否則返回 FALSE。
逐行讀取檔案
fgets() 函式用於從檔案中逐行讀取檔案。
註釋:在呼叫該函式之後,檔案指標會移動到下一行。
例項
下面的例項逐行讀取檔案,直到檔案末尾為止:
<?php
$file = fopen("welcome.txt", "r") or exit("無法開啟檔案!");
// 讀取檔案每一行,直到檔案結尾
while(!feof($file))
{
echo fgets($file). "<br>";
}
fclose($file); // 讀取後必須關閉
?>
welcome.txt
fafeqafqaf
dawdfafaff
`1`2`21333
fqafafqwfq
輸出:
逐字元讀取檔案
fgetc() 函式用於從檔案中逐字元地讀取檔案。
註釋:在呼叫該函式之後,檔案指標會移動到下一個字元。
例項
下面的例項逐字元地讀取檔案,直到檔案末尾為止:
<?php
$file=fopen("welcome.txt","r") or exit("無法開啟檔案!");
while (!feof($file))
{
echo fgetc($file);
}
fclose($file);
?>
>>>
fafeqafqaf dawdfafaff `1`2`21333 fqafafqwfq
如果開啟一個檔案,檔名為中文,如果系統程式設計和當前文件編碼不一致,會導致檔案找不到無法開啟,解決方法是用 iconv 函式編碼轉換成一致,如下:
$fpath=iconv('UTF-8','GB2312',"題庫.csv");
$file=fopen($fpath,"r") or exit("無法開啟檔案!");
//此處省略相關操作
fclose($file);
用相對路徑打不開子目錄中的檔案時,可用絕對路徑開啟,如下:
$file=fopen(dirname(__FILE__).'\\files\\tk.csv',"r") or exit("無法開啟檔案!");
//此處省略相關操作
fclose($file);
檔案上傳
開發中需要上傳圖片、音樂、視訊等等,這種上傳傳遞是二進位制資料。
客戶端上傳檔案
檔案域
<input type="file" name="image">
表單的enctype屬性
預設情況下,表單傳遞是字元流,不能傳遞二進位制流,通過設定表單的enctype屬性傳遞複合資料。
enctype屬性的值有:
- multipart/form-data:複合的表單資料(字串/字元,二進位制都可以傳),需要二進位制資料時,比如檔案內容,請使用 "multipart/form-data", 檔案上傳必須設定此值
- text/plain:用於向伺服器傳遞無格式的文字資料,主要使用者電子郵件
- application/x-www-form-urlencoded:【預設】,表示傳遞的是帶格式的文字資料。
- from標籤的 type="file" 屬性規定了應該把輸入作為檔案來處理。舉例來說,當在瀏覽器中預覽時,會看到輸入框旁邊有一個瀏覽按鈕。
單詞
multipart:複合
form-data:表單陣列
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<?php
if(!empty($_POST)){
echo "<pre>";
print_r($_FILES);
}
?>
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="face">
<input type="submit" name="button" value="上傳">
</form>
</body>
</html>
伺服器接受檔案
超全域性變數$_FILES
是一個二維陣列,用來儲存客戶端上傳到伺服器的檔案資訊,第一個行引數是表單的 input 標籤的name屬性值, 列引數有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表示正確
$_FILES[][‘error’]
詳解:沒有5
值 | 錯誤描述 |
---|---|
0 | 正確 |
1 | 檔案大小超過了php.ini中允許的最大值 upload_max_filesize = 2M |
2 | 檔案大小超過了表單允許的最大值 |
3 | 只有部分檔案上傳 |
4 | 沒有檔案上傳 |
6 | 找不到臨時檔案 |
7 | 檔案寫入失敗 |
hidden屬性值:隱藏作用。隱藏域,在頁面上不顯示,但是可以將引數傳遞給下一頁,也可以被本頁的javascript函式獲取。
隱含域主要用於提交表單的時候傳遞動態引數。
注意:MAX_FILE_SIZE必須在檔案域的上面。
只要掌握的錯誤號:0和4
將上傳檔案移動到指定位置
函式:
move_uploaded_file(臨時地址,目標地址)
程式碼
<body>
<?php
if(!empty($_POST)) {
if($_FILES['face']['error']==0){ //上傳正確
//檔案上傳
move_uploaded_file($_FILES['face']['tmp_name'],'./'.$_FILES['face']['name']); // tmp_name臨時檔案的引數,上面講了,第一個引數是name屬性值,在第14行
// 目標地址:'./'.$_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>
小結:上傳的同名的檔案要給覆蓋
與檔案上傳有關的配置
post_max_size = 8M:表單允許的最大值
upload_max_filesize = 2M:允許上傳的檔案大小
upload_tmp_dir =F:\wamp\tmp:指定臨時檔案地址,如果不指定,作業系統會指定。自己可以修改指定
file_uploads = On:是否允許檔案上傳
max_file_uploads = 20:允許同時上傳20個檔案
優化檔案上傳
更改檔名
方法一:通過時間戳做檔名
UNIX 時間戳(timestamp)是 PHP 中關於時間日期一個很重要的概念,它表示從 1970年1月1日 00:00:00 到當前時間的秒數之和。
PHP提供了內建函式 time() 來取得伺服器當前時間的時間戳。
例子:
<?php
echo time();
?>
上面的例子執行後得到的是一串類似這樣的數字:1279115455
我們可以通過 date()等函式將它格式化為我們需要的時間日期格式。
有效的時間戳典型範圍是格林威治時間 1901年12月13日 20:45:54 到 2038年1月19日 03:14:07(此範圍符合 32 位有符號整數的最小值和最大值)。不過從 5.1.0 起,已經克服了年的範圍只能是 1901 到 2038 之間的問題。
提示
- time() 得到的總是當前的時間戳,所以是不固定的值
- 如果時間戳為負數,則為從1970年1月1日 00:00:00往前推
時間差
時間戳雖然看起來好像不太直觀,但我們在對時間做計算時卻很方便。例如我們要計算時間差,或者對兩個時間做比較等,直接比較數字即可而不必分別去考慮年月日時分秒的換算。而且在效率上時間戳作為整型資料也會快得多。
要求使用者在登陸網站一定時間後失效而需要重新登入的例子:
<?php
$expiration = $time()+2*3600; //得到當前時間延遲2小時候的時間戳
//失效驗證程式碼略
?>
那麼只需要使用者在活動期間將當前時間戳與 $expiration 進行比較,如果大於 $expiration 則要求使用者重新登入。
頁面執行時間
計算當前頁面執行時間的例子:
<?php
//do something
sleep(3);
//do something
$running_time = time() - $_SERVER['REQUEST_TIME'];
echo '頁面執行時間:',$running_time,' 秒';
?>
執行例子輸出如下:
頁面執行時間:3 秒
$_SERVER[‘REQUEST_TIME’]是 PHP 內建的當前頁面開始執行時的時間戳,在當前頁面執行結束時將
time() - $_SERVER[‘REQUEST_TIME’]得到的就是當前頁面執行的時間(秒):
由於該例子沒有其他更多內容,因此是用 sleep(3) 函式讓頁面執行延遲 3 秒鐘。
// 更改檔名,用當前的時間加個位的隨機數來作為檔名(有可能同一時間剛好有兩個客戶端通過時間戳命名上傳檔案,那兩個檔名字相同會被覆蓋)
<?php
$path='face.stu.jpg';
//echo strrchr($path,'.'); //從最後一個點開始擷取,一直擷取到最後, 到這一步會輸出:.jpg
echo time().rand(100,999).strrchr($path,'.'); // 輸出:1594613333385.jpg(重新整理一次,時間變,資料變,名稱就變了)
方法二:通過uniqid()實現
$path='face.stu.jpg';
echo uniqid().strrchr($path,'.'),'<br>'; //uniqid()會輸出唯一的ID
echo uniqid('goods_').strrchr($path,'.'),'<br>'; //帶有字首
echo uniqid('goods_',true).strrchr($path,'.'),'<br>'; //唯一ID+隨機數
驗證檔案格式
方法一:判斷檔案的副檔名(不能識別檔案偽裝)
操作思路:將檔案的字尾和允許的字尾對比
// strrchr():搜尋 "Shanghai" 在字串中的位置,並返回從該位置到字串結尾的所有字元:
<?php
echo strrchr("I love Shanghai!","Shang");
?>
>>>Shanghai!
<body>
<?php
if(!empty($_POST)) {
$allow=array('.jpg','.png','.gif'); //允許的副檔名構成的陣列
$ext=strrchr($_FILES['face']['name'],'.'); //獲取上傳檔案的副檔名
if(in_array($ext,$allow)) // in_array(),返回值是bool值,字串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_*的函數了
<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擴充套件(可以防止檔案偽裝)
優化檔案上傳例題
步驟
第一步:驗證是否有誤
第二步:驗證格式
第三步:驗證大小
第四步:驗證是否是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{
//檔案上傳,上傳的檔案儲存到當天的資料夾中
// date('Y-m-d H:i:s', 1231346);將時間戳變格式,如果沒有第二個引數,預設是將當前的時間戳改變格式
$foldername=date('Y-m-d H:i:s'); //資料夾名稱,通過date()函式將當前的時間戳的格式變成年-月-日 小時:分鐘:秒的形式
// date('Y-m-d H:i:s')發現時間輸出不對,需要修改當前版本的php的php.ini檔案裡的date.timezone = PRC(改成Peoples Republic China時區,預設不寫是東一區即英國的格林尼治)
// 成功顯示2020-07-13 16:08:54
$folderpath="./uploads/{$foldername}"; //資料夾路徑(事先在WWW資料夾下新建這個uploads資料夾)
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>
執行結果
小結:
1、將時間戳轉換格式
echo date('Y-m-d H:i:s',1231346),'<br>'; //將時間戳轉成年-月-日 小時:分鐘:秒
echo date('Y-m-d H:i:s'),'<br>'; //將當前的時間轉成年-月-日 小時:分鐘:秒
2、設定時區(php.ini)
PRC:中華人民共和國
3、PHP的執行可以不需要Apache的參與