如何在没有插件的自定义帖子类型中自定义工作区/管理区?

时间:2017-01-09 作者:kater louis

奇怪的是,我在网上找不到多少关于我的欲望的消息来源。所以我希望这是一件小事(尽管我担心不是,Wordpress只是……)。

当然,我的自定义帖子类型中需要自定义字段。

Wordpress处理自定义字段的原生方式非常不方便,我不能期望我的客户处理这些下拉列表,根据需要添加字段——

到目前为止,我使用“高级自定义字段”插件管理我的自定义字段。

我想了解如何自己做到这一点,因此希望在定制“新帖子”和“编辑帖子”页面的工作区/管理区方面有更多的灵活性。

必须有一种方法来设置代码中的自定义字段,并影响如何在管理页面上访问输入。

举一个简单的例子,我想在页面中添加一个快速链接功能,管理员可以添加只包含标题和url的帖子(我知道本地的“链接”区域,并有意避免使用它)

到目前为止,我制作了一个简单的单文件插件,其中包含自定义帖子类型的声明:

<?php

    /*
    Plugin Name: Got Nexxt Quicklinks 
    Plugin URI: none
    Description: Quicklinks custom post type + special admin area
    Author: René Eschke
    Version: 1.0
    Author URI: http://www.eschke.info/
    */

    function my_custom_post_quicklinks() {
      $labels = array(
          \'name\'               => _x( \'Quicklinks\', \'post type general name\' ),
          \'singular_name\'      => _x( \'Quicklink\', \'post type singular name\' ),
          \'add_new\'            => _x( \'Hinzuf&uuml;gen\', \'book\' ),
          \'add_new_item\'       => __( \'Quicklink hinzuf&uuml;gen\' ),
          \'edit_item\'          => __( \'Quicklink bearbeiten\' ),
          \'new_item\'           => __( \'Neue Quicklink\' ),
          \'all_items\'          => __( \'Alle Quicklinks\' ),
          \'view_item\'          => __( \'Quicklink ansehen\' ),
          \'search_items\'       => __( \'Quicklink durchsuchen\' ),
          \'not_found\'          => __( \'Kein Quicklink gefunden\' ),
          \'not_found_in_trash\' => __( \'Keine Quicklinks im Papierkorb gefunden\' ), 
          \'parent_item_colon\'  => \'\',
          \'menu_name\'          => \'Quicklinks\'
      );
      $args = array(
        \'labels\' => $labels,
        \'menu_icon\' => \'dashicons-admin-links\',
        \'description\' => \'Quicklinks sind vor allem für Shortcuts zu bestimmten Podcast-positionen da\',
        \'public\' => true,
        \'menu_position\' => 5,
        \'supports\' => array(\'title\'), 
        \'has_archive\' => false,
      );
      register_post_type(\'quicklink\', $args);
    }
    add_action( \'init\', \'my_custom_post_quicklinks\' );

?>
再次强调:I want to implement this myself all in code without using a plugin.

谢谢

done with Advanced Custom Fields

3 个回复
最合适的回答,由SO网友:kater louis 整理而成

我找到了一个完全可定制的解决方案。LWS mo说明的一般方法保持不变。但不是使用add_meta_box() 我用过add_post_meta()

add_meta_box() 需要打印HTML的回调函数。使用add_post_meta() 回调必须手动挂接。

这里的关键动作钩是edit_form_after_editor. (实际上,管理工作区有很多挂钩> WP Codex)

我还有一个重要的见解:所有这些changes apply to every post type 除非在post类型与所需类型不同时返回函数。因此,我创建了一个helper函数,需要在动作挂钩中首先调用它。

此外,我跳过了在add_action 函数,并使用匿名函数作为参数。我觉得这样更方便<如果我错过了更大的东西,请纠正我

以下是简短版本的代码:

// helper function to prevent editing other post types than desired
function is_my_posttype() {
    global $post;
    if ($post->post_type == "my_custom_posttype") return true;
    else return false;
}

// create custom post type
add_action("init", function() {
    $labels = ... 
    $args = ...
    register_post_type("my_custom_posttype", $args); 
});

// add custom fields 
add_action("add_meta_boxes", function() {
    if (!is_my_posttype()) return;
    add_post_meta($post->ID, "url", "", true); // true creates a unique custom field; no initial value needed
    add_post_meta(...)
    // create as many as you need
});

// insert the html in both ADD and EDIT forms
// $post parameter required
add_action("edit_form_after_editor", function( $post ) {
    if (!is_my_posttype()) return;

    wp_nonce_field( basename( __FILE__ ), \'my_custom_nonce\' ); // to check for later in save function 

    $stored_meta = get_post_meta( $post->ID );

    // now do whatever magic you want; 
    // it gets inserted straight below the editor
    // without any wrapping html cage
    ?> 
        <label ...>Some Label</label>
        <input type="text" name="url" value="<?php if (isset($stored_meta["url"])) echo $stored_meta["url"][0]; ?>" />
        Add even more
    <?php
});

// make the custom fields savable 
add_action("save_post", function( $post_id )) {
    if (!is_my_posttype()) return;

    // Checks save status
    $is_autosave = wp_is_post_autosave( $post_id );
    $is_revision = wp_is_post_revision( $post_id );
    $is_valid_nonce = ( isset( $_POST[ \'my_custom_nonce\' ] ) && wp_verify_nonce( $_POST[ \'my_custom_nonce\' ], basename( __FILE__ ) ) ) ? \'true\' : \'false\';

    // Exits script depending on save status
    if ( $is_autosave || $is_revision || !$is_valid_nonce ) {
        return;
    }

    update_post_meta($post_id, "url", $_POST["url"]);
    update_post_meta( ... )
    // update all the other post metas 

});

SO网友:LWS-Mo

我想你在寻找“元盒子”。

您将与add_meta_box()create 一个或多个用于帖子类型的新元框。(Codex)

你必须设置一些callback function 其中包含要显示/显示的字段的HTML。

您还需要一个函数save 这些字段使用add_post_meta()update_post_meta(). (抄本至ADDUPDATE)

如果你想的话remove 可以使用的一些现有元框remove_meta_box(). (Codex)

<小时>

Some Details:

使用以下代码,您可以在“快速链接”帖子类型的新建/编辑屏幕上创建一个新的元框。(因为我输入了“quicklink”作为帖子类型)

function create_custom_metabox() {
    add_meta_box( 
        \'my_meta\', // HTML \'id\' attribute of the metabox
        __( \'My Setting\', \'textdomain\' ), // Title of metabox
        \'my_fields_callback\', // Function that prints out the HTML for metabox
        \'quicklink\', // The post-type of writing screen on which to show the edit screen section (example \'post\' or \'page\')
        \'normal\', // The part of the page where the metabox should be shown (\'normal\', \'advanced\', or \'side\')
        \'high\' // The priority within the context where the boxes should show (\'high\', \'core\', \'default\' or \'low\')
    );
}
add_action( \'add_meta_boxes\', \'create_custom_metabox\' );
在这段代码之后,您将看到一个新的元框,但它将是空的,没有要显示的字段。

接下来,我们用新字段创建一个新的回调函数:(请参见中的函数名和回调参数add_meta_box() 上文)

function my_fields_callback( $post ) {

    // creating a custom nonce
    wp_nonce_field( basename( __FILE__ ), \'my_custom_nonce\' );

    // see and get if some meta is already saved
    $stored_meta = get_post_meta( $post->ID );

    ?>
    <!-- Textfield START -->
    <p>
        <span class="my-row-title">
            <label for="meta-text" class="my-row-title"><?php _e( \'Text\', \'textdomain\' )?></label>
        </span>
        <div class="my-row-content">
            <input type="text" name="meta-text" id="meta-text" placeholder="Text..." value="<?php if ( isset ( $stored_meta[\'meta-text\'] ) ) echo $stored_meta[\'meta-text\'][0]; ?>" />

        </div>
    </p>
    <!-- Textfield END -->

<?php
}
在这段代码之后,您将看到一个新的输入字段和标签。但如果您输入了某些内容,它仍然不会被保存!因此,我们需要在此添加一个保存函数:

function save_my_meta( $post_id ) {

    // Checks save status
    $is_autosave = wp_is_post_autosave( $post_id );
    $is_revision = wp_is_post_revision( $post_id );
    $is_valid_nonce = ( isset( $_POST[ \'my_custom_nonce\' ] ) && wp_verify_nonce( $_POST[ \'my_custom_nonce\' ], basename( __FILE__ ) ) ) ? \'true\' : \'false\';

    // Exits script depending on save status
    if ( $is_autosave || $is_revision || !$is_valid_nonce ) {
        return;
    }


    // save our new created field
    if( isset( $_POST[ \'meta-text\' ] ) ) {
        // if there is some content in the field, we update it
        update_post_meta( $post_id, \'meta-text\', sanitize_text_field( $_POST[ \'meta-text\' ] ) );
    }


}
add_action( \'save_post\', \'save_my_meta\' );
之后,我们可以保存新字段的值。

如果要显示这些值,可以使用get_post_meta() 作用(Codex) 像这样:

$my_meta_value = get_post_meta( get_the_ID(), \'meta-text\', true );

if( !empty( $my_meta_value ) ) {
    echo $my_meta_value;
}
因此,您可以看到需要几个函数。有很多教程,here is an old one which still functions.

对不起,我现在找不到德语的。

还要确保在保存和检索字段时注意清理字段的不同值。

我希望这有帮助!

<小时>

Update:

创建元框时add_meta_box() 函数,您可以使用上下文参数设置元框的显示位置。。。

add_meta_box( 
            \'my_meta\', 
            __( \'My Setting\', \'textdomain\' ), 
            \'my_fields_callback\', 
            \'quicklink\',
            \'normal\', // The part of the page where the metabox should be shown (\'normal\', \'advanced\', or \'side\')
            \'high\'
        );
如果您选择side, 该框将在右侧边栏上创建。

Regarding ACF and fields without the wrapper container:

似乎当您使用ACF创建一个字段而不使用meta box包装器/容器时,一些元素被隐藏了,并且添加了一些额外的样式来隐藏容器!

因此,我认为最好的方法是加载一些自定义css,或者只在包含自定义字段的帖子类型的编辑/新建页面上加载jQuery。

function add_scripts_and_styles()
{
    global $typenow;
    if( \'quicklink\' != $typenow )
        return;         

    echo "
<script type=\'text/javascript\'>
    jQuery(document).ready( function($) {
        $(\'#my_meta\').removeClass(\'postbox\');
        $(\'#my_meta h3\').hide();
    });     
</script>
<style type=\'text/css\'>
    /* CUSTOM RULES */
</style>
";
}
add_action( \'admin_head-post-new.php\', \'add_scripts_and_styles\' );
add_action( \'admin_head-post.php\', \'add_scripts_and_styles\' );

Source: This Stackexchange answer

<人力资源>Nonces:我试着解释一下,但也许抄本会让你更清楚:

WP环境中的nonce是一种安全特性。它是数字和字母的随机和唯一组合,仅在有限的时间内有效,并且每个用户都有效。

在这种情况下,我们在表单中使用它来检查输入数据是否来自真正的用户。系统将在保存时检查nonce,以查看是否没有人/其他人试图保存数据。

或者正如法典所说:

nonce字段用于验证表单请求的内容是否来自当前站点,而不是其他地方。

你可以阅读herehere 关于nonces。

SO网友:janw

您要找的是一个自定义元框

您将需要add_meta_box(), 看一看。这里还有一个很好的教程,介绍了一些基本知识:https://www.smashingmagazine.com/2011/10/create-custom-post-meta-boxes-wordpress/

相关推荐

Admin Theme customization

我遵循wordpress codex网站上关于通过插件创建管理主题的说明。我激活了插件,但我的样式表没有包含在<head>.. 这是我的代码:add_action( \'admin_init\', \'kd_plugin_admin_init\' ); add_action( \'admin_menu\', \'kd_plugin_admin_menu\' ); function kd_plugin_admin_init() { /* Register