Wordpress在哪里存储自定义菜单?

时间:2011-01-16 12:47:24

标签: wordpress

我不得不将整个wordpress-installation复制到另一台服务器上。我只是在那里安装了一个新的Wordpress,并为我导入了以前Wordpress“导出”的xml文件中的所有数据。无论如何,自定义菜单不包括在内。你知道他们在数据库中的位置,所以我可以从那里抓住它们吗?

8 个答案:

答案 0 :(得分:20)

我有一个Magento安装的网站和WordPress安装,彼此相邻,并且交叉链接。

我最近花了几个小时编写一个类来放入Magento安装,这样我就可以将WordPress菜单渲染为Magento站点中的导航菜单。

此处的帖子很有帮助,但没有一个完整地解释了WordPress菜单存储方式的结构。像许多WP一样,它存储在一系列关系中。这是结构:

(请注意,此示例假设表格前缀为“wp _”)

  1. 首先,重要的是要认识到菜单项可以是帖子(技术上它是一个页面,但页面存储在帖子表中),类别,或者它可以是自定义链接。
  2. 因为WP支持多个菜单,所以首先查看 wp_term_taxonomy 表格表,找到任何带有“nav_menu”分类的术语。请注意该表中的term_id。
  3. 要查找菜单的名称和slug,请访问 wp_terms 表,找到上面步骤2中注明了ID的字词。
  4. 转到 wp_term_relationships 表并列出所有与term_taxonomy_id匹配的记录,该记录与步骤1中的term_id匹配.object_id字段告诉您wp_post.id记录,您可以在其中找到菜单记录。< / LI>
  5. 最后,转到 wp_postmeta 以查找描述菜单的许多元素。特别感兴趣的是:
    • _menu_item_object - 菜单项的类型(页面,自定义或类别)
    • _menu_item_object_id - 菜单项引用的实际POST(或类别,如果是类别)的ID
    • _menu_item_menu_item_parent - MENU的层次结构父母结构(可能与父母后关系不同)
    • _menu_item_url - 菜单项的slug(如果是自定义链接菜单项)
  6. 用于执行上述操作的示例SQL语句:

    SELECT t.term_id 
    FROM wp_term_taxonomy as tax 
    LEFT JOIN wp_terms as t ON tax.term_id = t.term_id 
    WHERE taxonomy = 'nav_menu' and name like '%top%'
    

    (查找名称为“Top”的菜单项,并获取术语ID)

    SELECT p.ID, p.post_title, p.post_name, p.menu_order, n.post_name as n_name, n.post_title as n_title, m.meta_value, pp.meta_value as menu_parent
    FROM wp_term_relationships as txr 
    INNER JOIN wp_posts as p ON txr.object_id = p.ID 
    LEFT JOIN wp_postmeta as m ON p.ID = m.post_id 
    LEFT JOIN wp_postmeta as pl ON p.ID = pl.post_id AND pl.meta_key = '_menu_item_object_id' 
    LEFT JOIN wp_postmeta as pp ON p.ID = pp.post_id AND pp.meta_key = '_menu_item_menu_item_parent' 
    LEFT JOIN wp_posts as n ON pl.meta_value = n.ID 
    WHERE txr.term_taxonomy_id = 3 AND p.post_status='publish' 
        AND p.post_type = 'nav_menu_item' AND m.meta_key = '_menu_item_url' 
    ORDER BY p.menu_order
    

    (根据term_id为3加载菜单数据)

    请注意,此sql语句适用于页面和自定义菜单(我没有任何类别,因此不包含该类别)。加载的数据将允许您使用 wp_options 表中的siteurl构建永久链接,并将post_name附加到末尾(从技术上讲,它没有获得父结构,但WP正确查找页面/帖子没有它)

    <强>更新
    评论者询问如何使用父菜单项组装子菜单项。这需要用PHP完成。下面的内容会为您做到这一点:

    // run the query from above
    $results = $wpdb->get_results('SELECT....');
    
    // declare new variable to store "assembled" menu
    $menu = array();
    
    // loop over the items assigning children to parents
    foreach( $results AS $row ) {
        // assemble key bits for the menu item
        $item = array(
            // handles custom navigation labels
            'title' => ( $row->post_title ) ? $row->post_title : $row->n_title,
            // handles custom links
            'permalink' => ( $row->meta_value ) ? $row->meta_value : get_permalink( $row->ID ),
            // declares empty placeholder for any child items
            'children' => array()
        );
    
        // if the menu item has a parent, assign as child of the parent
        if ( $row->menu_parent ) {
            $menu[ $row->menu_parent ][ 'children' ][] = $item;
        } else {
            $menu[ $row->ID ] = $item;
        }
    }
    
    var_dump( $menu );
    
    // outputs something like below:
    /**
     * array (size=6)
     *  77 => 
     *     array (size=3)
     *       'title' => string 'About Us' (length=8)
     *       'permalink' => string 'http://www.example.com/about' (length=33)
     *       'children' => 
     *        array (size=7)
     *          0 => 
     *            array (size=3)
     *              'title' => string 'Welcome' (length=22)
     *              'permalink' => string 'http://www.example.com/welcome' (length=35)
     *              'children' => 
     *                array (size=0)
     *                  empty
     *          1 => 
     *            array (size=3)
     *              'title' => string 'Mission' (length=20)
     *              'permalink' => string 'http://www.example.com/mission' (length=33)
     *              'children' => 
     *                array (size=0)
     *                  empty
     *  90 => 
     *    array (size=3)
     *      'title' => string 'Contact Us' (length=10)
     *      'permalink' => string 'http://www.example.com/contact' (length=33)
     *      'children' => 
     *        array (size=5)
     *          0 => 
     *            array (size=3)
     *              'title' => string 'Why Us' (length=12)
     *              'permalink' => string 'http://www.example.com/why' (length=35)
     *              'children' => 
     *                array (size=0)
     *                  empty
     *  1258 => 
     *    array (size=3)
     *      'title' => string 'Login' (length=12)
     *      'permalink' => string 'https://customlink.example.com/some/path/login.php' (length=82)
     *      'children' => 
     *        array (size=0)
     *          empty
     */
    

