【PHP程式設計+MySQL資料庫+PHPMaker整合教學+技術諮詢】 本月特價優惠中! 動態的架站程式時代,要自訂PHP程式頁面有那麼難嗎? MySQL『資料庫』與『資料表』,用PHP程式有那麼難控制嗎? 你不用死背『PHP程式』與『MySQL資料庫』語法也能獨自設計完成! 這是自動化軟體程式的年代 (用PHPMaker 設計在彈指之間就能自動生成整個 PHP 程式系統) 這不是:神話!程式軟體模組取代了這一切複雜的工程。 你可以自己建構自己專屬的: 訂購表單、會員名單、擴增購物車特殊頁面 →POS 系統、CRM 系統、ERP 系統、HRM 系統...等等 (更可以加入數據資源銷售賺錢!) 該是:【見證奇蹟】的時候了! 非親眼所見....真的無法相信此神兵利器!

php程式教學

PHP程式設計員入門必讀:

1.概要:學習任何語系都需要多看、多想、多寫、多問!
寫寫程式是一種熟能生巧的東西!
學習PHP也一樣,因為知識就那麼多,你看多了就會覺得怎麼都一樣。

程式員就是炒冷飯的,一遍又一遍。
代碼多敲幾遍就可以閉著眼睛寫了,所以企業招聘都會問你寫過多少行代碼的!
程式員最忌諱浮躁,有時候發現一段程式完全找不出錯誤,僅僅是因為少了或多了一個符號,程式員需要的是細心,粗心的人當不了程式員!

2.php參考手冊是必須熟知的,有的新手會問一些很基礎的問題,其實手冊上面都有,所以建議新手先把手冊看了,最好把常用函數抄幾遍!
再敲幾遍手冊裡的代碼。

當你把手冊裡的東西都熟悉了,你遇到問題的可能性就很小了。
當然mysql手冊,也要看一下,但可以不先看的那麼細!至少要知道常用的sql語句,這是必須的!

3.覺得php最好的東西就是,網上能找的開源項目很多,而且一些都是大項目的。
所以建議php程式新手可以看留言板代碼,先熟悉常用的資料操作,然後可以去看一下簡單的企業網站或是部落格,然後可以去研究一下ecshop之類,當你看懂這些 ,你可以去看看discuz,phpwind論壇源程式碼,帝國,PHP168等開源CMS系統,裡面的架構都是相當強悍的,當然這不是新手需要去做的,但是總要有個做將軍的理想!

4.要習慣,遇到問題自己先解決,在網路時代,要學會用百度,這是必須的。
當你實在沒法解決的時候再去尋求別人的說明!

5.當你寫完一個程式的時候,要學會分享出去,因為你是新手,你的程式也許會有很多不完善的地方,所以分享你寫的程式對你更有益!
多分享多交流!才會讓你寫的程式更精!

6.記住,學了php你要不只是學會php,你要學會分析一個項目的實現模式或是一個程式的實現模式。
都說算法是語系的基礎,要學好php,你還得去學習和運用算法去實現你的程式,學會用算法可以用於任何語系,學會用php你只能用php.

問題:
請問為什麼我向另一網頁傳送變數時,只得到前半部分,以空格開頭的則全部丟失?

<?php
$Var=”hello php”;//修改為$Var=”   hello php”;試試得到什麼結果
$post= “receive.php?Name=”.$Var;
header(“location:$post”);
?>

receive.php的內容:

<?PHP
Echo “<pre>”;
Echo  $_GET[“Name”];
Echo “</pre>”;
?>

回覆:
正確的方法是:

<?php
$Var=”hello php”;
$post= “receive.php?Name=”.urlencode($Var);
header(“location:$post”);
?>

在接收頁面你不需要使用Urldecode(),變數會自動編碼.

PHP程式設計問題諮詢:
請問,如何從資料庫讀取三天內的所有記錄?

———————————————————
PHP程式設計問題回覆:
您要如何從資料庫讀取三天內的所有記錄,可以參考以下的說明:

———————————————————
首先表格裏要有一個DATETIME欄位記錄時間,
格式為'2012-6-12 16:50:00'

SELECT * FROM `xltxlm` WHERE TO_DAYS(NOW()) – TO_DAYS(`date`) <= 3;

———————————————————

當magic_quotes_gpc=off

Pstzine0x03裡”[0x06] 高級PHP代碼審核技術”一文中關於 “5.3.6 變數key與魔術引號” 部分的php原始程式碼分析

author: ryat#www.wolvez.org
team:http://www.80vul.com
date:2009-04-10

一、綜述

magic_quotes_gpc是php中的一個安全選項,在php manual中對此有如下描述:

When on, all ‘ (single-quote), ” (double quote), (backslash) and NULL characters are escaped with a backslash automatically. This is identical to what addslashes() does

