2015年3月16日

[教學] PHP & MySQL 學習筆記 第五堂(瀏覽人數計數器製作)

非常抱歉,關於部落格內 PHP 的部分目前已經停止維護,因本人已經很久沒有寫 PHP ,且文章中所使用的 PHP 版本偏舊,希望有心學習 PHP 的朋友們,可以參考 Codecademy 的課程,或近一步嘗試 Laravel 這個 PHP 框架(可透過 laracasts 學習),若有找不到錯的學習資源也歡迎在留言串分享,方便有需要的人能夠有更多學習的管道!
第五堂課,我們要來練習製作一個計數器,可以記錄網站有多少人來瀏覽過。


可以玩玩看這次的成果喔:
這次會學習到的PHP語法共包含:

fgets():取得資料
for(起始值;結束值;設定){回圈內容}:建立回圈
strlen():判斷字串長度(string length)
substr():取得部分字串(sub string)

計數器製作
首先,我們打開DW後,開啟兩個新檔,一個是php檔,一個是文字檔,檔名分別取為p5.php和p5.txt。


接著,進入「設計」欄位,輸入「參觀人數:」

在p5.txt檔裡面,我們要設定的是計數器的起始值(這裡從1245開始),也就是即使沒有任何人來過,計數器會先從1245開始。

再來要來打php的語法了,這裡會用到open、gets和close,open和close已經在前一堂(第四堂)課有提過,fopen(檔案名稱,開啟模式),這裡我們開啟模式用r,表示唯讀。fgets則是新的語法,意思是取的資料。這裡在打的時候,要留意一下,用的是小括號,然後有些地方要記得加雙引號,每行結束要記得加上分號做結。

在內文的地方,我們則是希望echo出p5.txt裡面,我們剛剛輸入的數字。

預覽看看,卻發現有錯誤,到底錯誤發生在什麼地方呢?讓我們繼續看下去。
原來,之所以有錯誤,是因為我們這裡並沒有把抓起的資料建立成一個變數,$file只是把檔案開啟後的變數而已,並沒有把開啟的檔案讀出來。

因此,在這裡我們要把fgets的檔案建立一個新的變數,這裡我把它叫做num。同樣的,在內文的地方,我就要請它去幫我讀取num這個變數。

這時候預覽就會看到數字跑出來了喔!
可是,這不是計數器阿!這時候不管你怎麼按,數字都只會停留在1245而已。
為了要讓計數器會隨網頁被瀏覽的次數而改變,我們必須要增加以下的語法。
首先$num++,表示變數num會每一次都加一。fopen這裡,我們的開啟模式用的是w,意思是覆寫,也就是如果原本是1245,打開一次會加一,然後以1246覆寫進入原本的txt檔(這裡如果我們用的是a(寫入),會變成12451246)。fwrite則在上一堂課有學過,裡面放的是fwrite(檔案,寫入資料),所以這裡的意思是,我們把變數num,加一之後,再以覆寫的方式寫入p5.txt這個檔案中。

這時候,我們就完成第一部分了,數字會隨著點閱瀏覽器的次數而有改變了。

將計數器改為圖片呈現

再來這個部分就比較複雜一些,我們想要做的是,上面呈現的是「數字」,可是我們想要用圖片的方式來呈現,就像我們網頁最上方所呈現的樣子。


首先,我們到p5.php,一樣進入設計欄位,然後插入圖片(下載圖檔)。

取消掉就可以

接著程式碼的地方,就會產生一段「插入圖片」的程式碼

開始寫php嘍,這時候我們要把圖片呈現出來,一樣要用echo,echo後面用雙引號框住,然後把原本裡面的雙引號都刪除。

這時候會看到剛剛插入的圖片,可是只有一張,而且不會跟著參觀人數而改變。
所以我們現在的目標是要「根據參觀人數的位數,顯示不同張數的圖片」,也就是說如果瀏覽人數是2位數,就只要出現兩張圖片;如果瀏覽人數是4位數,就出現四張圖片。

為了解決這樣的問題,我們要用到「回圈」,想不到吧!
回圈的寫法上一堂課也有學過,for(起始值;結束值;設定){回圈內容}

要怎麼用呢?我們的思考是這樣的,如果我們是一位數,則跑一次回圈(一張圖),兩位數,則跑兩次回圈(兩張圖)。

所以我們會碰到另一個問題─要怎麼判斷有幾位數呢

遇到問題的時候,趕快讓我們來問問谷哥吧!
搜尋「php 判斷字串數」,發現我們可以用strlen這個函數,網站裡面有一些簡單的教學,可以參考看看要怎麼用。

這時候我知道用strlen就可以判斷我們的字串有幾位數,然後我把這個變數稱為string。
並且寫入回圈中,起始值是1,一直到<=我們的字串數,每次都加1。因此,如果我們的2位數,就會跑兩次回圈(1~2);如果我們是4位數,就會跑四次回圈(1~4)。

這時候預覽網頁,你就會發現,現在圖片的數目根據字串的位數成數。
這時候雖然圖片的數目會根據字串位數改變,可是圖片的數字不會變阿!該怎麼辦呢?
我們必須要找到方法,讓電腦能夠幫我們擷取某位數的數值

這時候,我們又要請教谷哥大神了!