答案 1 :(得分:4)

此设置发生在wp_posts表中。 在表格中查找menu_order大于零的记录。

select * from wp_posts where menu_order > 0;

它还会为您提供wp_options表中配置菜单选项的选项名称。

select * from wp_options where option_name = "nav_menu_options";

另请注意,wordpress导入/导出工具不会从媒体库中导入未在帖子中使用的媒体(图像,视频等)。如果你有你直接链接的东西,它也不会被移动。

答案 2 :(得分:4)

我发现这只是因为我自己在寻找答案。 我看到你的帖子已经很老了,但答案是在wp_postmeta中,运行这个查询:

SELECT *
FROM `wp_postmeta`
WHERE meta_key LIKE '%menu%'
LIMIT 0, 30

你会找到很多条目。

答案 3 :(得分:4)

我一直在寻找整个结构的高低,我终于破解了代码:

SELECT
p.ID,
m.meta_value,
md.post_author,
wp_users.user_nicename,
p.post_parent,
p.menu_order,
md.post_title
FROM
wp_posts AS p
INNER JOIN wp_postmeta AS m ON m.post_id = p.ID
INNER JOIN wp_posts AS md ON md.ID = m.meta_value AND m.meta_value = md.ID
INNER JOIN wp_users ON md.post_author = wp_users.ID
WHERE
p.menu_order > 0 AND
p.post_type = 'nav_menu_item' AND
m.meta_key = '_menu_item_object_id'
ORDER BY
p.menu_order ASC

答案 4 :(得分:2)

对于仍然遇到此问题的人们,我将其用简单的phpMyAdmin术语来表示。

涉及6个表。

1。 wp_term_taxonomy

WordPress将每个导航菜单的位置保留为“ wp_term_taxonomy”表中的一条记录,但是唯一的唯一标识符是数字ID。 1、2、3等

enter image description here

您还可以看到“计数”数字,显示每个菜单位置的项目数。

这是您键入时创建的内容

register_nav_menu('your-navmenu', 'Your Navmenu');

在数据库的任何地方都找不到名称“您的导航菜单”,该名称仅用于在界面中对其进行标签。

但是,您会在其他地方找到“您的导航菜单”。

2。 wp_terms

您的实际菜单存储在“ wp_terms”中。

WordPress对此术语感到困惑。在界面中,它具有“显示位置”和“菜单”。该位置是register_nav_menu()创建的位置。最好将界面中的“菜单”视为页面列表。

我在这里给他们起了“导航列表”的名字。

enter image description here

