狠狠爱成人网_日韩一级在线_国产综合自拍_亚洲精品韩国_亚洲视频导航_麻豆成人在线播放_欧美jjzz_一区在线视频观看_美脚丝袜一区二区三区在线观看_欧美91视频

當前位置:系統之家 > 技術開發教程 > 詳細頁面

細看PEAR的出錯處理

細看PEAR的出錯處理

更新時間:2024-04-11 文章作者:未知 信息來源:網絡 閱讀次數:

PEAR提供了強大的錯誤處理機制。這篇文章向你展示如何從這個系統中獲益。


許多程序已經使用了PEAR的包。許多PHP程序員或多或少的熟悉了PEAR中的錯誤處理。但是這個機制并不局限于PEAR的包——所有人都能在他們的類和程序中使用這些方法。

這篇文章被分為兩個部分:首先我們將看看類中用于錯誤處理的函數,然后我們將看看如何基于PEAR錯誤處理機制來處理錯誤。

我們的例子類稱為cvs2db,它把數據從CSV文件插入到數據庫的表中。因為數據可能是手寫的,他們的數據應該在插入之前先得到驗證——落實postcode。函數import()完成讀入,檢查和插入的工作;它返回損壞的記錄數目。如果返回的值大于0,出錯的記錄集能夠使用exportUnvalid()寫入到新的CSV文件中。典型的用法是這樣的:

<?php
$cd = new csv2db();
$dsn = 'mysql://root@localhost/csv2db';
if( 0 < $cd->import("./dat.csv", $dsn, 'address')) {
$cd->exportUnvalid("./dat2.csv");
}
?>


可能的錯誤包括:

要導入的CSV文件不存在,
連接到數據庫失敗,
記錄集損壞,以及CSV導出文件無法創建。

在提供錯誤信息的經典解決方案中你可能寫這樣的代碼:

<?php
$cd = new csv2db();
$dsn = 'mysql://root@localhost/csv2db';
$result = $cd->import("./dat.csv", $dsn, 'address')
switch($result) {
case FILE_NOT_OPENED:
...
break;
case DATABASE_ERROR:
...
break;
default:
if(0 < $result) {
$cd->exportUnvalid("./dat2.csv");
} else {
echo 'every thing ok!'
}
}
?>


這對于短的腳本來說是可接受的也是常用的辦法——但是對于錯誤處理經常受到關注的大程序來說不是這樣。傳統的可能性強迫類的作者做最終的決定!在大部分情況下,這個決定根據的是那時對類的調用而不是基于長期的使用和可重用代碼的思想。一個靈活的錯誤處理機制是可重用代碼的重要部分,PEAR Error API 就是這樣的一種受到良好測試的機制。


用戶眼中的類

除了那兩個函數之外,類提供了一套錯誤處理函數和一個自己的錯誤對象稱為DB2CVS_Error,它有一個特殊的本地化的錯誤信息的特性功能。

現在我將向你展示如何在錯誤發生時控制類的行為。

局部和全局錯誤處理

你用setErrorHandling()管理錯誤處理;這個函數需要兩個參數:第一個是錯誤模式,而第二個(可選的)參數是錯誤模式特定的選項。例如 setErrorHandling(PEAR_ERROR_PRINT, 'This error occurred %s') 還有 setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_WARNING)。


這個函數的調用方式是一般行為中最重要的:靜態還是實體。在類cvs2db中,我們能兩者都用來設置錯誤處理,所有這些調用有相同的結構——為類設置錯誤模式:

// per instance
$cd = new csv2db();
$cd->setErrorHandling(PEAR_ERROR_DIE):
// static
CVS2DB::setErrorHandling(PEAR_ERROR_DIE);
PEAR::setErrorHandling(PEAR_ERROR_DIE);


如果兩者給出同樣的結果,區別在哪?實體調用僅僅為那個類設置而靜態調用對于所有使用PEAR_Error或者從那個類派生的所有類起作用。這個也作用于第一個靜態命令CVS2DB::setErrorHandling(PEAR_ERROR_DIE)——雖然它看上去僅僅影響了cvs2db類。