找到了,我們可以用substr這個函數,參考網站可以發現它的用法是substr(字串,起始值,讀幾位)。

我們來試試看吧,我把擷取出來的數字取名叫做變數n,並且把圖片的連結也改成變數n。
這個意思是,從num從0(最左邊)開始,向右擷取一個數值。

預覽結果會發現,因為從最左邊向右擷取1個,所以慧黠取到「1」這個數值,而且4個都是1,並沒有根據我們的參觀人數而變,代表我們寫的還不夠完整。
這時候,我們可以修正一下寫法,擷取字串的地方,根據回圈i來擷取(這裡要思考一下),當i是1時,會從左邊數來第一個擷取右邊一個;當i是2時,會從左邊數來第二個擷取右邊一個。

預覽一下,看起來好像不錯,但是還是有個bug,因為他不是從最左邊那個(0)開始擷取,而是從左邊數來第一個(1),所以第一個抓到的值是2,最後一個值就抓讀到了(4右邊沒數字了)
因此,我們要修正一下,把i變成從0開始,為了不要讓圖片數目多1,因此把<=改成<,這樣跑得回圈數也會是一樣的。

預覽看看!成功嘍!


加入session,避免瀏覽人數透過重新整理加以灌水
最後,我們會發現到,在這個網頁中,只要一直按重新整理,計數人數就會一直跑!這樣不就很容易可以灌水瀏覽人數了嗎?這到底該怎麼辦才好呢?

這時候,我們必須要用到SESSION這個指令,之後我們會在做更多關於SESSION的介紹,這裡先看看怎麼執行就好:

在語法的最上面要加上「session_start()」,表示開始session。

下面則是寫一段if語法,告訴電腦如果come不是v(第一次瀏覽的話come會沒東西,所以不會是v),則執行num++,也就是計數器加一,接著把它的come設成v,這樣在網友沒有關閉瀏覽器的情況下,他的come就會是v,下次進來的時候計數器就不會增加。

本次課程的完整語法如下:
<?php
session_start();
$file=fopen("p5.txt","r");
$num=fgets($file);
fclose($file);
if($_SESSION['come']!='v'){
 $num++;
 $file=fopen("p5.txt","w");
 fwrite($file,$num);
 fclose($file);
 $_SESSION['come']='v';
}
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>製作計數器</title>
</head>

<body>
參觀人數:
<?php
echo "$num";
$string=strlen($num);
for($i=0;$i<$string;$i++){
/* $n=substr($num,$i,1);*/
 echo '<img src=counter/'.substr($num,$i,1).'.png width=48 height=48 />';
}
?>
</body>
</html>


補充

1.也可以用這種寫法,把函示塞到echo裡面,這裡要注意的是雙引號裡面可以接變數,但是不能接函式,所以我們必須要用單引號框住前後,同時把含式用「.」和前後的字串連接。

2.更多關於php字串的函式可以參考這裡
來看看結果

以上內容均為本人在馬老師雲端研究室學習所整理之筆記

11 則留言:

  1. 哈囉 想請問一下~ 若把 PHP 跟 HTML 跟開寫
    PHP 要把 瀏覽人數的資料 傳到 HTML 的方法 怎麼實現呢!!?
    PHP怎麼丟 HTML 怎麼接 ~
    感恩感恩!

    回覆刪除
    回覆
    1. 不好意思,不是很懂你的意思,你指的PHP丟?是指用MYSQL資料庫嗎?還是什麼呢?

      刪除
  2. 請問一夏 如果我要把觀看人數 寫入資料庫 然後讀取觀看次數的時候是讀取資料庫的次數 要怎麼改呢?

    回覆刪除
    回覆
    1. 如果是寫到mySQL資料庫的話,那就會用到資料庫的語法去把資料寫入資料庫當中「mysql_query("insert into 資料表 (欄位名稱1,欄位名稱2,...) value(‘欄位1值’,’欄位2值’…..)")」,資料庫的寫入可以參考http://pjchender.blogspot.tw/2015/04/php-mysql-13.html 這篇的做法。

      刪除
  3. 請問一夏 如果我要把觀看人數 寫入資料庫 然後讀取觀看次數的時候是讀取資料庫的次數 要怎麼改呢?

    回覆刪除
  4. 您好,我依照session_start();語法輸入
    但是卻出現這樣的錯誤,想請問是為甚麼呢?
    Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at C:\AppServ\www\homework\p5-1.php:1) in C:\AppServ\www\homework\p5-1.php on line 2

    Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\AppServ\www\homework\p5-1.php:1) in C:\AppServ\www\homework\p5-1.php on line 2

    回覆刪除
    回覆
    1. 請問你在session_start()的上面有寫其他程式嗎?

      刪除
    2. -----


      感謝您抽空回我,這段程式碼,我將它放在整個程式最上面,
      沒使用session之前都是正確 但加入了session之後就出現問題了

      刪除
    3. session_start();
      $file=fopen("p5-1.txt","r");
      $count_man = fgets($file);
      fclose($file);

      if($_SESSION['come']!='v'){
      $count_man++;
      $file=fopen("p5-1.txt","w");
      fwrite($file,$count_man);
      fclose($file);
      $_SESSION['come']='v';
      }

      刪除
    4. 我找到問題了,是因為檔首BOM的關係,我搞定了^^

      刪除