菜单还具有自己的ID,这些ID通常与位置ID相同(因为人们经常同时为一个位置创建一个菜单),这会造成混乱。

此项目是通过管理界面中的“菜单”页面创建的:

enter image description here

3。 wp_options

您将在“ wp_options”中看到“您的导航菜单”提示。 WordPress在这里存储了导航菜单的当前设置。它将其存储在序列化数组中(使用PHP的serialize()函数)。

enter image description here

原始数组(使用unserialize()获得)如下。

array (
  'custom_css_post_id' => 56,
  'nav_menu_locations' => 
  array (
    'your-navmenu' => 2,
    'another-navmenu' => 3,
  ),
)

这根据您将菜单设置为哪个位置(按其子弹;“您的导航菜单”,“另一个导航菜单”)而改变。

4。 wp_posts

菜单项本身存储在另一个表“ wp_posts”中。

您可以通过搜索“ nav_menu_item”找到这些内容:

enter image description here

为简洁起见,我已删掉了大部分专栏,并保留了相关专栏。

在这里,您可以看到“ menu_order”列,该列将其顺序存储在它们所在的菜单中。

菜单项的存储方式与实际的帖子一样,带有帖子ID和URL(但是如果您访问它,它将带404,并且它们没有“ post_content”)。

所有存储为子项目的菜单项都将具有“ post_parent” ID。这是其父级链接到的实际页面的ID,而不是其菜单项ID。

5。 wp_postmeta

菜单项链接到“ wp_postmeta”表中的相应页面。

菜单项ID('post_id')相对于帖子ID('meta_value')存储在'_menu_item_object_id'行中,而子项链接到其父项在'_menu_item_menu_item_parent'行中。 / p>

enter image description here

在这里很容易感到困惑。

'post_id'是菜单项的ID,而不是帖子的ID。 “ meta_value”是“ _menu_item_object_id”行中帖子的ID,而不是菜单项,但它是“ _menu_item_menu_item_parent”行中父菜单项的ID,而不是帖子。

6。 wp_term_relationships

每个菜单项和每个菜单位置之间的链接存储在“ wp_term_relationships”中。

enter image description here

在这里,“ object_ID”是菜单项的帖子ID(如在“ wp_posts”中所示),而“ term_taxonomy_id”是菜单位置的ID(如在“ wp_term_taxonomy”中所示)。

希望这可以为某些人清除。我知道我一开始很困惑。

答案 5 :(得分:0)

我在cale_b的查询中添加了其他列。 lvl列具有缩进深度。

假设:

  • 最大深度为6,所以我定义了6个变量。
  • 菜单的post_id超过6。大多数人已经超过了该数字。

查询:

select case when a.meta_value = 0 then least(@lvl:=1, @p1:=a.id) 
            when a.meta_value = @p1 then least(@lvl:=2, @p2:=a.id) 
            when a.meta_value = @p2 then least(@lvl:=3, @p3:=a.id) 
            when a.meta_value = @p3 then least(@lvl:=4, @p4:=a.id) 
            when a.meta_value = @p4 then least(@lvl:=5, @p5:=a.id) 
            when a.meta_value = @p5 then least(@lvl:=6, @p6:=a.id) 
       end lvl
      ,a.id
  from (
        SELECT p.id
              ,p.post_title
              ,p.post_name
              ,pp.meta_value 
              ,p.menu_order
              ,n.post_name as n_name
              ,n.post_title as n_title
              ,m.meta_value meta2
          FROM wordpress_dw.stat_term_relationships as txr 
               INNER JOIN wordpress_dw.stat_posts as p ON txr.object_id = p.ID 
               LEFT JOIN wordpress_dw.stat_postmeta as m ON p.ID = m.post_id and m.meta_key = '_menu_item_url' 
               LEFT JOIN wordpress_dw.stat_postmeta as pl ON p.ID = pl.post_id AND pl.meta_key = '_menu_item_object_id' 
               LEFT JOIN wordpress_dw.stat_postmeta as pp ON p.ID = pp.post_id AND pp.meta_key = '_menu_item_menu_item_parent' 
               LEFT JOIN wordpress_dw.stat_posts as n ON pl.meta_value = n.ID 
              ,(select @lvl:=0, @p1:=0, @p2:=0, @p3:=0, @p4:=0, @p5:=0, @p6:=0) x
         WHERE txr.term_taxonomy_id = 2  -- your menu term id 
           AND p.post_status='publish'
           AND p.post_type = 'nav_menu_item' 
         ORDER BY p.menu_order  
       ) a       