雖然magic_quotes_gpc有助於提升程式的安全性並且在php中默認開啟,但同時也帶來了其他的一些問題,因此在php6中將去掉此選項。

二、當magic_quotes_gpc=off

考慮到部分伺服器關閉了magic_quotes_gpc或者其他的一些原因[如影響功能等],很多程式在如magic_quotes_gpc=off下自己實現一個代碼來類比magic_quotes_gpc=on的情況. 如下面的一段代碼:

define(‘MAGIC_QUOTES_GPC’, get_magic_quotes_gpc());

foreach(array(‘_COOKIE’, ‘_POST’, ‘_GET’) as $_request) {

foreach($$_request as $_key => $_value) {

$_key{0} != ‘_’ && $$_key = daddslashes($_value);

}

}

function daddslashes($string, $force = 0) {

!defined(‘MAGIC_QUOTES_GPC’) && define(‘MAGIC_QUOTES_GPC’, get_magic_quotes_gpc());

if(!MAGIC_QUOTES_GPC || $force) {

if(is_array($string)) {

foreach($string as $key => $val) {

$string[$key] = daddslashes($val, $force);

}

} else {

$string = addslashes($string);

}

}

return $string;

}

利用addslashes()函數類比了magic_quotes_gpc=on時的效果,看上去很完美,其實是有缺陷的或者說只是類比了magic_quotes_gpc的部分功能.

三、magic_quotes_gpc的代碼分析

php在註冊$_GET/$_POST等超全域變數時magic_quotes_gpc部分的代碼:

// php_variables.c

PHPAPI void php_register_variable_safe(char *var, char *strval, int str_len, zval *track_vars_array TSRMLS_DC)

{

// 對變數值的處理

if (PG(magic_quotes_gpc)) {

Z_STRVAL(new_entry) = php_addslashes(strval, Z_STRLEN(new_entry), &Z_STRLEN(new_entry), 0 TSRMLS_CC);

} else {

Z_STRVAL(new_entry) = estrndup(strval, Z_STRLEN(new_entry));

}

PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array TSRMLS_DC)

