【问题标题】:Call PHP function inside TinyMCE modal window on the WordPress backend在 WordPress 后端的 TinyMCE 模式窗口中调用 PHP 函数
【发布时间】:2013-10-05 04:22:33
【问题描述】:

我正在使用为 TinyMCE 插件注册的静态 .js 文件。您单击新按钮,它会打开模态窗口,其中包含一个表单,我用它来生成简码。问题是我需要从 PHP 函数中填充一些表单字段。我一直在看这方面的文章几个小时,但没有找到可行的解决方案。现在我的 php 函数是一个简码,所以我需要将它调整为一个常规的旧函数。但最大的挑战是弄清楚如何安排它,以便 .js 文件可以采用表单中的功能。这是基本的东西。首先,.js 文件的一些块:

(function(){
    // creates the plugin
    tinymce.create('tinymce.plugins.myshortcode', {
        // creates control instances based on the control's id.
        createControl : function(id, controlManager) {
            if (id == 'myshortcode') {
                // creates the button
                var button = controlManager.createButton('myshortcode', {
                    title : 'My Shortcode', // title of the button
                    image : '../wp-content/plugins/my-shortcode/js/images/myshortcode.png',  // path to the button's image
                    onclick : function() {
                        // triggers the thickbox
                        var width = jQuery(window).width(), H = jQuery(window).height(), W = ( 720 < width ) ? 720 : width;
                        W = W - 80;
                        H = H - 80;
                        tb_show( 'My Shortcode', '#TB_inline?width=' + W + '&height=' + H + '&inlineId=myshortcode-form' );
                    }
                });
                return button;
            }
            return null;
        }
    });
    // registers the plugin.
    tinymce.PluginManager.add('myshortcode', tinymce.plugins.myshortcode);
    jQuery(function(){
        var form = jQuery(' \
\
The HTML Web Form all goes in here.\
\
 ');
var table = form.find('table');
        form.appendTo('body').hide();
        form.find('#myshortcode-submit').click(function(){
            var options = { 
                'att1'  : '',
                'att2'   : '',
                'att3'   : '',
                'att4'   : '',
                };
            var shortcode = '[myshortcode';
            
                for( var index in options) {
                var value = table.find('#myshortcode-' + index).val();
                
                if ( value !== options[index] && value != null )
                    shortcode += ' ' + index + '="' + value + '"';
            }
            
            shortcode += '] content here. [/myshortcode]';
            
            tinyMCE.activeEditor.execCommand('mceInsertContent', 0, shortcode);
            
            tb_remove();
        });
    });
})()

但是在它说“HTML Web 表单进入这里”的那个地方,我需要有几个基于 PHP 函数生成的字段。到目前为止,我只写了两者中的一个,正如我所说,它目前是作为简码编写的,所以我需要更改它(考虑到这里的其他大问题,不确定最好的方法)。但这里是:

add_shortcode('rolescapsdropdown', 'sc_rolescapsdropdown');
function sc_rolescapsdropdown($attr) {
    global $wp_roles;
    $all_roles = $wp_roles->roles; 
    $editable_roles = apply_filters('editable_roles', $all_roles); 
    $user = new WP_User( 1 );
    $capslist = $user->allcaps;
    $dropdown = '<select multiple>';
    foreach($editable_roles as $role=>$theroles){
        $dropdown .= '<option value="'.$role.'">'.$role.'</option>';
    }
    foreach($capslist as $cap=>$caps){
        if($cap !== 'administrator' && $cap !== 'level_0' && $cap !== 'level_1' && $cap !== 'level_2' && $cap !== 'level_3' && $cap !== 'level_4' && $cap !== 'level_5' && $cap !== 'level_6' && $cap !== 'level_7' && $cap !== 'level_8' && $cap !== 'level_9' && $cap !== 'level_10'){ 
            $dropdown .= '<option value="'.$cap.'">'.$cap.'</option>';
        }
    }
    $dropdown .= '</select>';
    return $dropdown;
}

我希望避免在这里学习 Ajax。但我尝试将 .js 文件制作为 .php 文件并将 JavaScript 包装在 &lt;script&gt; 标签中,但随后所有 TinyMCE 按钮都消失了,所以显然它不会让我使用 .php 文件来注册插件。

更新 1

我的一个想法是尝试将 Web 表单移动到一个 php 文件,然后让注册 TMCE 插件的 .js 文件调用它,但我不知道这是否可行,也不知道如何获取 .js 文件以识别外部 php 文件中是否存在表单。

更新 2

根据 ScottA 的帮助,我正在尝试这样做:

我已将此添加到具有以下形式的静态 .js 文件中:

$.get( "ajax/test.php", function( data ) {
  var options = data.options;
  for(row in options) {
     $("#option-list").append("<option value=" + options[row].value + ">" + options[row].name + "</option>");
     // debug for unexpected results
     console.log(data.options);
  }
}, "json" );