總結:作為一個實體函數使用命令意味著僅僅為這個實體(局部)設置錯誤模式,而作為靜態函數來調用就是為整個腳本設置錯誤模式(全局)。


setErrorHandling() 和 raiseError()


兩個函數都能夠被靜態調用和作為實體的函數調用。記住怎樣的一個組合使得他們如何互相影響的很重要。

基本上是:setErrorHandling()的靜態調用僅僅影響raiseError()的靜態調用——setErrorHandling()作為實體函數僅僅影響raiseError()作為靜態函數調用。在類csv2db中,使用csv2db::setErrorHandling()來設置錯誤模式是不可行的,因為我們使用$this->raiseError(...)。解決這個聞天有一點小技巧——改寫raiseError():

function raiseError(...,$mode=null, $options=null,...) {
if($mode==null && $this->_default_error_mode!=null) {
$mode = $this->_default_error_mode;
$options = $this->_default_error_options;
}
return PEAR::raiseError(...,$mode, $options,...);
}


這樣,我們映射實體調用到靜態上,如果你用錯誤模式調用raiseError(),然后這個模式將會覆蓋這些設置——這里是指的是全局的設置。

你應當當心錯誤是如何被類拋出的,如果你不小心,這可能導致不可預期的副作用。


錯誤的模式

對錯誤模式的了解對于使用PEAR的錯誤處理來說是重要的。PEAR錯誤處理讓用戶能夠決定怎么去做——注意:下文中術語用戶指的的是實際使用PEAR_Error程序的開發者而不是瀏覽腳本結果或者網頁的用戶。我將詳細展示可能的錯誤模式。

PEAR_ERROR_DIE——將這個模式開啟,程序將終結并且將打印錯誤信息。可選的,你能定義一個printf()式的字符串,它能夠用于產生信息;首先'%s'在字符串中將替代儲存在錯誤對象中的錯誤信息。

PEAR_ERROR_PRINT——僅僅打印錯誤信息,包括用于PEAR_ERROR_DIE的同樣的可選用的字符串。

PEAR_ERROR_RETURN——當錯誤發生時的一般行為;你能用類提供isError()函數或者PEAR::isError()檢查錯誤。

