source

Wordpress는 사용자 지정 메뉴를 어디에 저장합니까?

lovecheck 2023. 2. 9. 22:46
반응형

Wordpress는 사용자 지정 메뉴를 어디에 저장합니까?

워드프레스 설치 전체를 다른 서버에 복사해야 했습니다.새로운 Wordpress를 설치하고 이전 Wordpress "내보낸" xml 파일에서 모든 데이터를 가져왔습니다.어쨌든 커스텀 메뉴는 포함되지 않았습니다.데이터베이스 어디에 있는지 아세요? 거기서 가져올 수 있어요.

Magento 설치와 WordPress 설치를 나란히 하여 상호 링크하는 사이트가 있습니다.

최근 몇 시간 동안 클래스를 작성하여 WordPress 메뉴를 Magento 사이트의 탐색 메뉴로 렌더링할 수 있도록 했습니다.

여기 게시물은 도움이 되었지만, WordPress 메뉴가 어떻게 저장되는지에 대한 자세한 설명은 없습니다.많은 WP와 마찬가지로 일련의 관계에 저장됩니다.구조는 다음과 같습니다.

(이 예에서는 "wp_"의 경우 테이블프리픽스를 상정하고 있습니다).

  1. 우선 메뉴 항목은 포스트(기술적으로는 페이지이지만 페이지는 포스트 테이블에 저장됨), 카테고리 또는 커스텀 링크일 수 있습니다.
  2. WP는 여러 메뉴를 지원하므로 먼저 wp_term_taxonomy 테이블에서 'nav_menu' 분류법에 해당하는 용어를 찾습니다.이 테이블에서 term_id를 확인합니다.
  3. 메뉴 이름과 slug를 찾으려면 wp_terms 테이블을 방문하여 위의 2단계에서 언급한 ID를 가진 용어를 찾으십시오.
  4. wp_term_relations 테이블로 이동하여 1단계부터 term_id와 일치하는 term_taxonomy_id를 가진 모든 레코드를 나열합니다.object_id 필드에는 메뉴 레코드를 찾을 수 있는wp_post.id 레코드가 표시됩니다.
  5. 마지막으로 wp_postmeta로 이동하여 메뉴를 설명하는 많은 요소를 찾습니다.특히 관심사는 다음과 같습니다.
    • _menu_item_object - 메뉴 항목의 TYPE(페이지, 커스텀 또는 카테고리)
    • _menu_item_object_id - 메뉴 항목이 참조하는 실제 POST(또는 카테고리인 경우 카테고리)의 ID
    • _menu_item_menu_item_parent - MENU의 상속적 부모구조(사후 부모관계와는 다를 수 있음)
    • _menu_item_url - 메뉴 항목의 슬래그(커스텀 링크 메뉴 항목인 경우)

위에서 설명한 작업을 수행하기 위한 샘플 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%'