结果:

lvl |id  |
----|----|
1   |508 |
1   |509 |
2   |510 |
3   |511 |
3   |512 |
3   |513 |
3   |514 |
2   |515 |
1   |516 |
2   |517 |
2   |518 |
3   |519 |
3   |520 |
3   |521 |
3   |522 |

答案 6 :(得分:0)

要简化/复杂化@random_user_name的两个查询,可以将它们压缩为1个查询,以便所需的唯一输入参数是菜单名称。像这样:

SELECT p.ID, p.post_title, p.post_name, p.menu_order, 
       n.post_name as n_name, n.post_title as n_title, 
       m.meta_value, pp.meta_value as menu_parent
  FROM       wp_term_taxonomy      as tax 
  INNER JOIN wp_terms              as t   ON tax.term_id   = t.term_id
  INNER JOIN wp_term_relationships as txr ON t.term_id     = txr.term_taxonomy_id
  INNER JOIN wp_posts              as p   ON txr.object_id = p.ID       AND p.post_status = 'publish' AND p.post_type = 'nav_menu_item'
  LEFT  JOIN wp_postmeta           as m   ON p.ID          = m.post_id  AND m.meta_key    = '_menu_item_url'
  LEFT  JOIN wp_postmeta           as pl  ON p.ID          = pl.post_id AND pl.meta_key   = '_menu_item_object_id' 
  LEFT  JOIN wp_postmeta           as pp  ON p.ID          = pp.post_id AND pp.meta_key   = '_menu_item_menu_item_parent' 
  LEFT  JOIN wp_posts              as n   ON pl.meta_value = n.ID 
 WHERE tax.taxonomy = 'nav_menu' 
   AND t.name    like '%main nav%'
 ORDER BY p.menu_order

答案 7 :(得分:0)

我认为,此SQL语句比其他方法更彻底,更清楚地完成了工作。您需要做的就是在第一次加入时将菜单名称放入t.name = 'main nav'中。它会输出菜单信息的所有提示 XFN字段。

 SELECT t.name as 'menu name',
        p1.ID as 'post id', p1.post_title as title, p1.post_name as slug, p1.menu_order as 'order',
        m1.meta_value as classes, m2.meta_value as menu_item_parent, m3.meta_value as object, m4.meta_value as object_id,
        m5.meta_value as target, m6.meta_value as type, m7.meta_value as url,
        p2.post_title as 'title-2', p2.post_name as 'slug-2'
   FROM       wp_term_taxonomy      as tax
   INNER JOIN wp_terms              as t   ON t.term_id            = tax.term_id   AND t.name = 'main nav'
   INNER JOIN wp_term_relationships as txr ON txr.term_taxonomy_id = t.term_id
   INNER JOIN wp_posts              as p1  ON p1.ID                = txr.object_id AND p1.post_status = 'publish' AND p1.post_type = 'nav_menu_item'
   LEFT  JOIN wp_postmeta           as m1  ON m1.post_id           = txr.object_id AND m1.meta_key    = '_menu_item_classes'
   LEFT  JOIN wp_postmeta           as m2  ON m2.post_id           = txr.object_id AND m2.meta_key    = '_menu_item_menu_item_parent'
   LEFT  JOIN wp_postmeta           as m3  ON m3.post_id           = txr.object_id AND m3.meta_key    = '_menu_item_object'
   LEFT  JOIN wp_postmeta           as m4  ON m4.post_id           = txr.object_id AND m4.meta_key    = '_menu_item_object_id'
   LEFT  JOIN wp_postmeta           as m5  ON m5.post_id           = txr.object_id AND m5.meta_key    = '_menu_item_target'
   LEFT  JOIN wp_postmeta           as m6  ON m6.post_id           = txr.object_id AND m6.meta_key    = '_menu_item_type'
   LEFT  JOIN wp_postmeta           as m7  ON m7.post_id           = txr.object_id AND m7.meta_key    = '_menu_item_url'
   LEFT  JOIN wp_posts              as p2  ON p2.ID                = m4.meta_value AND p2.post_status = 'publish' AND m6.meta_value = 'post_type'
  WHERE tax.taxonomy = 'nav_menu'
  ORDER BY p1.menu_order