$db->setErrorhandling(PEAR_ERROR_RETURN)
if(!csv2db::isError(0 < $d = $cd->import("./dat.csv", $dsn, 'address'))) {
if(!csv2db::isError($cd->exportUnvalid("./dat2.csv")) {
} else {
// handle error
}
} else {
// handle error
}


PEAR_ERROR_TRIGGER——這兒函數向PHP運行時錯誤行為一樣。你必須定義哪種錯誤應該發生:E_USER_NOTICE,E_USER_WARNING或者E_USER_ERROR。他們直接和PHP本身產生的信息相對應。請注意,在錯誤信息中錯誤發生的那行(xxx on line yy)指的是在PEAR.php中調用trigger_error的那行——而不是錯誤直接發生的那行。

PEAR_ERROR_CALLBACK——這是只在一個地方處理錯誤并且讓你得代碼不用考慮錯誤處理的最佳方式。它需要一個函數或者類函數來捕獲錯誤,你能寫一個listing 2中展示的那樣的腳本,其中可以看到類相關錯誤對象的好處:import()函數拋出一個CSV2DB_Error給基于CSV的錯誤和一個DB_Error對象給相關于數據庫訪問的錯誤。

Listing 2

$cd = new csv2db();
$cd->setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError');
$dsn = 'mysql://root@localhost/csv2db';
if( 0 < $d = $cd->import("./dat.csv", $dsn, 'address')) {
$cd->exportUnvalid("./dat2.csv");
}

function handleError($error) {
if(DB::isError($error) {
// handle database error
}
if(csv2db::isError($error) {
switch($error->getCode()) {
case FILE_NOT_OPENED :
...
break;
case CORRUPTED_RECORD :
...
break;
}
}
}


單個的錯誤處理

我們有兩種可能的錯誤:我們能夠忽略的錯誤(損壞的記錄),以及使得程序無法運行的錯誤(找不到文件或者打不開數據庫)。如果你在shell腳本中使用類,你可以讓腳本終止于第二類錯誤。

自然的,你可以寫 $cd->setErrorHandling(PEAR_ERROR_DIE)——但是這可能在如果損壞的記錄錯誤發生時導致問題。在這樣的情況下你需要對某個錯誤停用或者替換錯誤處理辦法的可能。解決辦法時expectError(),如果你傳遞一個錯誤代碼給這個函數,指定錯誤的錯誤模式將被單獨于缺省錯誤模式地設置為PEAR_ERROR_RETURN。

expectError()函數把傳遞來的錯誤代碼儲存在棧中,使用popExpected()移出最后傳遞的錯誤代碼。自從PHP 4.3之后你還能使用delExpect()了;這個函數從棧中刪除了指定錯誤代碼的匹配,你不需要關心位置了。

在實際使用中,是這樣的:

$cd->setErrorHandling(PEAR_ERROR_DIE);
...
$cd->expectError(CORRUPTED_RECORD);
$cd->import(...);
$cd->popExpect();


pushErrorHandling() 和 popErrorHandling() 用起來差不多;他們能夠暫時的控制錯誤處理。例如:如果在 exportUnvalid() 中的文件不能打開,你想要忽略錯誤:

PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$cd->exportUnvalid("./dat2.csv");
PEAR::popErrorHandling();


注意調用方法的區別!expectError()/popExpect()必須作為實體函數來調用——pushErrorHandling和popErrorHandling可以靜態調用。如果作為實體函數,那么他們僅僅影響那個實體。

用戶有很多可能性,這是否又意味著程序員要做很多的工作呢?是,是因為你要比return false做更多的事情;否,是因為PEAR Error API給你完成了很多工作。


一些關于錯誤處理的思考

作為好的程序員,你不應該從你的類的用戶眼中遮掩起確切的錯誤原因。這阻止了簡單的return false的用法;還要注意也可能被PHP自動型別轉換為0——這對于import()函數來說意味著所有的記錄都已經被正確插入了!簡單地終止腳本?,可能對于簡單地PHP shell腳本來說這是可以接受地,但是對于一個web程序來說是一個壞的選擇!而且,在記錄損壞的情況,錯誤是能夠被忽略的。什么不trigger_error()?這是一個可能的選擇,但是有兩個缺點:類的行為取決于php.ini的設置,而且對于類來說這種行為不常見。可能性能夠需要用額外的函數找出錯誤狀態。即使是所有類都提供了非標準的函數名,這還是有問題的,而且類的用戶看上去會忘記那樣的函數調用——正如郵件列表和新聞組中顯示的那樣。怎么辦?讓用戶決定PEAR錯誤處理API。PEAR錯誤系統被廣泛知道并且許多類已經使用了PEAR類;因而我們無論如何必須用PEAR錯誤處理機制——為什么不建立在其上呢?這避免了前面提到的問題并且給用戶提供了很大的可能性。看看Listing 1,它展示了csv2db類和它的錯誤對象的實現。它可能是有些讓人嚇到,但是我們將一行行地瀏覽源代碼。

Listing 1

<?php
require_once 'PEAR.php';
require_once 'DB.php';

define("FILE_NOT_OPENED", 10);
define("CORRUPTED_RECORD", 20);

class csv2db extends PEAR{

var $records=array();
var $unvalid=array();

function csv2db() {
$this->PEAR("CSV2DB_Error");
}

function import($file, $dsn, $table) {
$this->PEAR("CSV2DB_Error");
if($fp=@fopen($file, 'r')) {
while($data=fgetcsv($fp, 1024,';')) {
$this->records[]=$data;
}
fclose($fp);
} else {
return $this->raiseError(null, FILE_NOT_OPENED);
}

$unvalidCount=0;

$storeMode = $GLOBALS['_PEAR_default_error_mode'];
$storeOpts = $GLOBALS['_PEAR_default_error_options'];
$GLOBALS['_PEAR_default_error_mode'] = $this->_default_error_mode;
$GLOBALS['_PEAR_default_error_options'] = $this->_default_error_options;

$db = DB::connect($dsn);

$GLOBALS['_PEAR_default_error_mode']= $storeMode;
$GLOBALS['_PEAR_default_error_options'] = $storeOpts;

if(!DB::isError($db)) {
$db->setErrorHandling($this->_default_error_mode,
$this->_default_error_options);
$qp = $db->prepare("INSERT INTO $table VALUES (?, ?, ?, ?)");
foreach( $this->records as $record) {
if(preg_match('/d{5}/',$record[2])) {
$db->execute($qp, $record);
} else {
$unvalidCount++;
$this->unvalid[]=$record;
$this->raiseError(corrupted record, CORRUPTED_RECORD);
}
}
$db->disconnect();
} else {
return $db;
}
return $unvalidCount;
}

function exportUnvalid($file) {
if($fp=@fopen($file, "w")) {
foreach($this->unvalid as $data) {
fwrite($fp, implode(';', $data)."n", 1024);
}
fclose($fp);
} else {
return $this->raiseError(null,FILE_NOT_OPENED);
}
}

function isError($data) {
return (bool)(is_object($data) &&
(get_class($data) == 'CSV2DB_Error' ||
is_subclass_of($data, 'CSV2DB_Error')));
}
}

class CSV2DB_Error extends PEAR_Error {
var $msgs = array(
FILE_NOT_OPENED =>
array( 'de' =>"Datei konnte nicht ge?ffnet werden",
'en' => "File couldn't be opened"),
CORRUPTED_RECORD =>
array( 'de' =>"fehlerhafter Datensatz",
'en' => "corrupted record")
);

function CSV2DB_Error($message=null, $code = null, $mode = null,
$level = null, $debuginfo = null) {
$this->PEAR_Error(null, $code, $mode, $level, $debuginfo);
}

function getMessage($lang = "en") {
return $this->msgs[$this->code][$lang];
}
}
?>


自己的錯誤對象

有一個自己的錯誤類總是好的,雖然它可能對于這么一個小的類來說是太大的額外負擔——但是這個類僅僅是一個例子并且你從如果沒有錯誤對象需要很多代碼來實現的特性那兒獲益良多。好處是:首先錯誤是直接賦給類的;以及本地化變得更加容易。

類必須從PEAR_Error繼承而來,為的是保持我們的實現簡單,否則PEAR::isError()將不能正常工作。

實現包含了構造函數,其中沒有改變地把參數傳遞給了PEAR_Error地構造函數。

改寫getMessage()函數是提供本地化錯誤信息地關鍵。錯誤定西被定義為類的變量并且將取決于語言動態的賦值。這也將幫助消息聚集于一處——而不是把他們分散于整個主要類的源代碼中。

實現PEAR錯誤處理

你在文章的第一部分看到了我們的類提供了一堆函數——但是他們中的僅僅有四個是直接實現的。所有的相關函數的錯誤處理是由PEAR基類提供的。為了從所有那些錯誤處理特性中獲益,我們必須讓cvs2db類從PEAR基類繼承,也就是:class csv2db extends PEAR。

在前面的錯誤對象段落中,我從對isError()的解釋開始。覆蓋這個方法不是必要的,雖然它確實使得我們能夠直接檢查我們的錯誤類,并且使得錯誤跟蹤更加精確并且可能節約了幾毫秒。

類的構造函數僅僅只是用錯誤類名稱最為參數調用了父類的構造函數。這個調用注冊了我們的錯誤對象并且確保了我們的錯誤類在每次觸發錯誤的時候被使用。


raiseError

在import()和exportUnvalid()的函數體中對raiseError()的使用是值得注意的。這是創建錯誤的關鍵函數;PEAR提供兩個函數用于這個目的:raiseError() 和 throwError()。后一個自從PHP 4.3開始存活在并且是raiseError()的一個簡化變體,兩者行為是一致的;它們的參數在段落 'raiseError 和 throwError' 中描述。


raiseError 和 throwError

原型:

&raiseError( $message, $code, $mode, $options, $userinfo, $errorclass, $skipmessage)
&throwError( $message, $code, $userinfo)

Parameter Description
$message (string) The error message
$code (int) The error number
$mode (constant) Error mode
$options (mixed) Error mode specific parameters
$userinfo (mixed) additional data (ie. Debug information)
$errorclass (string) A class name


可選的你能夠把已經存在的錯誤對象傳遞給這些函數:

&raiseError($error_object)
&throwError($error_object)


如果你從源代碼比較這兩個函數的參數表你將看到類并沒有設置message參數——這是不必須的因為我們在錯誤類中用 getMessage() 函數賦給錯誤信息。而且,調用PEAR構造函數來引入你的錯誤類也是不必要的,你可以在對 raiseError() 調用中指定錯誤類。在腦子中記住這個選項!例如,如果你的類提供了靜態函數或者多于一個錯誤對象,你不能給你的類像我們在csv2db中做得那樣全局地設置它們。

raiseError() 和 throwError() 能夠被靜態地調用以及像 setErrorHandling() 那樣作為實體函數來調用。當你作不作靜態調用地時候做正確地決定是重要的——它直接影響了用戶如何用setErrorHandling()來錯作我們的類。留意 setErrorHandling() 和 raiseError(),這將避免你和你的用戶的頭疼。

從類的這個部分能夠看到全局和局部的錯誤設置和觸發的負面影響。

$storeMode = $GLOBALS['_PEAR_default_error_mode'];
$storeOpts = $GLOBALS['_PEAR_default_error_options'];
$GLOBALS['_PEAR_default_error_mode'] = $this->_default_error_mode;
$GLOBALS['_PEAR_default_error_options'] = $this->_default_error_options;

$db = DB::connect($dsn);

$GLOBALS['_PEAR_default_error_mode'] = $storeMode;
$GLOBALS['_PEAR_default_error_options'] = $storeOpts;


首先,全局的錯誤模式被保存了,然后全局的錯誤模式設置給了局部的錯誤模式并且最后幾行,原來的錯誤模式被還原了。為什么?Connect()是一個靜態函數!它必須使用PEAR::raiseError()。因而假如我們不保存并且還原設置,我們會遇到問題:看看listing 3——如果類在import()函數不能連接到數據庫的時候會發生什么?因為對raiseError()的靜態調用受到全局錯誤模式的影響,而不是局部的$cd->setErrorHandling(...)的影響,腳本終止執行 。實際上push和popErrorHandling()就是設計來用于這樣的任務的——但是PHP中一個現下的bug看上去不幸的組織了它很好的工作。

強制$db對象使用我們的錯誤模式是更舒服的方式,它支持完整的PEAR Error API,這使得代碼能這樣寫:$db->setErrorHandling($this->_default_error_mode, $this->_default_error_options)。兩個實體變量都是由PEAR_Error類提供的。

那行$this->raiseError(corrupted record, CORRUPTED_RECORD)看上去值得注意——而且缺失的返回看上去不順眼。原因是:我們不想在發現損壞的記錄時中止函數執行。你能把這個和觸發一個警告進行比照。唯一的限制時模式PEAR_ERROR_RETURN沒有工作。

Listing 3

<?php
...
PEAR::setErrorHandling(PEAR_ERROR_DIE)

$cd = new csv2db();
$cd->setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError');
$dsn = 'mysql://root@localhost/csv2db';
if( 0 < $d = $cd->import("./dat.csv", $dsn, 'address')) {
$cd->exportUnvalid("./dat2.csv");
}

$db = DB::connect($dsn);
$db->query(...);
...

function handleError($error) {
if(DB::isError($error) {
// handle database error
}
if(csv2db::isError($error) {
switch($error->getCode()) {
case FILE_NOT_OPENED :
...
break;
case CORRUPTED_RECORD :
...
break;
}
}
}
?>



PEAR錯誤處理和PHP 5

因為我們使用函數來創建錯誤,我們沒有考慮在PHP 5中的try/catch/throw機制;raiseMethod和throwError將為你完成這些!對于PHP 5,函數能夠為你的類透明地調用拋出PEAR_Error()——錯誤模式PEAR_ERROR_EXCEPTION能夠用于這個目的。一下的代碼應該能夠在不改變類的情況下用于PHP5中:

<?php
$i = new csv2db();
$dsn = 'mysql://root@localhost/csv2db';
try {
if( 0 < $d = $i->import("./dat.csv", $dsn, 'address')) {
$i->exportUnvalid("./dat2.csv");
}
}
catch CSV2DB_Error {
// fetch the error
}
?>


結論

我希望你大概了解了PEAR錯誤處理,它提供了排除和處理錯誤的強大機制?纯碢EAR手冊[1]的代碼部分并且找出這些函數提供的好處。

Alexander Merz (alexmerz at php dot net) 是PEAR手冊的編輯并且以自由創作者和作家為職業。

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統下載排行

狠狠爱成人网_日韩一级在线_国产综合自拍_亚洲精品韩国_亚洲视频导航_麻豆成人在线播放_欧美jjzz_一区在线视频观看_美脚丝袜一区二区三区在线观看_欧美91视频
在线电影一区| 国产女主播一区二区| 激情五月激情综合网| 偷拍与自拍一区| 水野朝阳av一区二区三区| 亚洲午夜影视影院在线观看| 依依成人精品视频| 一区二区三区丝袜| 亚洲色图在线播放| 亚洲国产精品影院| 亚洲成人动漫在线观看| 五月天中文字幕一区二区| 亚洲一区二区三区不卡国产欧美 | 337p粉嫩大胆色噜噜噜噜亚洲| 欧美日韩国产免费| 日韩丝袜情趣美女图片| www亚洲一区| 国产精品毛片高清在线完整版| 中文字幕日韩一区| 亚洲大尺度视频在线观看| 美美哒免费高清在线观看视频一区二区 | 久88久久88久久久| 成人午夜碰碰视频| 狠狠爱成人网| 久久美女性网| 欧美一二三四在线| 中文字幕免费不卡在线| 亚洲资源中文字幕| 蜜桃一区二区三区四区| 成人黄色av电影| 在线不卡亚洲| 欧美三级日韩三级国产三级| 欧美成人国产一区二区| 中文字幕一区免费在线观看| 日日夜夜精品视频免费| 成人爽a毛片一区二区免费| 欧美久久久久| 色婷婷综合久久久中文字幕| 日韩亚洲欧美一区二区三区| 中文字幕日本不卡| 久久精品99国产精品| 91视频免费看| 色中色一区二区| 久久久国产精品麻豆| 亚洲资源在线观看| av在线综合网| 麻豆精品网站| 久久久精品国产免费观看同学| 亚洲图片欧美视频| 不卡的av网站| 色久综合一二码| 日本一区二区三区久久久久久久久不| 亚洲自拍另类综合| 97久久精品人人做人人爽50路 | 久久婷婷成人综合色| 亚洲美女少妇撒尿| 懂色av一区二区三区免费观看| 亚洲一区三区电影在线观看| 日韩免费观看高清完整版| 亚洲福利一区二区| 欧美日本久久| 日韩精品一区二区在线| 亚洲电影第三页| 国产在线成人| www激情久久| 国产精选一区二区三区| 香蕉免费一区二区三区在线观看| 久久久精品蜜桃| 国产精品69久久久久水密桃| 性色一区二区三区| 中文字幕一区视频| 91丨porny丨在线| 91精品国产综合久久婷婷香蕉| 天天色 色综合| 亚洲精品1区2区| 国产欧美精品一区二区色综合| 国产成人三级在线观看| 色吊一区二区三区| 亚洲成a人片在线观看中文| 亚洲国产精品第一区二区三区| 久久精品免视看| 成人一级视频在线观看| 在线成人av网站| 日本不卡的三区四区五区| 亚洲综合不卡| 亚洲综合小说图片| 亚洲精品资源| 亚洲欧美偷拍三级| 亚洲午夜视频| 亚洲图片欧美激情| 亚洲黄色视屏| 亚洲免费在线播放| 一本色道久久精品| 亚洲欧美另类在线| 一区在线免费观看| 亚洲欧美综合在线精品| 在线成人h网| 亚洲人妖av一区二区| 黄色国产精品| 亚洲欧洲中文日韩久久av乱码| 在线免费观看欧美| 亚洲精选视频在线| 亚洲少妇自拍| 午夜av区久久| 欧美电影在哪看比较好| 国产乱理伦片在线观看夜一区| 91精品国产欧美一区二区| 韩国午夜理伦三级不卡影院| 69p69国产精品| 成人免费视频app| 国产亚洲短视频| 亚洲午夜精品久久| 一区二区成人在线视频 | 亚洲精品久久久蜜桃| 一区二区三区国产在线| 亚洲国产裸拍裸体视频在线观看乱了 | 亚洲每日在线| 亚洲成人在线免费| 欧美日韩综合色| 9色porny自拍视频一区二区| 国产婷婷一区二区| 日韩亚洲在线| 麻豆91在线播放| 欧美不卡在线视频| 国产一区二区三区四区老人| 亚洲尤物视频在线| 欧美高清你懂得| 欧美黄色一级视频| 亚洲一区二区三区在线看| 欧美三级视频在线观看| 99久久国产综合精品女不卡| 亚洲欧美日韩一区| 91久久精品一区二区三区| 成人福利在线看| 亚洲区小说区图片区qvod| 欧美色网一区二区| 欧美日韩国产免费观看| 午夜欧美2019年伦理| 日韩欧美美女一区二区三区| 日韩午夜精品| 粉嫩嫩av羞羞动漫久久久| 亚洲欧美电影一区二区| 欧美乱熟臀69xxxxxx| 国产一区美女| 激情综合网天天干| 自拍偷拍国产精品| 91精品一区二区三区久久久久久| 亚洲午夜精品久久| 狠狠色丁香久久婷婷综| 亚洲蜜臀av乱码久久精品| 欧美日韩国产高清一区二区三区 | xnxx国产精品| 欧美在线观看一区二区| 欧美日本一区| 国产一区二区三区精品欧美日韩一区二区三区 | 国产日韩欧美激情| 日本韩国精品在线| 国产在线精品二区| 成人在线一区二区三区| 三级精品在线观看| 国产精品久久一级| 日韩欧美在线一区二区三区| 亚洲影音先锋| 欧美日本中文| youjizz国产精品| 日本vs亚洲vs韩国一区三区| 国产精品国产精品国产专区不蜜 | 欧美精品亚洲一区二区在线播放| 亚洲高清在线| 99久久精品免费| 另类成人小视频在线| 亚洲精品日日夜夜| 国产精品色呦呦| 精品国产一二三区| 91精品国产一区二区三区蜜臀| 六月婷婷一区| 亚洲国产午夜| 欧美另类视频| 91丨九色丨尤物| 不卡的看片网站| 国产美女娇喘av呻吟久久 | 可以免费看不卡的av网站| 国产欧美精品| www.亚洲免费av| 国产福利不卡视频| 黑人巨大精品欧美一区| 日韩avvvv在线播放| 亚洲一区二区三区国产| 日韩久久一区二区| 亚洲欧美在线高清| 中文字幕在线不卡视频| 国产精品嫩草影院com| 日本一区二区三区视频视频| 久久久www成人免费毛片麻豆| 日韩欧美黄色影院| 日韩精品中文字幕在线不卡尤物 | 亚洲欧美激情插 | 牛人盗摄一区二区三区视频| 成人免费精品视频| 成人高清免费在线播放|