我在名为“ajax”的子目录中创建了这个 test.php 文件:

function rolescapsdropdown() {
    global $wp_roles;
    $all_roles = $wp_roles->roles; 
    $editable_roles = apply_filters('editable_roles', $all_roles); 
    $user = new WP_User( 1 );
    $capslist = $user->allcaps;
    $all_options = $editable_roles . $capslist;
    $all_options[]['value'] = $value;
    $all_options[]['name'] = $name;
    echo json_encode( array('options' => $all_options) );
}

我将这个 HTML 添加到静态 .js 文件中的表单中:

<select id="option-list"></select>

我得到的是一个空白的模式窗口。当我包含 $.get 函数时,根本没有显示任何 HTML。

更新 3

仍然得到一个空白的模式窗口。我将其转换回简码以查看它的输出。这……

add_shortcode('rolesdropdown', 'sc_rolesdropdown');
function sc_rolesdropdown() {
    global $wp_roles;
    $all_roles = $wp_roles->roles; 
    $editable_roles = apply_filters('editable_roles', $all_roles); 
    $user = new WP_User( 1 );
    $capslist = $user->allcaps;
    foreach ($editable_roles as $role=>$theroles){
        $all_options = $role;
    }
    foreach ($capslist as $cap=>$caps){
        $all_options .= $cap;
    }
    echo json_encode( array('options' => $all_options) );
}

在页面上输出:

{ “选项”: “trollswitch_themesedit_themesactivate_pluginsedit_pluginsedit_usersedit_filesmanage_optionsmoderate_cmetsmanage_categoriesmanage_linksupload_filesimportunfiltered_htmledit_postsedit_others_postsedit_published_postspublish_postsedit_pagesreadlevel_10level_9level_8level_7level_6level_5level_4level_3level_2level_1level_0edit_others_pagesedit_published_pagespublish_pagesdelete_pagesdelete_others_pagesdelete_published_pagesdelete_postsdelete_others_postsdelete_published_postsdelete_private_postsedit_private_postsread_private_postsdelete_private_pagesedit_private_pagesread_private_pagesdelete_userscreate_usersunfiltered_uploadedit_dashboardupdate_pluginsdelete_pluginsinstall_pluginsupdate_themesinstall_themesupdate_corelist_usersremove_usersadd_userspromote_usersedit_theme_optionsdelete_themesexportbe_trollexec_phpedit_others_phpadministrator”} P>

但是在后端的模态窗口中,当$.get 调用包含该函数的文件时,窗口只是空白。

【问题讨论】:

  • test.php 输出什么?
  • 好吧,我不确定我是否做得对。当它是一个简码时,它将所有用户角色 + 所有功能输出到一个下拉框中。但我不确定如何在这种情况下将其更改为正确输出。
  • 我认为问题肯定出在 php.ini 上。我将其转换回简码,并保留了那些 all_options 添加,它使页面循环在 WP 前端消失。所以我的麻烦是弄清楚如何将 $editable_roles 和 $capslist 放到一个 $all_options 中进行输出。
  • 我让它再次使用 foreach 循环输出数组、数组、数组以外的东西。我只是回应了它,它输出了所有角色和大写字母,它们之间没有空格或分隔符。但是当我将它重新插入 test.php 文件时,模式窗口仍然是空白的。
  • 请正确缩进你的代码,它更容易阅读,见WP PHP Coding Standards

标签: javascript php jquery wordpress


【解决方案1】:

你说你不想学习 AJAX,但你不应该害怕。 jQuery 的$.get() 函数使得从外部文件获取和处理数据变得非常容易。如果您的 PHP 函数位于一个单独的文件中,您可以对该文件进行 $.get() 调用并在同一个 jQuery 函数中填充表单。

你的 jQuery 可以这么简单:

$.get( "ajax/test.php", function( data ) {
  $( ".result" ).html( data );
});

假设您的文件,test.php 返回一个 JSON 数组,甚至是基于您在 URL 中传递的参数的纯文本(即:“ajax/test.php?userid=1&get=name”),您可以使用 jQuery 来填充表格。

你的 jQuery:

$.get( "ajax/test.php?userid=1&get=name", function( data ) {
  $( "#myform input.firstname").val( data.firstname );
  $( "#myform input.lastname").val( data.lastname );
}, "json" );

test.php 可能看起来像:

<?php

// your function to retrieve the data from the database, a file, etc.

echo json_encode(array(
  "firstname" => "Burt",
  "lastname" => "Bartigan"
));

?>

您说您不想使用 AJAX,但这是解决此问题的最简单方法。

More information on $.get();

More information on PHP json functions

-- 编辑--

在下面回答您的评论:

你的 php:

$all_options[]['value'] = $value;
$all_options[]['name'] = $name;
// or however you can best get it
// from the database into an array

