Tại sao query_posts () không được đánh dấu là không dùng nữa?


15

Có hai query_posts()chức năng nói về mặt kỹ thuật. Một cái query_posts()thực sự WP_Query::query_posts()và cái kia là trong không gian toàn cầu.

Hỏi từ sự tỉnh táo:

Nếu toàn cầu query_posts()là "cái ác" thì tại sao không được tán thành?

Hoặc tại sao không được đánh dấu là _doing_it_wong.


2
Đó là một câu hỏi lớn! Đối với những người khác đi qua điều này, những người không biết lý do tại sao bạn không nên sử dụng query_posts (), đâyđây là một số câu hỏi và trả lời tốt về nó.
Tim Malone

Câu trả lời:


11

Câu hỏi quan trọng

Hãy đào vào bộ ba: ::query_posts, ::get_postsclass WP_Queryđể hiểu ::query_poststốt hơn.

Nền tảng để nhận dữ liệu trong WordPress là WP_Querylớp. Cả hai phương thức ::query_posts::get_postssử dụng lớp đó.

Lưu ý rằng lớp WP_Querycũng chứa các phương thức có cùng tên: WP_Query::query_postsWP_Query::get_posts, nhưng chúng tôi thực sự chỉ xem xét các phương thức toàn cầu, vì vậy đừng nhầm lẫn.

nhập mô tả hình ảnh ở đây

Hiểu biết về WP_Query

Lớp được gọi WP_Queryđã được giới thiệu trở lại vào năm 2004. Tất cả các trường có dấu ☂ (ô) xuất hiện trở lại vào năm 2004. Các trường bổ sung đã được thêm vào sau đó.

Đây là WP_Querycấu trúc:

class WP_Query (as in WordPress v4.7) 
    public $query; 
    public $query_vars = array(); 
    public $tax_query;
    public $meta_query = false;
    public $date_query = false;
    public $queried_object; 
    public $queried_object_id; 
    public $request;
    public $posts; 
    public $post_count = 0; 
    public $current_post = -1; 
    public $in_the_loop = false;
    public $post; 
    public $comments;
    public $comment_count = 0;
    public $current_comment = -1;
    public $comment;
    public $found_posts = 0;
    public $max_num_pages = 0;
    public $max_num_comment_pages = 0;
    public $is_single = false; 
    public $is_preview = false; 
    public $is_page = false; 
    public $is_archive = false; 
    public $is_date = false; 
    public $is_year = false; 
    public $is_month = false; 
    public $is_day = false; 
    public $is_time = false; 
    public $is_author = false; 
    public $is_category = false; 
    public $is_tag = false;
    public $is_tax = false;
    public $is_search = false; 
    public $is_feed = false; 
    public $is_comment_feed = false;
    public $is_trackback = false; 
    public $is_home = false; 
    public $is_404 = false; 
    public $is_embed = false;
    public $is_paged = false;
    public $is_admin = false; 
    public $is_attachment = false;
    public $is_singular = false;
    public $is_robots = false;
    public $is_posts_page = false;
    public $is_post_type_archive = false;
    private $query_vars_hash = false;
    private $query_vars_changed = true;
    public $thumbnails_cached = false;
    private $stopwords;
    private $compat_fields = array('query_vars_hash', 'query_vars_changed');
    private $compat_methods = array('init_query_flags', 'parse_tax_query');
    private function init_query_flags()

WP_Query là con dao quân đội Thụy Sĩ.

Một số điều về WP_Query:

  • đó là thứ bạn có thể kiểm soát thông qua các đối số bạn vượt qua
  • nó là tham lam theo mặc định
  • nó giữ chất để lặp
  • nó được lưu trong không gian toàn cầu x2
  • Nó có thể là chính hay phụ
  • nó sử dụng các lớp trợ giúp
  • nó có một pre_get_postscái móc tiện dụng
  • nó thậm chí còn hỗ trợ cho các vòng lặp lồng nhau
  • nó giữ chuỗi truy vấn SQL
  • nó giữ số lượng kết quả
  • nó giữ kết quả
  • nó giữ danh sách tất cả các đối số truy vấn có thể
  • nó giữ các cờ mẫu
  • ...

