自定义WordPress SQL查询,根据帖子ID - php,数据库(自定义帖子类型和字段)输出元数据


Custom WordPress SQL query to output metadata based on post ID - php, database (custom post type&fields)

我正在从另一个Wordpress数据库运行数据库查询,因此使用标准sql查询而不是各种wordpress函数。

从本质上讲,我想显示与 postID 相关的所有元值/数据。我已经设置了一个带有自己的自定义字段(开始日期等)的客户帖子类型"事件"。

几乎拥有我需要的一切,我只需要编写正确的 php 循环来输出每个帖子 ID 的数据(以显示帖子的元数据)。

表结构图像

注意:meta_values可以为空,将来可能会添加更多meta_keys。

$newdb = //already setup new db connection (don't worry about this)
$query =
                "
                    SELECT * 
                    FROM wp_posts, wp_postmeta
                    WHERE wp_posts.ID = wp_postmeta.post_ID
                    AND wp_postmeta.meta_key NOT LIKE ''_%'   
                    AND wp_posts.post_type='event' 
                    AND wp_posts.post_status = 'publish';
                " ;  

$events = $newdb->get_results($query, OBJECT);
//get_results() is a wordpress function, nearly equiv to my_sqli
//OBJECT - result will be output as an object.
//ARRAY_A - result will be output as an associative array.

foreach ( $events as $event ) {
echo $event->post_title;
echo $event->meta_value;    
}

当前结果:

Title_1, 11/02/2016

Title_1, 05:00

Title_1, 12/01/2016

Title_2, 05/02/2016


**期望结果: **(针对每个帖子)

(结构上):

post_ID: 1, post_title: Title_1, start_date: 11/02/2016,

start_time: 05:00, end_date: 12/01/2016

$event->post_title;
$event->meta_value”;  //meta_key = start_date
$event->meta_value”;  //meta_key = end_time
$event->meta_value”; //meta_key = end_date

(视觉上)

Title_1,11/02/2016,05:00,2016/12/1,

Title_2,05/02/2016,07:00,2016/02/07,

我最终制作了自己的透视 php 循环,该循环检查每个生成的数组(来自 SQL 查询)并根据帖子的 ID 将其分组到另一个关联数组中。 一切都运行良好,我可以将每个帖子的元值放在要显示的适当 HTML 标签中。

这是我选择自定义帖子类型("事件")和自定义字段(存储在元键值对中)的完整工作代码:

//credentials can be found in your wp-config.php file
$newdb = new wpdb('DB_USER', 'DB_PASSWORD', 'DB_NAME', 'DB_HOST');
//sql query
$querystr =
        "
        SELECT wp_posts.ID, wp_posts.post_title, wp_postmeta.meta_key, wp_postmeta.meta_value
        FROM wp_posts, wp_postmeta
        WHERE wp_posts.ID = wp_postmeta.post_ID
        AND wp_postmeta.meta_key NOT LIKE ''_%'
        AND wp_posts.post_type='event'
        AND wp_posts.post_status = 'publish';
        " ;
//wordpress function that returns the query as an array of associative arrays
$results = $newdb->get_results($querystr, ARRAY_A);
//create an empty array
$events = array();
foreach ($results as $row) {
    //if row's ID doesn't exist in the array, add a new array
    if (!isset($events[$row['ID']])) {
        $events[$row['ID']] = array();
    }
    //add all the values to the array with matching IDs
    $events[$row['ID']] = array_merge($events[$row['ID']], array('post_title'=>$row['post_title']), array($row['meta_key']=>$row['meta_value']));
}
//extract data from each event
foreach ($events as $event) {
    var_dump($event); //do something
    echo $event['start_date']; //can also echo specific metavalues etc.
}

您要做的是SQL中臭名昭著的痛苦,因为wp_postmeta是一个键值存储。 所有元数据都是痛苦的部分。

很难将键

值存储项转换为结果集中自己的列,以允许在添加新键值时显示新列。

专业提示:在尝试做这种事情时,SELECT *不是你的朋友。

如果您提前知道元数据项,则会更容易。例如,如果您知道需要开始日期、结束时间和结束日期的列,则可以执行此操作。

 SELECT wp_posts.*, 
        a.meta_value start_date, 
        b.meta_value end_time,
        c.meta_value end_date
   FROM wp_posts
   LEFT JOIN wp_postmeta a ON wp_posts.ID = a.post_ID AND a.meta_key='start_date'
   LEFT JOIN wp_postmeta b ON wp_posts.ID = b.post_ID AND a.meta_key='end_time'
   LEFT JOIN wp_postmeta c ON wp_posts.ID = c.post_ID AND a.meta_key='end_date'
  WHERE wp_posts.post_type = 'event' etc etc

我建议在这里LEFT JOIN,因为如果您使用普通的内部JOIN,任何缺少元数据值的帖子都将从结果集中被禁止。LEFT JOIN允许它们以 NULL 值显示在结果集中。

如果你必须做所有元数据的事情,你需要在你的php代码中做很多格式化。首先要找出不同的元数据项:

 SELECT DISTINCT wp_metadata.meta_key
   FROM wp_posts
   JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_ID
  WHERE wp_posts.post_type = 'event'  etc etc

然后,您将在 php 中构建一个数据结构,该结构适用于存储为每个meta_key值命名的列。(解释这超出了SO答案的范围)。

接下来,您将运行一个类似于问题中的查询,并使用它来填充 php 中的数据表。最后,您将显示该表。

这种一般操作类型的行话是旋转您的表格。在一般情况下,在MySQL中很难做到。