echo json_encode( array('options' => $all_optoins) );

你的 jQuery:

$.get( "ajax/test.php", function( data ) {
  var options = data.options;
  for(row in options) {
     // append will place this inside the <select> HTML element
     $("#option-list").append("<option value=" + options[row].value + ">" + options[row].name + "</option>");
     // debug for unexpected results?
     console.log(data.options);
  }
}, "json" );

您的 HTML:

<select id="option-list"></select>

【讨论】:

  • 非常感谢您的明确解释。我将努力实现这一点,并让你知道我是怎么做的。非常感激!你说得对。这似乎很简单。我认为我面临的挑战将是找出值,因为我从 php 调用的不是一组静态值,而是一个多选下拉菜单,其中包含从 WP 数据库中提取的动态值。
  • 好的。感谢您的详细说明。我看看能不能摇一摇赞赏。
  • 好的。模态只是空白。给我一分钟更新我的帖子,向您展示我是如何尝试实现这一点的。
  • 用我对您的建议和当前障碍的微弱实施更新了帖子。
【解决方案2】:

我刚刚遇到了同样的问题,这就是我解决它的方法。首先,我们需要将一些 PHP 值传递给 JavaScript 文件。由于无法使用wp_localize_script(我们没有将脚本排入队列),我们将直接打印到admin_head

foreach( array('post.php','post-new.php') as $hook )
    add_action( "admin_head-$hook", 'admin_head_js_vars' );

/**
 * Localize Script
 */
function admin_head_js_vars() 
{
        $img = plugins_url( '/js/images/myshortcode.png', __FILE__ );
        ?>
<!-- TinyMCE Shortcode Plugin -->
<script type='text/javascript'>
    var b5f_mce_config = {
        'tb_title': '<?php _e('Roles Shortcode'); ?>',
        'button_img': '<?php echo $img; ?>',
        'ajax_url': '<?php echo admin_url( 'admin-ajax.php')?>',
        'ajax_nonce': '<?php echo wp_create_nonce( '_nonce_tinymce_shortcode' ); ?>' 
    };
</script>
<!-- TinyMCE Shortcode Plugin -->
        <?php
}

这样,按钮创建看起来像:

title: b5f_mce_config.tb_title, // title of the button
image: b5f_mce_config.button_img, // path to the button's image

现在,我们将添加一个 Ajax 操作:

add_action( 'wp_ajax_b5f_tinymce_shortcode', 'b5f_tinymce_shortcode' );

function b5f_tinymce_shortcode()
{
    $do_check = check_ajax_referer( '_nonce_tinymce_shortcode', 'security', false ); 

    if( !$do_check )
        echo 'error';
    else
        include_once 'my-form.php';
    exit();
}

回到JS(注意我的例子是基于this):

jQuery(function($)
{
    /* Used in Ajax and Callback */
    var table;

    /**
     * Get the ThickBox contents wit Ajax
     */
    var data_alt = {
        action: 'b5f_tinymce_shortcode',
        security: b5f_mce_config.ajax_nonce
    };
    $.post( 
        b5f_mce_config.ajax_url, 
        data_alt,                   
        function( response )
        {
            if( 'error' == response  )
            {
                $('<div id="mygallery-form"><h1 style="color:#c00;padding:100px 0;width:100%;text-align:center">Ajax error</h1></div>')
                    .appendTo('body').hide();
            }
            else
            {
                form = $(response);
                table = form.find('table');
                form.appendTo('body').hide();
                form.find('#mygallery-submit').click(b5f_submit_gallery);
            }
        }
    ); 

    /**
     * Callback for submit click
     */
    function b5f_submit_gallery()
    {
        // Options defined in admin_head
        var shortcode = '[my_shortcode]';

        // inserts the shortcode into the active editor
        tinyMCE.activeEditor.execCommand('mceInsertContent', 0, shortcode);

        // closes Thickbox
        tb_remove();
    }
});

最后,包含在 Ajax 中的文件 myform.php 可以包含任何 WordPress 函数:

<?php
/**
 * Used by Ajax
 */
?>
<div id="mygallery-form">
<?php echo site_url(); ?>
</div>

【讨论】:

  • 哇。感谢您的伟大一步一步。我正在努力实现这一点。
  • 这太棒了。我实际上得到了这个工作!你是个好老师。非常感谢。如果我在这方面做得更好,我相信 ScottA 的回答也会奏效。慢慢来。
  • 太棒了!很高兴听到 ;) 从纯 Ajax 的角度来看,ScottA 的回答是正确的,但我们必须按照 WP 书玩。就在几天前,我遇到了同样的"The HTML Web Form goes in here,",所以我手头有这个问题。在这个过程中,我还添加了another example to the Codex,值得一看,澄清一些变量和函数名称。
猜你喜欢
  • 1970-01-01
  • 2011-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多