Tôi không thể giải thích tất cả những điều này, nhưng một số trong số này là khó khăn, vì vậy hãy cung cấp các mẹo ngắn.

WP_Query là thứ bạn có thể kiểm soát thông qua các đối số bạn vượt qua

The list of the arguments
---
 attachment
 attachment_id
 author
 author__in
 author__not_in
 author_name
 cache_results
 cat
 category__and
 category__in
 category__not_in
 category_name
 comments_per_page
 day
 embed
 error
 feed
 fields
 hour
 ignore_sticky_posts
 lazy_load_term_meta
 m
 menu_order
 meta_key
 meta_value
 minute
 monthnum
 name
 no_found_rows
 nopaging
 order
 p
 page_id
 paged
 pagename
 post__in
 post__not_in
 post_name__in
 post_parent
 post_parent__in
 post_parent__not_in
 post_type
 posts_per_page
 preview
 s
 second
 sentence
 static
 subpost
 subpost_id
 suppress_filters
 tag
 tag__and
 tag__in
 tag__not_in
 tag_id
 tag_slug__and
 tag_slug__in
 tb
 title
 update_post_meta_cache
 update_post_term_cache
 w
 year

Danh sách này từ WordPress phiên bản 4.7 chắc chắn sẽ thay đổi trong tương lai.

Đây sẽ là ví dụ tối thiểu tạo WP_Queryđối tượng từ các đối số:

// WP_Query arguments
$args = array ( /* arguments*/ );
// creating the WP_Query object
$query = new WP_Query( $args );
// print full list of arguments WP_Query can take
print ( $query->query_vars );

WP_Query là tham lam

Được tạo ra dựa trên ý tưởng Các get all you cannhà phát triển WordPress đã quyết định sớm nhận được tất cả dữ liệu có thể vì điều này tốt cho hiệu suất . Đây là lý do tại sao theo mặc định khi truy vấn lấy 10 bài đăng từ cơ sở dữ liệu, nó cũng sẽ nhận được các điều khoản và siêu dữ liệu cho các bài đăng này thông qua các truy vấn riêng biệt. Điều khoản và siêu dữ liệu sẽ được lưu trữ (tìm nạp trước).

Lưu ý bộ nhớ đệm chỉ dành cho vòng đời yêu cầu duy nhất.

Bạn có thể vô hiệu hóa bộ nhớ đệm nếu bạn thiết lập update_post_meta_cacheupdate_post_term_cacheđể falsetrong khi thiết lậpWP_Query đối số. Khi bộ nhớ đệm bị vô hiệu hóa, dữ liệu sẽ chỉ được yêu cầu từ cơ sở dữ liệu theo yêu cầu.

Đối với phần lớn các blog WordPress bộ nhớ đệm hoạt động tốt, nhưng có một số trường hợp khi bạn có thể vô hiệu hóa bộ đệm.

WP_Query sử dụng các lớp trợ giúp

Nếu bạn đã kiểm tra WP_Querycác trường ở đó, bạn có ba:

public $tax_query;
public $meta_query;
public $date_query;

Bạn có thể tưởng tượng thêm mới trong tương lai.

nhập mô tả hình ảnh ở đây

WP_Query giữ chất cho vòng lặp

Trong mã này:

$query = new WP_Query( $args )
if ( $query->have_posts() ) {
        while ( $query->have_posts() ) {
            $query->the_post();

bạn có thể nhận thấy WP_Querycó chất bạn có thể lặp lại. Các phương pháp trợ giúp cũng có. Bạn chỉ cần đặt whilevòng lặp.

Ghi chú. forwhilecác vòng lặp tương đương về mặt ngữ nghĩa.

WP_Query tiểu học và trung học

Trong WordPress, bạn có một truy vấn chính và không hoặc nhiều truy vấn phụ .

Có thể không có truy vấn chính, nhưng điều này nằm ngoài phạm vi của bài viết này.

Truy vấn chính được gọi là truy vấn chính hoặc truy vấn thông thường . Truy vấn phụ cũng được gọi là truy vấn tùy chỉnh .

WordPress sử dụng WP_Rewritelớp sớm để tạo các đối số truy vấn dựa trên URL. Dựa trên những lập luận này, nó lưu trữ hai đối tượng giống hệt nhau trong không gian toàn cầu. Cả hai sẽ giữ truy vấn chính.

global $wp_query   @since WordPress 1.5
global $wp_the_query @since WordPress 2.1

Khi chúng ta nói truy vấn chính, chúng ta nghĩ về các biến này. Các truy vấn khác có thể được gọi là thứ cấp hoặc tùy chỉnh.

Nó là hoàn toàn hợp pháp để sử dụng global $wp_queryhoặc $GLOBALS['wp_query'] , nhưng việc sử dụng ký hiệu thứ hai đáng chú ý hơn nhiều và tiết kiệm việc nhập một dòng bổ sung bên trong phạm vi của các chức năng.

$GLOBALS['wp_query']$GLOBALS['wp_the_query']là những đối tượng riêng biệt. $GLOBALS['wp_the_query']nên vẫn đông lạnh.

WP_Query có ích pre_get_posts móc .

Đây là móc hành động. Nó sẽ áp dụng cho bất kỳ WP_Query trường hợp. Bạn gọi nó như:

add_action( 'pre_get_posts', function($query){

 if ( is_category() && $query->is_main_query() ) {
    // set your improved arguments
    $query->set( ... );  
    ...  
 }

 return $query;  
});

Móc này là tuyệt vời và nó có thể thay đổi bất kỳ đối số truy vấn.

Đây là những gì bạn có thể đọc :

Bắn sau khi đối tượng biến truy vấn được tạo, nhưng trước khi truy vấn thực tế được chạy.

Vì vậy, hook này là trình quản lý đối số nhưng không thể tạo WP_Queryđối tượng mới . Nếu bạn có một truy vấn chính và một truy vấn phụ, pre_get_postskhông thể tạo truy vấn thứ ba. Hoặc nếu bạn chỉ có một chính, nó không thể tạo thứ cấp.

Lưu ý trong trường hợp bạn cần thay đổi truy vấn chính, bạn cũng có thể sử dụng requesthook.

WP_Query hỗ trợ các vòng lặp lồng nhau

Kịch bản này có thể xảy ra nếu bạn sử dụng plugin và bạn gọi các chức năng của plugin từ mẫu.

Dưới đây là ví dụ giới thiệu WordPress có các chức năng trợ giúp ngay cả đối với các vòng lặp lồng nhau:

global $id;
while ( have_posts() ) : the_post(); 

    // the custom $query
    $query = new WP_Query( array(   'posts_per_page' => 5   ) );    
    if ( $query->have_posts() ) {

        while ( $query->have_posts() ) : $query->the_post();            
            echo '<li>Custom ' . $id . '. ' . get_the_title() . '</li>';
        endwhile;       
    }   

    wp_reset_postdata();
    echo '<li>Main Query ' . $id . '. ' . get_the_title() . '</li>';

endwhile;

Đầu ra sẽ như thế này kể từ khi tôi cài đặt dữ liệu thử nghiệm đơn vị chủ đề :

Custom 100. Template: Sticky
Custom 1. Hello world!
Custom 10. Markup: HTML Tags and Formatting
Custom 11. Markup: Image Alignment
Custom 12. Markup: Text Alignment
Custom 13. Markup: Title With Special Characters
Main Query 1. Hello world!

Mặc dù tôi đã yêu cầu 5 bài đăng trong truy vấn $ tùy chỉnh, nó sẽ trả về cho tôi sáu bài viết, bởi vì bài đăng dính sẽ đi cùng. Nếu không có wp_reset_postdatatrong ví dụ trước, đầu ra sẽ như thế này, vì $GLOBALS['post']sẽ không hợp lệ.

Custom 1001. Template: Sticky
Custom 1. Hello world!
Custom 10. Markup: HTML Tags and Formatting
Custom 11. Markup: Image Alignment
Custom 12. Markup: Text Alignment
Custom 13. Markup: Title With Special Characters
Main Query 13. Markup: Title With Special Characters

WP_Querywp_reset_querychức năng

Đây giống như một nút đặt lại. $GLOBALS['wp_the_query']nên được đóng băng mọi lúc và các plugin hoặc chủ đề không bao giờ thay đổi nó.

Đây là những gì wp_reset_querylàm:

function wp_reset_query() {
    $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
    wp_reset_postdata();
}

Nhận xét về get_posts

get_posts giống như

File: /wp-includes/post.php
1661: function get_posts( $args = null ) {
1662:   $defaults = array(
1663:       'numberposts' => 5,
1664:       'category' => 0, 'orderby' => 'date',
1665:       'order' => 'DESC', 'include' => array(),
1666:       'exclude' => array(), 'meta_key' => '',
1667:       'meta_value' =>'', 'post_type' => 'post',
1668:       'suppress_filters' => true
1669:   );
... // do some argument parsing
1685:   $r['ignore_sticky_posts'] = true;
1686:   $r['no_found_rows'] = true;
1687: 
1688:   $get_posts = new WP_Query;
1689:   return $get_posts->query($r);

Số dòng có thể thay đổi trong tương lai.

Nó chỉ là một wrapper xung quanh WP_Queryrằng lợi nhuận các bài viết đối tượng truy vấn.

Các ignore_sticky_poststhiết lập để phương tiện đúng các bài viết dính có thể xuất hiện chỉ ở một vị trí tự nhiên. Sẽ không có bài viết dính ở phía trước. Cái khác no_found_rowsđược đặt thành true có nghĩa là API cơ sở dữ liệu WordPress sẽ không sử dụng SQL_CALC_FOUND_ROWSđể triển khai phân trang, giảm tải cho cơ sở dữ liệu để thực thi các hàng tìm thấy số lượng .

Điều này rất hữu ích khi bạn không cần phân trang. Bây giờ chúng tôi hiểu rằng chúng tôi có thể bắt chước chức năng này với truy vấn này:

$args = array ( 'ignore_sticky_posts' => true, 'no_found_rows' => true);
$query = new WP_Query( $args );
print( $query->request );

Đây là yêu cầu SQL tương ứng:

SELECT wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 10

So sánh những gì chúng ta có bây giờ với yêu cầu SQL trước đây SQL_CALC_FOUND_ROWStồn tại.

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')  ORDER BY wp_posts.post_date DESC LIMIT 0, 10

Yêu cầu không có SQL_CALC_FOUND_ROWS sẽ nhanh hơn.

Nhận xét về query_posts

Mẹo: Lúc đầu năm 2004 chỉ có global $wp_query. Kể từ phiên bản WordPress 2.1 $wp_the_query. Mẹo: $GLOBALS['wp_query']$GLOBALS['wp_the_query']là các đối tượng riêng biệt.

query_posts()WP_Querybao bọc. Nó trả về tham chiếu đến WP_Queryđối tượng chính , đồng thời nó sẽ đặt global $wp_query.

File: /wp-includes/query.php
function query_posts($args) {
    $GLOBALS['wp_query'] = new WP_Query();
    return $GLOBALS['wp_query']->query($args);
}

Trong PHP4, mọi thứ, bao gồm các đối tượng, được truyền bằng giá trị. query_postslà như thế này:

File: /wp-includes/query.php (WordPress 3.1)
function &query_posts($args) {
    unset($GLOBALS['wp_query']);
    $GLOBALS['wp_query'] =& new WP_Query();
    return $GLOBALS['wp_query']->query($args);
}

Xin lưu ý trong kịch bản điển hình với một truy vấn chính và một truy vấn phụ, chúng tôi có ba biến sau:

$GLOBALS['wp_the_query'] 
$GLOBALS['wp_query'] // should be the copy of first one
$custom_query // secondary

Giả sử mỗi người trong số ba người này chiếm 1M bộ nhớ. Tổng cộng sẽ là 3M bộ nhớ. Nếu chúng ta sử dụng query_posts, $GLOBALS['wp_query']sẽ không được đặt và tạo lại.

PHP5 + nên làm trống $GLOBALS['wp_query']đối tượng một cách thông minh , giống như trong PHP4, chúng ta đã làm điều đó vớiunset($GLOBALS['wp_query']);

function query_posts($args) {
    $GLOBALS['wp_query'] = new WP_Query();
    return $GLOBALS['wp_query']->query($args);
}

Kết quả là query_poststiêu thụ tổng cộng 2M bộ nhớ, trong khi get_poststiêu thụ 3M bộ nhớ.

Lưu ý trong query_postschúng tôi không trả về đối tượng thực tế, mà là một tham chiếu đến đối tượng.

Từ php.net : Tham chiếu PHP là bí danh, cho phép hai biến khác nhau ghi vào cùng một giá trị. Kể từ PHP 5, một biến đối tượng không chứa chính đối tượng đó là giá trị nữa. Nó chỉ chứa một định danh đối tượng cho phép người truy cập đối tượng tìm thấy đối tượng thực tế. Khi một đối tượng được gửi bằng đối số, được trả về hoặc được gán cho một biến khác, các biến khác nhau không phải là bí danh: chúng giữ một bản sao của mã định danh, trỏ đến cùng một đối tượng.

Ngoài ra trong PHP5 + toán tử gán (=) là thông minh. Nó sẽ sử dụng bản sao nông và bản sao đối tượng không cứng. Khi chúng ta viết như thế này $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];chỉ có dữ liệu sẽ được sao chép chứ không phải toàn bộ đối tượng vì chúng chia sẻ cùng loại đối tượng.

Đây là một ví dụ

print( md5(serialize($GLOBALS['wp_the_query']) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
query_posts( '' );
print( md5(serialize($GLOBALS['wp_the_query']) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );

Sẽ có kết quả:

f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
d6db1c6bfddac328442e91b6059210b5

Cố gắng đặt lại truy vấn:

print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
query_posts( '' );
wp_reset_query();
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );

Sẽ có kết quả:

f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef

Bạn có thể tạo ra vấn đề ngay cả khi bạn sử dụng WP_Query

print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
global $wp_query;
$wp_query = new WP_Query( array( 'post_type' => 'post' ) );   
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );

Tất nhiên, giải pháp sẽ là sử dụng wp_reset_querychức năng một lần nữa.

print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
global $wp_query;
$wp_query = new WP_Query( array( 'post_type' => 'post' ) );
wp_reset_query();
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );

Đây là lý do tại sao tôi nghĩ query_postscó thể tốt hơn từ quan điểm bộ nhớ. Nhưng bạn nên luôn luôn làm wp_reset_querymẹo.


10

Tôi vừa tạo một vé trac mới, vé # 36874 , để đề xuất khấu haoquery_posts() . Có hay không nó sẽ được chấp nhận vẫn là một câu hỏi hay.

Vấn đề thực sự lớn query_posts()là, nó vẫn được sử dụng rộng rãi bởi các plugin và chủ đề, mặc dù đã có những bài viết thực sự hay về chủ đề tại sao bạn KHÔNG BAO GIỜ nên sử dụng nó. Tôi nghĩ rằng bài viết hoành tráng nhất ở đây trên WPSE là bài sau:

deprecation! == loại bỏ , vì vậy việc phản đối query_posts()sẽ không ngăn chặn việc sử dụng bởi các nhà phát triển kém chất lượng và những người nói chung không biết WordPress và sử dụng các hướng dẫn chất lượng kém làm hướng dẫn. Cũng giống như một số bằng chứng, bao nhiêu câu hỏi sao chúng ta vẫn nhận được ở đây, nơi mọi người sử dụng caller_get_poststrong WP_Query? Nó đã bị phản đối trong nhiều năm nay.

Tuy nhiên, các hàm và đối số không được chấp nhận có thể bị xóa bất cứ lúc nào các nhà phát triển cốt lõi thấy phù hợp, nhưng điều này có lẽ sẽ không bao giờ xảy ra query_posts()vì điều này sẽ phá vỡ hàng triệu trang web. Vì vậy, có, chúng ta có thể sẽ không bao giờ thấy việc loại bỏ hoàn toàn query_posts()- điều này có thể dẫn đến thực tế là nó có thể sẽ không bao giờ bị phản đối.

Đây là một điểm khởi đầu, nhưng người ta phải nhớ, việc từ chối một cái gì đó trong WordPress không ngăn được việc sử dụng nó.

CẬP NHẬT ngày 19 tháng 5 năm 2016

Vé tôi đã nâng hiện đã bị đóng và được đánh dấu là trùng lặp với vé 4 năm tuổi , đã bị đóng dưới dạng wontfix và được mở lại và vẫn còn mở và chưa được giải quyết.

Có vẻ như các nhà phát triển cốt lõi đang bám vào cái ác nhỏ bé trung thành này. Mọi người quan tâm, đây là vé cũ 4 năm


Tại sao họ lại đóng vé core.trac.wordpress.org/ticket/36874 ? Vui lòng @PieterGoosen bạn có thể bao gồm liên kết đến chủ đề này trong vé của bạn core.trac.wordpress.org/ticket/36874 kể từ khi câu hỏi này liên quan đến vé 1: 1
prosti

@prosti Hình như nó được đánh dấu là trùng lặp vì vấn đề này đã được đưa ra ... 4 năm trước được tìm thấy ở đây .
Howdy_McGee

3

[hơi giận dữ]

Đó là triết lý cốt lõi thường trực vào thời điểm này mà không có gì là thực sự bị phản đối. Thông báo phản đối, mặc dù nó là một thứ tốt đẹp, sẽ bị bỏ qua nếu chức năng sẽ không thực sự bị loại bỏ tại một số điểm. Có nhiều người không phát triển cùng WP_DEBUGvà sẽ không chú ý đến thông báo nếu không có sự phá vỡ thực sự.

OTOH tay, chức năng này giống như gototuyên bố. Cá nhân tôi không bao giờ (đối với định nghĩa nhỏ hơn dự kiến) được sử dụng gotonhưng tôi có thể hiểu các đối số chỉ ra một số tình huống trong đó nó không phải là xấu theo mặc định. Tương tự như vậy query_posts, đó là một cách đơn giản để thiết lập tất cả các quả cầu cần thiết để tạo một vòng lặp đơn giản và có thể hữu ích trong bối cảnh ajax hoặc rest-api. Tôi cũng sẽ không bao giờ sử dụng nó trong các bối cảnh đó, nhưng tôi có thể thấy rằng ở đó, đó là vấn đề về phong cách mã hóa, sau đó một chức năng trở nên xấu xa.

Đi sâu hơn một chút, vấn đề chính là toàn cầu cần phải được thiết lập. Đó là vấn đề chính không phải là một chức năng giúp thiết lập chúng.


Và để so sánh, thực sự query_postschậm hơn một truy vấn phụ (đọc: không phải là truy vấn chính).
prosti

@prosti, vì nó chỉ thiết lập và chạy wp_query, nó có thể chậm hơn bao nhiêu? chắc chắn có một số chi phí nhưng có lẽ chúng ta đang nói chuyện hàng triệu giây ở đây. Điều này tất nhiên giả định rằng bạn sử dụng nó ở những nơi mà WP không cung cấp truy vấn theo mặc định. Ở những nơi nó làm điều đó là xấu, không phải là query_postschính nó mà là truy vấn vô ích đã được thực hiện khi WP đang tải
Mark Kaplun
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.