admin管理员组

文章数量:1391968

I've stumbled on the "403 Forbidden error" for which many explanations/solutions can be found in many places, most of them on Stack. However, I struggle for quite a while for solving this error in my situation. I asked that same question on the Wordpress forum but got no answer..

I have a Wordpress plugin, let's call it "foobar", that processes a shortcode.

My plugin's php file, foobar.php, builds and returns at some point the Javascript code:

$myvariable = '
$.ajax({
 url: "'.plugin_dir_url( __FILE__ ) .'myPHPFunction.php",
 '.type: "post",
 success: function(response) { console.log("return from myPHPFunction.php:"+response); },
 error: function(xhr,status,error) { console.log("status="+status+",xhr="+xhr+",errth="+error);}
 });';

return $myvariable;

The reason why I want to call php from the browser with an ajax call is that I need that its content is run asynchronously when the page is displayed.

The myPHPFunction.php file is in the same directory as the plugin's.

myPHPFunction.php is very powerful, it makes : ;-)

<?php
    echo "abcd";
?>

When I open a WordPress page (mytestpage) containing the shortcode, WordPress builds and runs the Javascript in an HTML page /, and I get in the browser console :

status=error,xhr=<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /wp-content/plugins/foobar/myPHPFunction.php
on this server.</p>
</body></html>
,errth=Forbidden

Curiously, this is what happens locally on my development server (I use MAMP 5.7). On the production site at my provider's, it works. But I need having it running in development…

If I move myPHPFunction.php to the root of my website, and update my code accordingly:

 url: ".php",

it works.. : abcd is returned in the console…

So very probably it comes from the fact that the HTML page generated by WordPress and the PHP file are not in the same domain. As myPHPFunction.php must be delivered with my plugin, there is no way to put it outside the plugin's directory.

Hence I must solve the cross-domain call.

I think that solving this on the server by configuration (.htaccess) is not safe. In the case of a plugin, no guarantee that my plugin users won't experience that error in their deployment context. And many users can't/don't know how to operate on their apache server, especially if it's managed by a provider (and possibly mutualized). Besides it's probably not straightforward : I tried myself .html without success.

The other solution seems to try having headers returned by the server :

That didn't work either.. I tried adding those lines in either of my php files, without success...

I now run out of ideas…

Any help appreciated…

Thanks a lot

Edit:

Thanks to Sally CJ I found a solution with wp_ajax hooks as its seems to be the official way to proceed. However that doesn't answer precisely the question as there is no explanation why this code works on a production WP website and not in development (at least in my context). Anyway I won't go further on the unofficial way, and I'll keep goin with ajax hooks. As writing such plugin is however not straightforward in spite of WP guidelines, you'll find hereafter a complete usable test plugin for a shortcode. NB : Here the Javascript is not in a separate file, thus not requesting use of wp_localize_script.

Hope it can help...

<?php
/*
Plugin Name:    FOOBAR
 Calls PHP function my_ajax_foobar_handler() on the server from front-end Ajax call in a page generated by WP from a shortcode.
 Just put [foobar] in a WP test page after activating FOOBAR plugin. The console should display abcd
*/

if(!class_exists('FOOBAR'))
{
    class FOOBAR
    {
        /**
         * Construct the plugin object
         */
        public function __construct()
        {
            add_action('init', array($this, 'add_hooks'));
        }

        public function myplugin_ajaxurl() {
            echo '<script type="text/javascript">
            var ajax_url = "' . admin_url('admin-ajax.php') . '";
            </script>';
        }

        /**
         * Add hooks
         */
        public function add_hooks()
        {
            register_activation_hook(__FILE__, array($this, 'activate'));
            register_deactivation_hook(__FILE__, array($this, 'deactivate'));
            add_shortcode ('foobar', array($this, 'process_foobar' ));
            add_action('wp_head', array($this, 'myplugin_ajaxurl'));
            add_action('wp_ajax_foobar', array($this, 'my_ajax_foobar_handler'));
            add_action('wp_ajax_nopriv_foobar', array($this, 'my_ajax_foobar_handler'));
        }

        /**
         * my_ajax_foobar_handler
         */
        public function my_ajax_foobar_handler()
        {
            echo "abcd";
            wp_die();
        }

        /**
         * Activate the plugin
         */
        public function activate()
        {
            if ( shortcode_exists( 'foobar' ) )
                die('Plugin NOT activated: shortcode foobar already used by another plugin.');
        }

        /**
         * Deactivate the plugin
         */
        public function deactivate()
        {
            remove_shortcode ('foobar');
        }

        /**
         * This is THE function that processes the shortcode
        */
        public function process_foobar ($atts, $content = "")
        {
    ?>
             <script type="text/javascript">
            jQuery(document).ready(function($){
            $.ajax({
                   url: ajax_url,
                   data: { action : "foobar" },
                   type: "post",
                   success: function(response) { console.log("return from my_ajax_foobar_handler:"+response); },
                   error: function(xhr,status,error) { console.log("status="+status+",xhr="+xhr.responseText+",errth="+error);}
                   });
                });
            </script>
<?php
        }
    } // END class FOOBAR
} // END if(!class_exists('FOOBAR'))

if(class_exists('FOOBAR'))
{
    new FOOBAR();
}

本文标签: How to avoid the 403 Forbidden error in a WP Plugin with Ajax and PHP