WordPress - 以编程方式在页面中插入 Elementor Widgets

WordPress - Programmatically insert Elementor Widgets in a page

我在我的 WordPress 网站上安装了 Elementor Pro,我正在编写一个自定义插件,它可以做一些事情并以编程方式创建一个新页面。我能够创建页面,但问题是,我想以编程方式在此新页面中插入一个 Elementor Widget。

我已经联系了 Elementor 支持人员,看看他们是否有任何意见要告诉我。但是他们的回复是:

As much as I'd like to assist you with this, custom code/snippet or any guidance for this is beyond the scope of our support, given that we provide support for Elementor's existing features only.

那么我是否可以通过代码实现此目的,我的意思是将特定的 Elementor Widget 插入页面?

这不是最好的解决方案,但我会解释我是如何找到解决方法的。

对我来说,我尝试监控我的 WordPress 网站的数据库,以查看当我使用 Elementor 创建新页面时发生的所有更改。我监控的表是:wp_postswp_postmeta。请注意,如果您在安装 WordPress 时选择了不同的前缀,wp_ 前缀可能与您的情况不同。

创建页面时,会在 wp_posts table 中插入一个新行,其 post_type 值为 page。记下 post_id 值(为了便于解释,让 post_id123)。

此页面的元数据将存储在 wp_postmeta table 中,这就是 Elementor 存储与每个页面或 Post 相关的数据的位置。使用 phpMyAdmin,我访问了 table 并搜索了具有 post_id = 123 的记录(这里 123 是页面的 ID)。您可以像这样使用 phpMyAdmin 的 Search 选项卡(在选择 wp_postmeta table 之后):

或者,可以 运行 在 phpMyAdmin 的 SQL 选项卡 中进行这样的查询:

SELECT * FROM `wp_postmeta` WHERE `post_id` = 123

现在您将看到附加到我们页面的所有元数据(ID 123)。

就我而言,我之前已经在 Elementor 中为此页面 (ID 123) 添加了一个小部件。因此,正如您在上图中所见,它附加了一些元数据。

_wp_page_template = page-fullwidth.php 在那里是因为我为我的页面的 模板属性 选择了 Full Width :

并且似乎需要这两个值才能理解该页面是使用 Elementor 创建的:

_elementor_edit_mode = builder
_elementor_template_type = wp-page

所以我们绝对需要它。然后对于 Elementor 版本值:

_elementor_version = 2.9.14
_elementor_pro_version = 2.10.3

您可以使用常量:ELEMENTOR_VERSION(如果您有免费版 Elementor 插件)和 ELEMENTOR_PRO_VERSION(如果您有专业版插件)。如果您安装了相应版本(免费或专业版)的 Elementor 插件,则这些常量已经定义。

然后是重要的部分,Widget 的数据和布局相关数据似乎存储在:_elementor_data_elementor_controls_usage 元键中。

_elementor_data 的值似乎是 JSON 字符串。所以你可以使用任何 online JSON parser 来查看它有什么。在我的案例中,值是这样的:

[{"id":"2e0569b","elType":"section","settings":[],"elements":[{"id":"e2a6dbb","elType":"column","settings":{"_column_size":100,"_inline_size":null},"elements":[{"id":"441552a","elType":"widget","settings":{"tag_ids":"21"},"elements":[],"widgetType":"listings_grid_new"}],"isInner":false}],"isInner":false}]

解析后,它看起来像这样:

[
  {
    "id": "2e0569b",
    "elType": "section",
    "settings": [],
    "elements": [
      {
        "id": "e2a6dbb",
        "elType": "column",
        "settings": {
          "_column_size": 100,
          "_inline_size": null
        },
        "elements": [
          {
            "id": "441552a",
            "elType": "widget",
            "settings": {
              "tag_ids": "21"
            },
            "elements": [],
            "widgetType": "listings_grid_new"
          }
        ],
        "isInner": false
      }
    ],
    "isInner": false
  }
]

由于我之前将该小部件添加到我的页面,并将标签 ID 输入框的值设置为 21(通过 Elementor Editor),我明白我必须传递新值来替换 21.

然后是 _elementor_controls_usage 元密钥。它的价值是这样的:

a:3:{s:17:"listings_grid_new";a:3:{s:5:"count";i:1;s:15:"control_percent";i:1;s:8:"controls";a:1:{s:7:"content";a:1:{s:13:"section_query";a:2:{s:7:"loc_ids";i:1;s:7:"tag_ids";i:1;}}}}s:6:"column";a:3:{s:5:"count";i:1;s:15:"control_percent";i:0;s:8:"controls";a:1:{s:6:"layout";a:1:{s:6:"layout";a:1:{s:12:"_inline_size";i:1;}}}}s:7:"section";a:3:{s:5:"count";i:1;s:15:"control_percent";i:0;s:8:"controls";a:0:{}}}

这是序列化数据。您可以使用任何 online tool to unserialize 该数据。这是反序列化后我的样子:

array (
  'listings_grid_new' => 
  array (
    'count' => 1,
    'control_percent' => 1,
    'controls' => 
    array (
      'content' => 
      array (
        'section_query' => 
        array (
          'loc_ids' => 1,
          'tag_ids' => 1,
        ),
      ),
    ),
  ),
  'column' => 
  array (
    'count' => 1,
    'control_percent' => 0,
    'controls' => 
    array (
      'layout' => 
      array (
        'layout' => 
        array (
          '_inline_size' => 1,
        ),
      ),
    ),
  ),
  'section' => 
  array (
    'count' => 1,
    'control_percent' => 0,
    'controls' => 
    array (
    ),
  ),
)

看起来基本上是与布局相关的数据。所以我想不做任何编辑这个值,并按原样使用它。


我们来做最后一道菜吧

为了创建页面,我使用了 wp_insert_post() method, which returns the new page_id after insertion. And after creating the page, I used the update_post_meta() 方法,传递了这个 page_id 并附加了元数据。

我的最终代码如下所示:

//-- set the new page arguments
$new_page_args = array(
    'post_type'     => 'page',              //-- this is of type 'page'
    'post_title'    => 'My Dynamic Page',   //-- title of the page              
    'post_status'   => 'publish'            //-- publish the page
);

//-- insert the page
$new_page_id = wp_insert_post( $new_page_args );

if( is_wp_error( $new_page_id ) )
{
    echo 'Unable to create the page!';        
    die;
}

if( defined( 'ELEMENTOR_VERSION' ) )    //-- if FREE version of Elementor plugin is installed
{
    update_post_meta( $new_page_id, '_elementor_version', ELEMENTOR_VERSION );
}

if( defined( 'ELEMENTOR_PRO_VERSION' ) )    //-- if PRO version of Elementor plugin is installed
{
    update_post_meta( $new_page_id, '_elementor_pro_version', ELEMENTOR_PRO_VERSION );
}

update_post_meta( $new_page_id, '_wp_page_template', 'page-fullwidth.php' );    //-- for using full width template

//-- for Elementor
update_post_meta( $new_page_id, '_elementor_edit_mode', 'builder' );
update_post_meta( $new_page_id, '_elementor_template_type', 'wp-page' );

//-- Elementor layout
update_post_meta( $new_page_id, '_elementor_controls_usage', 'a:3:{s:17:"listings_grid_new";a:3:{s:5:"count";i:1;s:15:"control_percent";i:1;s:8:"controls";a:1:{s:7:"content";a:1:{s:13:"section_query";a:2:{s:7:"loc_ids";i:1;s:7:"tag_ids";i:1;}}}}s:6:"column";a:3:{s:5:"count";i:1;s:15:"control_percent";i:0;s:8:"controls";a:1:{s:6:"layout";a:1:{s:6:"layout";a:1:{s:12:"_inline_size";i:1;}}}}s:7:"section";a:3:{s:5:"count";i:1;s:15:"control_percent";i:0;s:8:"controls";a:0:{}}}' );

$tag_id = '56'; //-- new value
//-- Elementor data ( I have injected the new $tag_id value in the string )
update_post_meta( $new_page_id, '_elementor_data', '[{"id":"2e0569b","elType":"section","settings":[],"elements":[{"id":"e2a6dbb","elType":"column","settings":{"_column_size":100,"_inline_size":null},"elements":[{"id":"441552a","elType":"widget","settings":{"tag_ids":"'. $tag_id .'"},"elements":[],"widgetType":"listings_grid_new"}],"isInner":false}],"isInner":false}]' );

请记住,这不是完美的解决方案。但是我解释了我是如何找到解决这个问题的方法的。

也许其他人会发布更好的解决方案。 ;)