('위'라는 이름의 메뉴 항목을 검색하여 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

(3의 term_id를 기준으로 메뉴 데이터 표시)

이 sql 문은 페이지 및 사용자 지정 메뉴에 대해 작동합니다(카테고리가 없으므로 포함시키지 않음).로드된 데이터에 의해 post_name을 wp_options 테이블에서 siteurl을 사용하여 permalink를 구축할 수 있습니다(기술적으로는 부모 구조를 취득할 수 없지만 WP는 post_name을 사용하지 않아도 페이지/post를 올바르게 찾을 수 있습니다).


한 해설자가 부모 메뉴 항목과 자녀 메뉴 항목을 조합하는 것에 대해 물었습니다.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
 */

아직 이 질문을 받고 있는 분들을 위해 간단한 phpMyAdmin 용어로 설명하겠습니다.

6개의 테이블이 있습니다.

1. wp_term_displays

WordPress는 각 내비게이션 메뉴 위치를 'wp_term_taxonomy' 테이블의 레코드로 유지하지만 고유 식별자는 숫자 ID(1, 2, 3 등)뿐입니다.

여기에 이미지 설명 입력

각 메뉴 위치의 항목 수를 나타내는 '카운트' 수치도 볼 수 있습니다.

입력 시 생성되는 내용입니다.

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

데이터베이스에서 '내비게이션 메뉴'라는 이름은 찾을 수 없습니다. 이 이름은 인터페이스에서 라벨링하는 데만 사용됩니다.

그러나 '내비게이션 메뉴'는 다른 곳에 있습니다.

2. wp_module

실제 메뉴는 'wp_terms'에 저장됩니다.

워드프레스는 이 용어와 혼동된다.인터페이스에는 '표시 위치'와 '메뉴'가 있습니다.로케이션은 에 의해 작성된 것입니다.register_nav_menu() 의 '메뉴것이 좋습니다. 인터페이스의 '메뉴'를 페이지 목록으로 간주하는 것이 좋습니다.

여기에 '내비게이션 리스트'라는 이름을 붙여놨어요

여기에 이미지 설명 입력

또한 메뉴에는 위치 ID와 동일한 자체 ID가 있습니다(많은 경우 사람들은 한 위치에 대해 동시에 하나의 메뉴를 만들기 때문에). 이는 혼동될 수 있습니다.

이 항목은 관리 인터페이스의 '메뉴' 페이지에서 생성됩니다.

여기에 이미지 설명 입력

3. wp_module

'wp_options'에 'your-nav-menu' 슬래그가 표시됩니다.여기서 WordPress는 탐색 메뉴에 대한 현재 설정을 저장합니다.PHP 기능을 사용하여 직렬화된 배열에 저장합니다.

여기에 이미지 설명 입력

원래의 어레이(를 사용해 취득)는, 다음과 같습니다.

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

이는 사용자가 어떤 메뉴(ID별, '2', '3'별)로 설정하느냐에 따라 달라집니다(슬러그별, 'your-nav menu', 'another-nav menu'별).

4. wp_module

메뉴 항목 자체는 다른 테이블인 'wp_posts'에 저장됩니다.

'nav_menu_item'을 검색하면 다음 항목을 찾을 수 있습니다.

여기에 이미지 설명 입력

나는 간결함을 위해 대부분의 칼럼을 오려내고 관련 칼럼을 보관했다.

여기서 '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' 행에 상위 항목과 연동됩니다.

여기에 이미지 설명 입력

여기는 헷갈리기 쉬워요.

'post_id'는 게시물이 아닌 메뉴 항목의 ID입니다.'meta_value'는 '_menu_item_object_id' 행에서 메뉴 항목이 아닌 게시물의 ID이지만, '_menu_item_menu_item_parent' 행에서 게시물이 아닌 상위 메뉴 항목의 ID입니다.

6. wp_term_관계

각 메뉴 항목과 메뉴 위치 간의 링크는 'wp_term_relations'에 저장됩니다.

여기에 이미지 설명 입력

여기서는 'object_'ID'는 메뉴 항목의 게시 ID('wp_posts' 참조), 'term_taxonomy_id'는 메뉴 위치의 ID('wp_term_taxonomy' 참조)입니다.

이걸로 몇몇 사람들이 해결됐으면 좋겠네요.처음에 많이 혼란스러웠다는 거 알아요.

제가 직접 답을 찾다가 이걸 발견했어요.당신의 투고는 꽤 오래되었지만 답은 wp_postmeta에 있습니다.다음 쿼리를 실행합니다.

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

많은 엔트리를 찾을 수 있습니다.

이 설정은 wp_posts 테이블에서 이루어집니다.테이블에서 menu_order가 0보다 큰 레코드를 찾습니다.

select * from wp_posts where menu_order > 0;

또한 메뉴 옵션이 설정되어 있는wp_options 테이블의 옵션 이름도 표시됩니다.

select * from wp_options where option_name = "nav_menu_options";

또한 워드프레스 Import/export 도구는 투고에서 사용되지 않는 미디어(이미지, 비디오 등)를 미디어 라이브러리에서 Import하지 않습니다.직접 연결된 파일이 있는 경우에도 이동되지 않습니다.

나는 구조 전체를 샅샅이 뒤졌고 마침내 암호를 풀었다.

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

@random_user_name의 두 가지 쿼리를 단순화/복잡화하기 위해 필요한 입력 파라미터가 메뉴 이름뿐이 되도록 이들을 하나의 쿼리로 압축할 수 있습니다.다음과 같이 합니다.

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

이 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

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 |

언급URL : https://stackoverflow.com/questions/4705413/where-does-wordpress-store-custom-menus

반응형