站長資訊網
        最全最豐富的資訊網站

        PHP學習中實用的知識點和坑分享

        本篇文章給大家分享一些 PHP 中有用的知識和坑。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有所幫助。

        PHP學習中實用的知識點和坑分享

        在一次偶然查看 PHP 文檔的時候,發現了一些有趣的內容,隨著閱讀的增加,越發覺得有趣的內容或者說時坑越來越多,所以我決定記錄下來,分享出去,下文中一些內容摘錄自一些優秀的博客、PHP 文檔的用戶筆記,或者文檔原文。

        尤其是文檔原文,我發現很多人不會去讀,很多東西也不會去注意(是的,我也是這樣,所以借著這次機會,一起來學習一下。)

        我忘了PHP函數的參數順序,它們是隨機的嗎?

        PHP is a glue that brings together hundreds of external libraries, so sometimes this gets messy. However, a simple rule of thumb is as follows:

        Array functionparameters are ordered as " needle, haystack" whereas String functionsare the opposite, so " haystack, needle".

        譯:數組相關方法的參數順序為,「needle, haystack」,字符串相關方法則是相反的 「haystack, needle」,

        來源: https://www.php.net/manual/zh/faq.using.php#faq.using.parameterorder

        我應該如何保存“鹽”?

        當使用 password_hash() 或者 crypt() 函數時, “鹽”會被作為生成的散列值的一部分返回。 你可以直接把完整的返回值存儲到數據庫中, 因為這個返回值中已經包含了足夠的信息, 可以直接用在 password_verify() 或 crypt() 函數來進行密碼驗證。

        下圖展示了 crypt() 或 password_hash() 函數返回值的結構。 如你所見,算法的信息以及“鹽”都已經包含在返回值中, 在后續的密碼驗證中將會用到這些信息。

        來源: https://www.php.net/manual/zh/faq.passwords.php#faq.password.storing-salts

        下面代碼怎么沒有分成兩行顯示?

        <pre> <?php echo "This should be the first line."; ?> <?php echo "This should show up after the new line above."; ?> </pre>

        在 PHP 中,一段代碼的結束標記要么是“?>”要么是“?>n”(n 表示換行)。因此在上面的例子中,輸出的句子將顯示在同一行中,因為 PHP 忽略了代碼結束標記后面的換行。這意味著如果要輸出一個換行符,需要在每段 PHP 代碼的結束標記后面多加一個換行。

        PHP 為什么這么做呢?因為在格式化正常的 HTML 時,這樣通常會更容易。假如輸出了換行而你不需要這個換行時,就不得不用一個非常長的行來達到這樣的效果,或者讓產生的 HTML 頁面的源文件的格式很難讀。

        來源: https://www.php.net/manual/zh/faq.using.php#faq.using.newlines

        字符串連接操作符的優先級問題

        如果你運行下面的代碼,他將會輸出一個警告和結果 3 ,因為字符串連接操作符 . 和 數學運算符 +- 的優先級時一樣的,它們將從左往右執行。 Result: 會被強轉成數組 0 。如果你在低版本的 PHP 中運行,會告訴你 中邊不是一個數字,如果你在 7.4 中運行,會告訴你,在 PHP 8 中 + 、 - 的優先級將會被提高。如果你使用了 PHPSTORM 中的 EA 插件,將會提醒你這個問題。

        <php $var = 3;  echo "Result: " . $var + 3;

        如果你不希望這樣,那么最好使用括號把它包裹起來,就像下面那樣。

        <?php $var = 3;  echo "Result: " . ($var + 3);

        來源: https://www.php.net/manual/zh/language.operators.string.php#41950

        字符串連接操作符與數字

        運行下面代碼,尤其是第三行,請注意,如果 . 左右存在空格,那么即使是一個數字,也將會作用成字符串連接。

        <?php  echo "thr"."ee";           //prints the string "three" echo "twe" . "lve";        //prints the string "twelve" echo 1 . 2;                //prints the string "12" echo 1.2;                  //prints the number 1.2 echo 1+2;                  //prints the number 3

        來源: https://www.php.net/manual/zh/language.operators.string.php#41950

        使用 http_build_query

        NULL 的值將會被會略

        <?php $arr = array('test' => null, 'test2' => 1);  // test2=1 echo http_build_query($arr);

        來源: https://www.php.net/manual/zh/function.http-build-query.php#60523

        True 和 False 將會被轉換成數字

        <?php $a = [teste1= true,teste2=false]; // teste1=1&teste2=0 echo http_build_query($a)

        來源: https://www.php.net/manual/zh/function.http-build-query.php#122232

        空的數組不會出現在結果中

        <?php  $post_data = array('name'=>'miller', 'address'=>array('address_lines'=>array()), 'age'=>23); // name=miller&age=23 echo http_build_query($post_data);

        來源: https://www.php.net/manual/zh/function.http-build-query.php#109466

        簡述 OpCache 的原理

        PHP執行這段代碼會經過如下4個步驟(確切的來說,應該是PHP的語言引擎Zend)

        • 1. Scanning(Lexing) ,將PHP代碼轉換為語言片段(Tokens)
        • 2. Parsing, 將Tokens轉換成簡單而有意義的表達式
        • 3. Compilation, 將表達式編譯成Opocdes
        • 4. Execution, 順次執行Opcodes,每次一條,從而實現PHP腳本的功能。

        現在有的Cache比如APC,可以使得PHP緩存住Opcodes,這樣,每次有請求來臨的時候,就不需要重復執行前面3步,從而能大幅的提高PHP的執行速度。

        來源: https://www.laruence.com/2008/06/18/221.html

        var_dump(1…9)輸出什么?

        <?php  // 10.9 var_dump(1...9);

        輸出10.9, 乍一看這個var_dump的輸出很奇怪是不是? 為什么呢?

        這里教大家,如果看到一段PHP代碼感覺輸出很奇怪,第一反應是看下這段代碼生成的opcodes是啥,雖然這個問題其實是詞法分析階段的問題,不過還是用phpdbg分析下吧(一般為了防止opcache的影響,會傳遞-n):

        phpdbg -n -p /tmp/1.php function name: (null) L1-35 {main}() /tmp/1.php - 0x7f56d1a63460 + 4 ops L2 #0 INIT_FCALL<1> 96 "var_dump" L2 #1 SEND_VAL "10.9" 1 L2 #2 DO_ICALL L35 #3 RETURN<-1> 1

        所以這么看來,早在生成opcode之前,1…9就變成了常量10.9,考慮到這是字面量,我們現在去看看zend_language_scanner.l, 找到這么一行:

        DNUM ({LNUM}?"."{LNUM})|({LNUM}"."{LNUM}?)

        這個是詞法分析定義的浮點數的格式,到這里也就恍然大悟了:
        1…9 會被依次接受為: 1. (浮點數1), 然后是 . (字符串連接符號) 然后是.9(浮點數0.9)

        所以在編譯階段就會直接生成 “1” . “0.9” -> 字符串的字面量”10.9”

        來源: https://www.laruence.com/2020/02/23/1990.html

        HTTPOXY 漏洞

        這里有一個核心的背景是, 長久一來我們習慣了使用一個名為"http_proxy"的環境變量來設置我們的請求代理。

        http_proxy=127.0.0.1:9999 wget http://www.laruence.com/

        如何形成?

        在CGI(RFC 3875)的模式的時候, 會把請求中的Header, 加上HTTP_ 前綴, 注冊為環境變量, 所以如果你在Header中發送一個Proxy:xxxxxx, 那么 PHP 就會把他注冊為HTTP_PROXY環境變量, 于是getenv("HTTP_PROXY")就變成可被控制的了. 那么如果你的所有類似的請求, 都會被代理到攻擊者想要的地址,之后攻擊者就可以偽造,監聽,篡改你的請求了

        如何影響?

        所以, 這個漏洞要影響你, 有幾個核心前提是:

        • 你的服務會對外請求資源
        • 你的服務使用了HTTP_PROXY(大寫的)環境變量來代理你的請求(可能是你自己寫,或是使用一些有缺陷的類庫)
        • 你的服務跑在PHP的CGI模式下(cgi, php-fpm)

        如何處理?

        以Nginx為例, 在配置中加入:

        fastcgi_param HTTP_PROXY "";

        所以建議, 即使你不受此次漏洞影響, 也應該加入這個配置.
        而如果你是一個類庫的作者,或者你因為什么原因沒有辦法修改服務配置, 那么你就需要在代碼中加入對sapi的判斷, 除非是cli模式, 否則永遠不要相信http_proxy環境變量,

        <?php if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) {   //只有CLI模式下, HTTP_PROXY環境變量才是可控的 }

        補充: 從PHP5.5.38開始, getenv增加了第二個參數, local_only = false, 如果這個參數為true, 則只會從系統本地的環境變量表中獲取, 從而修復這個問題, 并且默認的PHP將攔截HTTP_PROXY:fix

        HTTPOXY漏洞說明 – 風雪之隅
        https://www.laruence.com/2016/07/19/3101.html

        運算符優先級

        && 和 and 在賦值運算中的問題

        運行下面的代碼,第一個 $bool 將打印為 false ,預期如此,但是第二個 $bool 將打印 true 。這是因為 = 的優先級高于 and 運算符,所以,第二個 $bool 將會被當成 ($bool = true) and false 執行。

        <?php  $bool = true && false; // false var_dump($bool);   $bool = true and false; // true var_dump($bool);

        來源: https://www.php.net/manual/zh/language.operators.precedence.php#117390

        instanceof 運算符

        你是否曾經寫過下面這樣的代碼?

        <?php  class A {  }  $A = new A();  var_dump((! $A instanceof A));  // 其實不用擔心,因為 instanceof 的優先級要高于 ! ,你可以放心的使用, // 不必添加括號,讓他們看起來是一個表達式,但是在復雜的情況下例外。 var_dump(! $A instanceof A);

        在你需要對 instanceof 運算的結果做取反運算時,因為取反運算符 ! 的優先級低于 instanceof 所以,你不必再它們外面再加上一個圓括號來表明這是一組表達式,但是再復雜情況下例外。

        array_map 的有趣用法

        通常,我會使用 array_map 來處理一個數組,讓他返回一個新的數組,當然,它的用處就是這樣的,但是除了這種基礎的用法,它其實還有一些有趣的用法,并且,這些用法都存在于 PHP 的手冊中。

        多個 array 用法

        通常你會這樣使用它。

        <?php  $arr1 = ['apple', 'orange', 'mango', 'pear']; $newArr1 = array_map('strtoupper',$arr1);

        這只是一個簡單的,它會把所有的值轉為大寫的。那么看看下面的用法,猜猜會打印什么?

        <?php  $arr1 = ['apple', 'orange', 'mango', 'pear']; $arr2 = ['cauliflower', 'lettuce', 'kale', 'romaine'];  function map1($a, $b){     var_dump($a, $b);   // apple   cauliflower   // orange  lettuce   // mango   kale   // pear    romaine }  array_map('map1', $arr1, $arr2);

        如上 map1 方法所示,將會順序遍歷 $arr1 , $arr2 中的值,并且傳遞給 map1 ,根據手冊所定義: 如果多個數組的長度不一,即短的數組將會被填充空,至長的數組一樣 。

        原生函數使用不當的話會比你想象的要慢

        array_unique、array_merge 等,如果使用方法不正確,會比你想想的要慢,甚至是慢很多,遠不如 foreach。

        在下面這個回答中,列舉了 PHP 中一些 array_* 方法的時間復雜度
        performance – List of Big-O for PHP functions – Stack Overflow

        小心代碼中的比較

        下面的比較將會返回 true,是不是不敢相信?

        因為兩個 md5 值都有開始'0e',所以PHP類型理解這些字符串是科學符號。根據定義,0 的任何次方都是 0,所以在這里會成立?,所以當你確定一個變量的類型時,你最好使用 ===(恒等于)進行比較。

        <?php  $a = md5('240610708');// 0e462097431906509019562988736854 $b = md5('QNKCDZO'); // 0e830400451993494058024219903391  var_dump($a == $b); // true

        注意,當你在考慮使用 md5 存儲密碼時,你應該放棄這個想法,應該改用為 password_hash 系列方法。

        來自:https://www.php.net/manual/zh/function.md5.php#123392

        禁用 PHP 中不安全的 eval 方法

        眾所周知, 在 php 中,eval 方法可以執行任意 PHP 代碼,如果沒有做好處理,被用戶利用了, 就有可能會造成安全漏洞,所以最好想辦法禁用它,談到禁用 php 函數,你應該想到了 php.ini 中的 disable_functions參數,可以用來禁用 PHP 函數,一些集成環境中也會禁用一些高風險函數來降低風險。

        但是,這個配置項,卻禁用不了 eval 函數,因為根據官方文檔的定義, eval 不是一個函數,他如同 echo 、這些特殊方法一樣,他是一個語法結構,所以不能使用 disable_functions進行禁用,除此之外,還有 require、list、array、print、unset、include、isset、empty 、die、exit 等,這些都是語法結構,不是函數,如果你使用 function_exists判斷,他們都會返回 false

        如果你真的需要禁用 eval ,你得安裝一些第三方擴展來實現,比如 mk-j/PHP_diseval_extension

        參考:https://www.php.net/manual/zh/functions.variable-functions.php#functions.variable-functions

        將任意類型轉換為 null

        聽起來沒什么用但是你確實可以這樣做。

        <?php  $a = 'Hi!'; // 在 PHP 7.2 以下,這行代碼會返回 null,7.2 ~ 7.4 會返回 NULL,但是會提示被遺棄, // 8.0 開始,將不再支持 var_dump((unset)$a); var_dump($a);

        除此之外,你還可以用 settype 函數
        參考:https://www.php.net/settype

        參考:https://www.php.net/manual/zh/function.unset.php#example-5601

        isset 和 unset 同時支持多個參數

        unset 支持多個參數,想必大多數人是知道的,但是 isset 也支持喲。

        <?php  var_dump(isset($a, $b, $c));  unset($a, $b, $c);

        你不需要擔心這幾個變量沒有被設置,他們在這里都是安全的,不會報錯,在 isset 多個變量時,必須要所有變量都不為 null時,才會返回 true,當遇到一個不存在時,將會立即返回。

        參考:https://www.php.net/isset

        快速查詢一個函數或者類或語法的參考

        當你要查詢一個 php 方法或者對象或者語法時,你不需要打開 php 手冊進行搜索,你只需要在 https://php.net/<keyword>后面跟上方法、語法、對象的名字即可,并且不需要關心大小i額,比如像下面這些鏈接。

        • https://php.net/curlfile
        • https://php.net/isset
        • https://php.net/if

        使用反射調用 protected 或者 private 的類方法

        如果想避免一個方法被外部可見或者子類可見,可以采用 protected 或者 private 關鍵字來修改這些類,但是我們有時候又想在外部調用這些方法,應該怎么辦呢?只能改成 public 嗎?如果這是我們自己的代碼,當然可以這樣做,但是如果是引入的外部代碼的話,可能就不太好直接修改了。

        現在,我們可以在外部使用 反射 來調用這些方法,現在我們來定義一個 Lisa 類

        <?php  class Lisa {     public function name()     {         return 'Lisa';     }      protected function age()     {         return 22;     }      private function weight()     {         return 95;     }        private static function eat(){         return 1;     } }

        通常情況下,我們是沒有辦法直接調用 age 和 weight 方法的,現在,我們使用反射來調用。

        <?php // ... $reflectionClass = new ReflectionClass('Lisa'); $ageMethod = $reflectionClass->getMethod('age'); // 獲取 age 方法 $ageMethod->setAccessible(true); // 設置可見性 // 調用這個方法,需要傳入對象作為上下文 $age = $ageMethod->invoke($reflectionClass->newInstance()); var_dump($age);// 22

        上面的代碼看起來有些繁瑣,還有一個更簡單的辦法。

        <?php // ... $reflectionClass = new ReflectionClass('Lisa'); $weightMethod = $reflectionClass->getMethod('weight');// 獲取 weight 方法 // 獲取一個閉包,然后調用,同樣需要傳入對象作為上下文,后面調用的地方就可以傳入參數 $weight = $weightMethod->getClosure($reflectionClass->newInstance())(); var_dump($weight);

        調用靜態方法

        <?php // ... $reflectionClass = new ReflectionClass('Lisa'); $eatMethod = $reflectionClass->getMethod('eat'); $eatMethod->setAccessible(true); $eat = $eatMethod->invoke(null); // 如果是一個靜態方法,你可以傳遞一個 null var_dump($eat);

        同樣,類成員也可以使用反射進行修改。
        參考: https://www.php.net/manual/zh/class.reflectionproperty.php

        實例化一個類,但是繞過他的構造方法

        有沒有這樣想過?實例化一個類,但是卻不想調用他的構造方法(__construct),這里也可以用反射做到。

        <?php  class Dog {     private $name;      public function __construct($name)     {         $this->name = $name;     }      public function getName()     {         return $this->name;     } }  $dogClass = new ReflectionClass('Dog'); // 創建一個新實例,但是不調用構造方法 $dogInstance = $dogClass->newInstanceWithoutConstructor(); var_dump($dogInstance->getName()); // null

        如果你的環境不能使用反射,你還可以試試另一個很 cool 的方法,就是使用反序列化,可以參考包 doctrine/instantiator – Packagist

        參考: https://www.php.net/manual/zh/reflectionclass.newinstancewithoutconstructor.php

        獲取類一個類的所有父類

        使用 class_parents可以獲取一個類的所有父類,并且支持自動加載。

        <?php  class A{} class B extends A{} class C extends B{} class D extends C{}  var_dump(class_parents('D')); /* array(3) {   'C' =>   string(1) "C"   'B' =>   string(1) "B"   'A' =>   string(1) "A" } */

        參考:https://www.php.net/manual/zh/function.class-parents.php

        有趣的遞增和遞減

        遞增遞減不能作用域 bool 值

        遞增、遞減不能使用在 false 上面,但是 +=-= 可以

        <?php  $a = false;  ++$a;  var_dump($a);// false  $a++;  var_dump($a);// false  --$a;  var_dump($a);// false  $a--;  var_dump($a);// false  $a-= 1;  var_dump($a);// -1  $a+= 1;// 因為前面改變了,變成了 -1,所以下面是 0 ,請不要在這里疑惑  var_dump($a);// 0

        遞增可以作用域 NULL,但是遞減不可以

        <?php  $a = null; ++$a; var_dump($a); //1  $a = null; --$a; var_dump($a); // null

        遞增可以作用于字母,但是遞減不可以

        a-y 遞增時字母都將向后增加一個,但是當 z 的時候,就將會回到 aa ,循環如此,但是只能遞增,不能遞減

        <?php  $a = 'a'; ++$a; var_dump($a); // b  $a = 'z'; ++$a; var_dump($a); // aa  $a = 'A'; ++$a; var_dump($a); // B  $a = 'Z'; ++$a; var_dump($a); // AA

        混合遞增數字和字母

        現在你還可以把字母和數字混合起來,就像這樣:

        >>> $a = 'A1' => "A1" >>> ++$a => "A2" >>> ++$a => "A3" >>> $a = '001A' => "001A" >>> ++$a => "001B" >>> ++$a => "001C" >>> $a = 'A001' => "A001" >>> ++$a => "A002" >>> ++$a => "A003"

        但是請注意一些意外情況,比如這樣。

        >>> $a = '9E0' => "9E0" >>> ++$a => 10.0

        這是因為9E0 被當作成了浮點數的字符串表示,被 PHP 當成了 9*10^0 ,被評估成了 9 ,然后在執行的遞增。

        參考來源: https://www.php.net/manual/zh…

        請注意你的嵌套強制類型轉換,否則他會發生意外

        <?php  var_dump(TRUE === (boolean) (array) (int) FALSE);// true  var_dump((array) (int) FALSE);

        因為當把 FALSE 轉為數字是,他是 0,再轉為數組后,就成了,[0],所以再轉為 boolean 時,將會返回 true,因為數組不為空,并且 [0] != []

        參考:https://www.php.net/manual/zh/language.types.type-juggling.php#115373

        高版本中的數字與字符串進行比較

        自 PHP 8.0 開始。

        數字與非數字形式的字符串之間的非嚴格比較現在將首先將數字轉為字符串,然后比較這兩個字符串。 數字與數字形式的字符串之間的比較仍然像之前那樣進行。 請注意,這意味著 0 == "not-a-number" 現在將被認為是 false 。

        Comparison Before After
        0 == "0" true true
        0 == "0.0" true true
        0 == "foo" true false
        0 == "" true false
        42 == " 42" true true
        42 == "42foo" true false

        參考:https://www.php.net/manual/zh/migration80.incompatible.php#migration80.incompatible.core

        數組也可以直接比較

        你可以直接使用 == 比較兩個數組有相同的鍵值對,如果這不是一個關聯數組,那么就要保證值的順序相對應,如果時一個關聯數組,你就可以不用擔心。

        >>> $b = [1,2,3,4] => [      1,      2,      3,      4,    ] >>> $a = [1,2,3,4] => [      1,      2,      3,      4,    ] >>> $a == $b => true  // 注意,他不會比較類型。  >>> $a = [0,1,2,3,4] => [      0,      1,      2,      3,      4,    ] >>> $b = [false,1,2,3,4] => [      false,      1,      2,      3,      4,    ] >>> $a == $b => true  // 如果你要比較類型,你應該使用 ===  >>> $a === $b => false

        無序的比較:
        下面的列表中,使用 == 將會返回 true ,因為他們的值是相等的,只是順序不同,但是如果使用 === 將會返回類型,因為 === 的時候會考慮鍵值順序和數據類型。

        >>> $a = ['name'=>'Jack','sex'=>1,'age'=>18]; => [      "name" => "Jack",      "sex" => 1,      "age" => 18,    ] >>> $b = ['name'=>'Jack','age'=>18,'sex'=>1]; => [      "name" => "Jack",      "age" => 18,      "sex" => 1,    ] >>> $a == $b => true >>> $a === $b => false >>>

        來源:PHP: 數組運算符 – Manual

        https://www.php.net/manual/zh/language.operators.array.php

        合并數組

        數組還可以相加 (+),用來合并數組,使用 array_merge 可以合并數組可以把兩個數組相加,想必是都知道的,但是其實 + 號也可以,雖然都是合并數組,這兩個方法各有區別。+ 更像是替換。

        1、使用 array_merge 合并非關聯數組時,不會過濾重復項目, + 會(更像是替換)

        >>> $a = [1,2,3] => [      1,      2,      3,    ] >>> $b = [2,3,4] => [      2,      3,      4,    ] >>> array_merge($a,$b) => [      1,      2,      3,      2,      3,      4,    ] >>> $a + $b => [      1,      2,      3,    ]

        2、使用 array_merge 合并關聯數組時,如果鍵重復,將會保留最后一個數組的值,而使用 + 將會保留第一個鍵下面的值。

        >>> $a = ['name'=>'Jack','sex'=>1,'age'=>18]; => [      "name" => "Jack",      "sex" => 1,      "age" => 18,    ] >>> $b = ['name'=>'Jack','age'=>'18','sex'=>'1']; => [      "name" => "Jack",      "age" => "18",      "sex" => "1",    ] >>> array_merge($a, $b) => [      "name" => "Jack",      "sex" => "1",      "age" => "18",    ] >>> $a + $b => [      "name" => "Jack",      "sex" => 1,      "age" => 18,    ]

        3、當關聯數組中存在數字鍵時, array_merge 會重置數字鍵, + 則不會

        >>> $a = ['name'=>'Jack','sex'=>1,'age'=>18]; => [      "name" => "Jack",      "sex" => 1,      "age" => 18,    ] >>> $b = ['name'=>'Jack','age'=>'18','sex'=>'1','10'=>'hi']; => [      "name" => "Jack",      "age" => "18",      "sex" => "1",      10 => "hi",    ] >>> array_merge($a,$b) => [      "name" => "Jack",      "sex" => "1",      "age" => "18",      // 注意這里      0 => "hi",    ] >>> $a + $b => [      "name" => "Jack",      "sex" => 1,      "age" => 18,      // 注意這里      10 => "hi",    ]

        下面用一張圖來概括一下。

        PHP學習中實用的知識點和坑分享

        圖片來源:array_merge vs array_replace vs + (plus aka union) in PHP | SOFTonSOFA

        結束

        • 文章中大部分內容來自網絡搜集,我已經盡所能去驗證其真實性,但可能部分會有紕漏,如果有請不吝賜教。
        • 另外,如果文中的內容侵犯到了你得權益,請與我聯系處理。
        • 你還可以點擊文章中的來源鏈接,了解更詳細的內容。

        推薦學習:《PHP視頻教程》

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 亚洲精品国产精品乱码在线观看| 中文成人无码精品久久久不卡 | 热re99久久精品国产99热| 久久精品无码专区免费| 欧美精品国产一区二区| 日韩AV无码精品人妻系列| 久久国产精品国语对白| 韩国精品欧美一区二区三区| 亚洲国产精品无码久久SM| 精品国产91久久久久久久a| 免费欧美精品a在线| 成人伊人精品色XXXX视频| 亚洲AV成人精品网站在线播放 | japanese乱人伦精品| 亚洲精品成人久久久| 麻豆精品三级全部视频| 91精品国产麻豆国产自产在线| 精品国产一区二区三区不卡| 伊在人亚洲香蕉精品区麻豆| 精品国产欧美一区二区三区成人| 2024最新国产精品一区| 国内精品91最新在线观看| 凹凸国产熟女精品视频app| 久久这里只有精品18| 真实国产乱子伦精品视频| 亚洲国产精品激情在线观看| 欧美精品国产一区二区三区| 精品水蜜桃久久久久久久| 国产精品亚洲综合专区片高清久久久| 亚洲国语精品自产拍在线观看| 久久福利青草精品资源站免费| 国产亚洲精品一品区99热| 久久青草国产精品一区| 影音先锋国产精品国语对白| 99热精品毛片全部国产无缓冲| 99久久精品这里只有精品| 国产VA免费精品高清在线| 国产午夜精品理论片久久| 久久久久久青草大香综合精品| 久久中文精品无码中文字幕| 日韩欧美一区二区三区中文精品|