{

// 對變數名的處理

zend_bool is_array = 0;

for (p = var; *p; p++) {

if (*p == ‘ ‘ || *p == ‘.’) {

*p=’_’;

} else if (*p == ‘[‘) {

is_array = 1;

ip = p;

*p = 0;

break;

}

}

var_len = p – var;

// 上面這段代碼沒有考慮變數名的原始長度,所以這裡是not binary safe

// 也就是說,提交 test.php?ryat%00wst=1 將會生成$_GET[‘ryat’]=1

if (is_array) {

// 如果變數名是陣列的形式

} else {

// php > 5.2.1

if (PG(magic_quotes_gpc)) {

// php = 4.x && php <= 5.2.1

// if (PG(magic_quotes_gpc) && (index!=var)) {

escaped_index = php_addslashes(index, index_len, &index_len, 0 TSRMLS_CC);

} else {

escaped_index = index;

}

} else {

// 這部分的magic_quotes_gpc處理和上面一樣

由上面的代碼可以看到,magic_quotes_gpc=on時不僅僅用addslashes處理了變數值,而且處理了變數名[既$_GET/$_POST等超全域變數的key,另外要注意的是:[1]在php4和php<5.2.1的版本中,不處理第一維的key:)]

而前面那段模擬magic_quotes_gpc的代碼僅僅處理了陣列的值,因此是存在安全隱患的。

四、實例[ECShop SQL injection 漏洞分析]

文件includes/init.php判斷get_magic_quotes_gpc(),如果為off則調用addslashes_deep():

// includes/init.php

if (!get_magic_quotes_gpc())

{

if (!empty($_GET))

{

$_GET = addslashes_deep($_GET);

}

if (!empty($_POST))

{

$_POST = addslashes_deep($_POST);

}

$_COOKIE = addslashes_deep($_COOKIE);

$_REQUEST = addslashes_deep($_REQUEST);

}

addslashes_deep()在文件includes/lib_base.php裡最後通過addslashes()處理

// includes/lib_base.php

function addslashes_deep($value)

{

if (empty($value))

{

return $value;

}

else

{

return is_array($value) ? array_map(‘addslashes_deep’, $value) : addslashes($value);

// 只處理了陣列的值:)

}

}

下面看下具體的導致漏洞的代碼,文件 pick_out.php裡:

// pick_out.php

if (!empty($_GET[‘attr’]))

{

foreach($_GET[‘attr’] as $key => $value)

{

$key = intval($key);

$_GET[‘attr’][$key] = htmlspecialchars($value);

// foreach處理的是指定陣列的拷貝,所以這裡的處理並不影響陣列原先的key和value

// 因此可以引入任意的key:)

// 程式師的邏輯出了問題?

}

}

foreach ($_GET[‘attr’] AS $key => $value)

{

$attr_url .= ‘&attr[‘ . $key . ‘]=’ . $value;

$attr_picks[] = $key;

if ($i > 0)

{

if (empty($goods_result))

{

break;

}

// 利用key進行注射:)

$goods_result = $db->getCol(“SELECT goods_id FROM ” . $ecs->table(“goods_attr”) . ” WHERE goods_id IN (” . implode(‘,’ , $goods_result) . “) AND attr_id=’$key’ AND attr_value=’$value'”);

由於magic_quotes_gpc=off時沒有對$key處理,同時在陣列賦值時存在邏輯問題,最終導致了注射漏洞:)

EXP:

http://www.80vul.com/exp/ecshop-pch-005.txt

五、參考:

http://bugs.php.net/bug.php?id=41093

PHP程式設計問題諮詢:
請問,如何計算現用的線上人數?

———————————————————
PHP程式設計問題回覆:
您要計算現用的線上人數?,可以參考以下的說明:

———————————————————
計算現用的線上人數

例子一:用文字實現
<?php
//首先你要有讀寫檔的許可權
//本程式可以直接運行,第一次報錯,以後就可以
  $online_log = "count.dat"; //儲存人數的檔,
  $timeout = 30;//30秒內沒動作者,認為掉線
  $entries = file($online_log);

  $temp = array();
 
  for ($i=0;$i<count($entries);$i++) {
   $entry = explode(",",trim($entries[$i]));
   if (($entry[0] != getenv('REMOTE_ADDR')) && ($entry[1] > time())) {
    array_push($temp,$entry[0].",".$entry[1]."
"); //取出其他流覽者的資訊,並去掉逾時者,儲存進$temp
   }
  }

   array_push($temp,getenv('REMOTE_ADDR').",".(time() + ($timeout))."
"); //更新流覽者的時間
  $users_online = count($temp); //計算線上人數

  $entries = implode("",$temp);
  //寫入檔案
  $fp = fopen($online_log,"w");
   flock($fp,LOCK_EX); //flock() 不能在NFS以及其他的一些網路檔系統中標準工作
   fputs($fp,$entries);
   flock($fp,LOCK_UN);
   fclose($fp);

   echo "現用的有".$users_online."人線上";

?>  
例子二:
用資料庫實現線上使用者

<?
#
# Author: Marco(hkfuk)
#
# Contact: Crazy_Marco@msn.com
#
$host="localhost";//mysql的host
$user="root";//mysql的使用者名稱
$pw="";//mysql的密碼
$db="";//mysql資料庫名稱
$update_time="30";//更新的頻率—秒數
session_start();
if(!$_SESSION['name'])session_register("name");
############################################
$con=mysql_connect($host,$user,$pw)or die("不可以連線資料庫");
$now=time();
mysql_select_db($db,$con)or die("錯誤的資料庫$db");
if(!empty($name)){//如果使用者已經登入了
$query=mysql_query("select count(username) from online_list where username='$name'",$con);//查詢線上到表是否已經有使用者的名稱
$result=mysql_result($query,0);//查詢的結果
if($result!=0){//如果使用者已經在線上清單了
@mysql_query("update online_list set second_time='$now' where username='$name'",$con);//更新使用者的最後線上時間
}else{//如果使用者已經不在線上清單
@mysql_query("insert into online_list(username,userip,online_time,second_time)values('$name','$REMOTE_ADDR','$now','$now')",$con);// 新增一個使用者到線上清單
}
}

else{//如果使用者沒有登入
$query=mysql_query("select count(userip) from online_list where userip='$REMOTE_ADDR'",$con);//查詢線上到表是否已經有訪客的ip 位址
$result=mysql_result($query,0);//查詢的結果
if($result!=0){//如果訪客的ip位址已經在線上清單了
@mysql_query("update online_list set second_time='$now' where userip='$REMOTE_ADDR'",$con);//更新訪客的最後線上時間
}else{//如果使用者清單沒有訪客的ip位址
@mysql_query("insert into online_list(username,userip,online_time,second_time)values('訪客 ','$REMOTE_ADDR','$now','$now')",$con);//新增一個訪客到線上清單
}
}
$del_time=$now-$update_time;
@mysql_query("delete from online_list where second_time<$del_time",$con);//刪除在$update_time秒內沒有動作的使用者
?>

———————————————————

您想要使用PHP程式語法下載CSS檔案中的圖片嗎?
我相信每個做web的程式員也都會有類似的需求與想法。

在PHP下載CSS檔案中的圖片過程中,必不可少的需要下載樣式檔案中的圖片。
碰到比較龐大的樣式檔案,其中可能會有上百個需要下載的圖片,那麼使用下面這段小代碼是最為合適的了。
——————————————————————–
< ?php
/*
More & Original PHP Framwork
Copyright (c) 2007 – 2008 IsMole Inc.

Author: kimi
Documentation: 下載樣式檔案中的圖片,PHP下載CSS檔案中的圖片工具
*/

//note 設定PHP逾時時間
set_time_limit(0);

//note 取得樣式檔案內容
$styleFileContent = file_get_contents(‘images/style.css’);

//note 符合出需要下載的URL位址
preg_match_all(“/url((.*))/”, $styleFileContent, $imagesURLArray);

//note 迴圈需要下載的位址,逐個下載
$imagesURLArray = array_unique($imagesURLArray[1]);
foreach($imagesURLArray as $imagesURL) {
file_put_contents(basename($imagesURL), file_get_contents($imagesURL));
}
—————————————————–

問題:
請問在PHP網頁出現以下的錯誤:

Warning: session_start(): open(/tmpsess_7d190aa36b4c5ec13a5c1649cc2da23f, O_RDWR) failed:….
這是什麼錯誤?

回覆:
因為你沒有指定session檔的存放路徑.

  解決方法:

(1)在c硬碟建立文件夾tmp

(2)打開php.ini,找到session.save_path,修改為session.save_path= "c:/tmp"

用單引號代替雙引號來包括字串,這樣做會更快一些。
因為PHP會在雙引號包圍的字串中搜尋變量,單引號則不會
注意:只有echo能這麼做,它是一種可以把多個字串當作參數的「函數」
(譯註:PHP手冊中說echo是語系結構,不是真正的函數,故把函數加上了雙引號)。

1.如果能將類的方法定義成static,就盡量定義成static,它的速度會提升將近4倍。

2.$row[』id』] 的速度是$row[id]的7倍。

3.echo 比 print 快,並且使用echo的多重參數
(譯註:指用逗號而不是句點)代替字串連線,比如echo $str1,$str2。

4.在執行for迴圈之前確定最大迴圈數,不要每迴圈一次都計算最大值,最好運用foreach代替。

5.註銷那些不用的變量尤其是大陣列,以便釋放記憶體。

6.盡量避免使用__get,__set,__autoload。

7.require_once()代價昂貴。

8.include檔案時盡量使用絕對路徑,因為它避免了PHP去include_path裡尋找檔案的速度,解析操作系統路徑所需的時間會更少。

9.如果你想知道腳本開始執行(譯註:即伺服器端收到用戶端請求)的時刻,使用$_SERVER[『REQUEST_TIME』]要好於time()。

10.函數代替正則表達式完成相同功能。

11.str_replace函數比preg_replace函數快,但strtr函數的效率是str_replace函數的四倍。

12.如果一個字串置換函數,可接受陣列或字元作為參數,並且參數長度不太長,那麼可以考慮額外寫一段置換代碼,使得每次傳遞參數是一個字元,而不是只寫一行代碼接受陣列作為查詢和置換的參數。

13.使用選取分支語句(譯註:即switch case)好於使用多個if,else if語句。

14.用@屏蔽錯誤訊息的做法非常低效,極其低效。

15.開啟apache的mod_deflate模組,可以提高網頁的瀏覽速度。

16.資料庫連線當使用完畢時應關掉,不要用長連線。

17.錯誤訊息代價昂貴。

18.在方法中遞增局部變量,速度是最快的。幾乎與在函數中呼叫局部變量的速度相當。

19.遞增一個全局變量要比遞增一個局部變量慢2倍。

20.遞增一個對像屬性(如:$this->prop++)要比遞增一個局部變量慢3倍。

21.遞增一個未預定義的局部變量要比遞增一個預定義的局部變量慢9至10倍。

22.僅定義一個局部變量而沒在函數中呼叫它,同樣會減慢速度(其程度相當於遞增一個局部變量)。PHP大概會檢檢視是否存在全局變量。

23.方法呼叫看來與類中定義的方法的數量無關,因為我(在測試方法之前和之後都)加入了10個方法,但效能上沒有變化。

24.派生類中的方法運行起來要快於在基類中定義的同樣的方法。

25.呼叫帶有一個參數的空函數,其花費的時間相當於執行7至8次的局部變量遞增操作。類似的方法呼叫所花費的時間接近於15次的局部變量遞增操作。

26.Apache解析一個PHP腳本的時間要比解析一個靜態HTML頁面慢2至10倍。盡量多用靜態HTML頁面,少用腳本。

27.除非腳本可以快取,否則每次呼叫時都會重新編譯一次。引入一套PHP快取機制通常可以提升25%至100%的效能,以免除編譯開銷。

28.盡量做快取,可使用memcached。memcached是一款高效能的記憶體對像快取系統,可用來加速動態Web應用程式,減輕資料庫負載。對操作碼 (OP code)的快取很有用,使得腳本不必為每個請求做重新編譯。

29.當操作字串並需要檢驗其長度是否滿足某種要求時,你想當然地會使用strlen()函數。此函數執行起來相當快,因為它不做任何計算,只返回在zval 結構(C的內建資料結構,用於存儲PHP變量)中存儲的已知字串長度。但是,由於strlen()是函數,多多少少會有些慢,因為函數呼叫會經由諸多步驟,如字母小寫化(譯註:指函數名小寫化,PHP不區分函數名大小寫).哈希尋找,會跟隨被呼叫的函數一起執行。在某些情況下,你可以使用isset() 技巧加速執行你的代碼。

(舉例如下)
if (strlen($foo) < 5) { echo 「Foo is too short」$$ }
(與下面的技巧做比較)
if (!isset($foo{5})) { echo 「Foo is too short」$$ }

呼叫isset()恰巧比strlen()快,因為與後者不同的是,isset()作為一種語系結構,意味著它的執行不需要函數尋找和字母小寫化。也就是說,實際上在檢驗字串長度的頂層代碼中你沒有花太多開銷。

34.當執行變量$i的遞增或遞減時,$i++會比++$i慢一些。這種差異是PHP特有的,並不適用於其他語系,所以請不要修改你的C或Java代碼並指望它們能立即變快,沒用的。++$i更快是因為它只需要3條指令(opcodes),$i++則需要4條指令。後置遞增實際上會產生一個臨時變量,這個臨時變量隨後被遞增。而前置遞增直接在原值上遞增。這是最改善處理的一種,正如Zend的PHP改善器所作的那樣。牢記這個改善處理不失為一個好主意,因為並不是所有的指令改善器都會做同樣的改善處理,並且存在大量沒有裝配指令改善器的際網路服務提供商(ISPs)和伺服器。

35.並不是事必面向對像(OOP),面向對像往往開銷很大,每個方法和對像呼叫都會消耗很多記憶體。

36.並非要用類實現所有的資料結構,陣列也很有用。

37.不要把方法細分得過多,仔細想想你真正打算重用的是哪些代碼?

38.當你需要時,你總能把代碼分解成方法。

39.盡量採用大量的PHP內建函數。

40.如果在代碼中存在大量耗時的函數,你可以考慮用C延伸的模式實現它們。

41.評估檢驗(profile)你的代碼。檢驗器會告訴你,代碼的哪些部分消耗了多少時間。Xdebug除錯器包括了檢驗程式,評估檢驗總體上可以顯示出代碼的瓶頸。

42.mod_zip可作為Apache模組,用來即時壓縮你的資料,並可讓資料傳輸量降低80%。

43.在可以用file_get_contents替代file.fopen.feof.fgets等系列方法的情況下,盡量用file_get_contents,因為他的效率高得多!但是要注意file_get_contents在開啟一個URL檔案時候的PHP版本問題;

44.盡量的少進行檔案操作,雖然PHP的檔案操作效率也不低的;

45.改善Select SQL語句,在可能的情況下盡量少的進行Insert.Update操作(在update上,我被惡批過);

46.盡可能的使用PHP內定函數(但是我卻為了找個PHP裡面不存在的函數,浪費了本可以寫出一個自訂函數的時間,經驗問題啊!);

47.迴圈內定不要聲明變量,尤其是大變量:對像(這好像不只是PHP裡面要注意的問題吧?);

48.多維陣列盡量不要迴圈嵌套賦值;

49.在可以用PHP內定字串操作函數的情況下,不要用正則表達式;

50.foreach效率更高,盡量用foreach代替while和for迴圈;

51.用單引號替代雙引號引用字串;

52.「用i+=1代替i=i+1。符合c/c++的習慣,效率還高」;

53.對global變量,應該用完就unset()掉;

     PHP星期幾取得代碼:

1 date("l");

2 //data就可以取得英文的星期比如Sunday

3 date("w");

4 //這個可以取得數字星期比如123,注意0是星期日

  取得中文星期幾:

1 $weekarray=array("日","一","二","三","四","五","六");

2 //先定義一個陣列

3 echo "星期".$weekarray[date("w")];

  取得指定日期是:

1 $weekarray=array("日","一","二","三","四","五","六");

2 echo "星期".$weekarray[date("w","2011-11-11")];

因為date函數非常強大,他完全可以勝任一切這樣的工作我附個手冊裡的表吧 方便隨時查閱

1 a – "am" 或是 "pm"

2 A – "AM" 或是 "PM"

3 d – 幾日,二位數字,若不足二位則前面補零; 如: "01" 至 "31"

4 D – 星期幾,三個英文字母; 如: "Fri"

5 F – 月份,英文全名; 如: "January"

6 h – 12 小時制的小時; 如: "01" 至 "12"

7 H – 24 小時制的小時; 如: "00" 至 "23"

8 g – 12 小時制的小時,不足二位不補零; 如: "1" 至 12"

9 G – 24 小時制的小時,不足二位不補零; 如: "0" 至 "23"

10 i – 分鐘; 如: "00" 至 "59"

11 j – 幾日,二位數字,若不足二位不補零; 如: "1" 至 "31"

12 l – 星期幾,英文全名; 如: "Friday"

13 m – 月份,二位數字,若不足二位則在前面補零; 如: "01" 至 "12"

14 n – 月份,二位數字,若不足二位則不補零; 如: "1" 至 "12"

15 M – 月份,三個英文字母; 如: "Jan"

16 s – 秒; 如: "00" 至 "59"

17 S – 字尾加英文序數,二個英文字母; 如: "th","nd"

18 t – 指定月份的天數; 如: "28" 至 "31"

19 U – 總秒數

20 w – 數字型的星期幾,如: "0" (星期日) 至 "6" (星期六)

21 Y – 年,四位數字; 如: "1999"

22 y – 年,二位數字; 如: "99"

23 z – 一年中的第幾天; 如: "0" 至 "365"

要如何在延伸裡呼叫PHP函數呢?在寫延伸的時候,肯定不能什麼功能都自己實現,原因有很多,開發效率、效能問題、維護成本等。

這就避免不了要在延伸裡呼叫PHP內核函數。

那麼如何在延伸裡面使用我們的內建函數呢?

PHP既然有函數,肯定提供了呼叫函數的介面,

這裡有兩個函數:

ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC);

ZEND_API int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC);

很可惜,只找到聲明的地方,沒有找到註釋的地方,

從聲明來看,call_user_function 封裝了call_user_function_ex,

少了兩個傳參:

int no_separation:這個的用意就是是否對zval進行分離,不過此功能現在已經不用了,如果設為1則直接會出錯,分離的作用是為了改善空間。

symbol_table :是幹嗎用的,確實目前還不知道。

HashTable* function_table: 函數表,我們都知道 使用者函數也好,其他內建函數也好都會存在hashtable裡面,function_table會儲存所有內建函數和使用者函數,用CG來取得,因為函數表屬於是 編譯全局變量。

zval **object_pp:這個是用來我們呼叫類裡的某個方法的對象,看到這裡,你恍然大悟沒有,呼叫普通函數和呼叫類的方法是同一個,
function_table和object_pp只需要一個就可以了。

zval **retval_ptr_ptr:是函數的返回值。

zend_uint param_count:函數/方法 的參數個數

zval **params[] :函數/方法的參數指標。

那麼清楚了兩個API的參數及呼叫方法之後,我們來測試一下,究竟如何來使用。

因為項目需要,要將PHP中SESSION儲存部分資料,不過總有個過期不能處理,這兒介紹一下session的過期設定,如果設定了session過期無效,請看下後面的解決辦法:

在PHP中,設定php.ini,找到session.gc_maxlifetime = 1440 #(PHP5預設24分鐘)

這裡你可以隨便設定一下過期時間.但是有人說設定以後,好像不起作用!

其實不是不起作用,而是因為系統預設:

session.gc_probability = 1

session.gc_divisor = 1000

garbage collection 有個概率的,1/1000就是session 1000次才有一次被回收。

只要你的訪問量大了,那就能達到回收的效果.

要不然你也可以設定一下session.gc_divisor 的值,

例如:session.gc_divisor = 1,這樣就能明顯的看到SESSION過期的效果了!

使用php程式的五個小技巧

php程式的一些小技巧,這些比較基礎,總結一下(如果你是老鳥那就當成複習吧)。

1. str_replace

str_replace是非常常常常常用的php函數,用於字串置換,經常看到某些php新人為了置換一批字串,寫了好多行str_replace,實在是慘不忍睹。

比如這個例子:

$str = ‘某人的棲息地 — www.abc.net’;

$str = str_replace(‘某人’, ‘壞人’, $str);

$str = str_replace(‘的’, ‘di’, $str);

$str = str_replace(‘棲息地’, ‘豬窩窩’, $str);

$str = str_replace(‘www.abc.net’, ‘abc.net’, $str);

以上,置換了4次字串,實際只要換個寫法,一行就搞定了:

$str = ‘某人的棲息地 — www.abc.net’;

$str = str_replace(array(‘某人’, ‘的’, ‘棲息地’, ‘www.abc.net’), array(‘壞人’, ‘di’, ‘豬窩窩’, ‘abc.net’), $str);

 

2. array

經常看到有人拿陣列這樣寫:

echo $arr[some_key];

上面這行代碼能跑,看上去也沒什麼大問題,但是如果你把php.ini的error notice開啟的話,會收到一大批error。
php解析器首先是拿「some_key」當作一個常量來解釋的,但如果沒有定義some_key這樣一個常量,解析器還是很寬容的把它當作了一個字串來看待。
因此新人同學們最好寫完整一點:

echo $arr[‘some_key’];

這樣就沒有問題了,如果你要把它放在雙引號中連用,也不能省掉引號,可以這樣寫:

echo “這是混在雙引號中的字串{$arr[‘some_key’]}”;

 

3. 類型戲法

類型戲法相當好用,比如有一個表單送出過來的變量,標準情況下它應該是整型的,有時候偷懶省去校驗的寫法可以是這樣的:

$intVar = (int)$_POST[‘post_var’];

再比如陣列,有時候寫鍵值要打引號是不是很不爽啊,我們可以把它轉換成object,比如:

$arr = array(‘name’ => ‘volcano’, ‘sex’ => ‘male’);

$arr = (object)$arr;

echo $arr->name;

echo $arr->sex;

是不是很省事?

 

4. lambda函數

lamda函數和array_*系列函數使用有奇效,拿php手冊上的一個例子來說:

<?php

$av = array(“the “, “a “, “that “, “this “);

array_walk($av, create_function(‘&$v,$k’, ‘$v = $v . “mango”;’));

print_r($av);

?>

至少省了一個for迴圈

 

5. 嵌套迴圈顯示表格的單元格

嵌套迴圈顯示表格的單元格,這是一個很老的話題哦,往往會要在某個單元格後邊加個條件判斷什麼的,考慮是不是要輸出tr抑或是td標籤。

俺這裡介紹一個辦法,利用array_chunk函數能夠比較工整的輸出html,見下例,這個例子要輸出一個4行6列的表格:

<?php

$arr = range(1, 24); //這個會生成一個陣列array(1,2,3,4….24)

$arr = array_chunk($arr, 6);

// output table

?>

<table> <?php foreach($arr as $row): ?> <tr> <?php foreach($row as $col):?> <td><?php echo $col?></td> <?php endforeach;?> </tr> <?php endforeach;?> </table>

PHP程式設計問題諮詢:
請問,我想知道他是通過哪個網站連接到本頁?

———————————————————
PHP程式設計問題回覆:
您想知道他是通過哪個網站連接到本頁,可以參考以下的範例:

<?php
//必須通過超級連接進入才有輸出
Echo $_SERVER['HTTP_REFERER'];
?>

PHP程式設計問題諮詢:
請問,如何取得用戶的真實IP?

———————————————————
PHP程式設計問題回覆:
您要取得用戶的真實IP,可以參考以下的範例:

———————————————————

<?
function iptype1 () {
if (getenv("HTTP_CLIENT_IP")) {
   return getenv("HTTP_CLIENT_IP");
}
else {
   return "none";
}
}
function iptype2 () {
if (getenv("HTTP_X_FORWARDED_FOR")) {
   return getenv("HTTP_X_FORWARDED_FOR");
}
else {
   return "none";
}
}
function iptype3 () {
if (getenv("REMOTE_ADDR")) {
   return getenv("REMOTE_ADDR");
}
else {
   return "none";
}
}
function ip() {
$ip1 = iptype1();
  $ip2 = iptype2();
$ip3 = iptype3();
if (isset($ip1) && $ip1 != "none" && $ip1 != "unknown") {
   return $ip1;
}
elseif (isset($ip2) && $ip2 != "none" && $ip2 != "unknown") {
   return $ip2;
}
elseif (isset($ip3) && $ip3 != "none" && $ip3 != "unknown") {
   return $ip3;
}   
  else {
  return "none";
}
}

Echo ip();
?>  

———————————————————

PHP程式設計問題諮詢:
怎麼在圖片裏顯示IP位址?

———————————————————
PHP程式設計問題回覆:
怎麼在圖片裏顯示IP位址,可以參考以下的範例:

———————————————————
<?
  Header("Content-type: image/png");
  $img = ImageCreate(180,50);
  $ip = $_SERVER['REMOTE_ADDR'];
  ImageColorTransparent($img,$bgcolor);
  $bgColor = ImageColorAllocate($img, 0x2c,0x6D,0xAF); // 背景顏色
  $shadow = ImageColorAllocate($img, 250,0,0);    // 陰影顏色
  $textColor = ImageColorAllocate($img, oxff,oxff,oxff);       // 字體顏色
  ImageTTFText($img,10,0,78,30,$shadow,"d:/windows/fonts/Tahoma.ttf",$ip); //顯示背景
  ImageTTFText($img,10,0,25,28,$textColor,"d:/windows/fonts/Tahoma.ttf","your ip is".$ip); // 顯示IP
  ImagePng($img);
  imagecreatefrompng($img);
  ImageDestroy($img);
?>
———————————————————

學員來函諮詢:
老師您好:
好久不見,有一個問題想請教您,最近有接觸到一個倉儲的業務,是有關於管理進出貨的
不知道有沒有相關PHP的軟體可以處理,詳細的說明請見附檔
謝謝
祝:安康

——————————————————————
洪總教頭回覆:
可以用此教學:課程中的PHPMaker快速生成PHP網站
 
 PHP程式設計+MySQL資料庫+Dreamweaver整合教學(PHPMaker運用設計網站教學):

http://por.tw/php/new-E_learning/index.php
 
———————————————————————————
用PHPMaker快速生成PHP網站管理進出貨的好處:
1.生成管理進出貨是網路網站,只要能上網,有帳號與密碼任何人都可以瀏覽
(有管理者權限者,可以進階新增、修改、搜尋甚至刪除)
2.解決個人電腦版進銷存的缺點
3.快速生成(不用花很多時間設計)更不用花錢購買套裝進銷存軟體
(買軟體萬一日後不能更新或擴增…不合用就變成:垃圾!)
4.獨家系統(依據自己需要設計欄位,不會有一般進銷存用不到的雜七雜八選項或欄位的缺點)
5.可以自由擴增,不會受制於人或被套裝軟體綁死。

PHP程式設計問題諮詢:
請問,怎麼讓程式一直運行下去,而不是超過30秒就停止?

———————————————————
PHP程式設計問題回覆:
您要讓程式一直運行下去,而不是超過30秒就停止,可以參考以下的說明:

———————————————————
怎麼讓程式一直運行下去,而不是超過30秒就停止?

set_time_limit(60)//最長運行時間一分鐘
set_time_limit(0)//運行到程式自己結束,或手動停止

———————————————————

PHP程式設計問題諮詢:
我怎麼知道系統預設支援什麼函數?

———————————————————
PHP程式設計問題回覆:
要怎麼知道系統預設支援什麼函數,請看以下的範例:

<?php
$arr = get_defined_functions();
Function php() {
}
echo  "<pre>";
Echo  "這裏顯示系統所支援的所有函數,和自定以函數php ";
print_r($arr);
echo  "</pre>";
?>

———————————————————

問題:我在一網頁向另一網頁POST資料name,為什麼輸出$name時卻得不到任何值?

技術回覆:在PHP4.2以後的版本中register_global預設為off

  若想取得從另一頁面送出的變數:

方法一:在PHP.ini中找到register_global,並把它設定為on.

方法二:在接收網頁最前面放上這個extract($_POST);extract($_GET);(注意extract($_SESSION)前必須要有Session_Start()).

方法三:一個一個讀取變數$a=$_GET["a"];$b=$_POST["b"]等,這種方法雖然麻煩,但比較安全.

  2:除錯你的程式

在運行時必須知道某個變數為何值。我是這樣做的,建立一檔案debug.php,其內容如下:

<?PHP
Ob_Start();
Session_Start();
Echo "<pre>";

Echo "本頁得到的_GET變數有:";
Print_R($_GET);

Echo "本頁得到的_POST變數有:";
Print_R($_POST);

Echo "本頁得到的_COOKIE變數有:";

Print_R($_COOKIE);

Echo "本頁得到的_SESSION變數有:";
Print_R($_SESSION);
Echo "</pre>";
?>

然後在php.ini中設定:include_path = "c:/php",並將debug.php放在此檔夾,以後就可以在每個網頁裏包括此檔,檢視得到的變數名和值.

  3:如何使用session

凡是與session有關的,之前必須呼叫函數session_start();

為session付值很簡單,如:

<?php
Session_start();
$Name = "這是一個Session例子";
Session_Register("Name");//注意,不要寫成:Session_Register("$Name");
Echo $_SESSION["Name"];
//之後$_SESSION["Name"]為"這是一個Session例子"
?>

在php4.2之後,可以為session直接付值:

<?PHP
Session_Start();
$_SESSION["name"]="value";
?>

取消session可以這樣:

<?php
session_start();
session_unset();
session_destroy();
?>
取消某個session變數在php4.2以上還有BUG.

注意:

1:在呼叫Session_Start()之前不能有任何輸出.例如下面是錯誤的.
==========================================
1行
2行 <?PHP
3行 Session_Start();//之前在第一行已經有輸出
4行 …..
5行 ?>
==========================================

提示1:

凡是出現"……..headers already sent……….",就是Session_Start()之前嚮流覽器輸出資訊.
去掉輸出就標準,(COOKIE也會出現這種錯誤,錯誤原因一樣)

提示2:

如果你的Session_Start()放在迴圈語句裏,並且很難確定之前哪裡向流覽器輸出資訊,可以用下面這種方法:
1行 <?PHP Ob_Start(); ?>
……..這裏是你的程式……