Call PHP file within a plugin to activate function

admin2025-06-04  4

So, the following might be absolutely against WordPress standards & best practices, but I'm in the process of learning.

Currently, I am calling a PHP file to generate a PDF through a third party.

The way I call the file is by visiting: .php?order_id=1553&key=d5df1b20-15a9-11e9-ad15-c704673daa98

The code for generate.php:

require_once("../../../wp-load.php");
nocache_headers();

$orderId = $_GET['order_id'];
$key = $_GET['key'];

$eventixOrderId = get_post_meta( $orderId, 'eventix_order_id', true );

if($eventixOrderId != $key){
    echo "These are not the tickets you're looking for.";
    exit;
}


$accessToken = get_option('eventix_access_token');  
$curl = curl_init();

curl_setopt_array($curl, array(
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_URL => '.0.0/order/'.$eventixOrderId.'/downloadlink',
    CURLOPT_USERAGENT => 'example',
    CURLOPT_HTTPHEADER => array(                                                                          
    'Content-Type: application/json',  
    'Authorization: ' . $accessToken) 
));

$ticketPdf = curl_exec($curl);
curl_close($curl);
update_post_meta( $orderId, 'eventix_pdf_ticket', $ticketPdf ); 
header("Location: $ticketPdf");
exit;

Now, for the most part, this actually works excellent. But in a few cases this script messes up, throws me to the 404 page of example and doesn't load the PDF. On the other hand, if I visit the link incognito; no problems.

My first thought was that it might be caused by header cache. I tried numerous ways to clear header cache, but didn't work.

So, the following might be absolutely against WordPress standards & best practices, but I'm in the process of learning.

Currently, I am calling a PHP file to generate a PDF through a third party.

The way I call the file is by visiting: https://example/wp-content/plugins/eventix-woocommerce/generate.php?order_id=1553&key=d5df1b20-15a9-11e9-ad15-c704673daa98

The code for generate.php:

require_once("../../../wp-load.php");
nocache_headers();

$orderId = $_GET['order_id'];
$key = $_GET['key'];

$eventixOrderId = get_post_meta( $orderId, 'eventix_order_id', true );

if($eventixOrderId != $key){
    echo "These are not the tickets you're looking for.";
    exit;
}


$accessToken = get_option('eventix_access_token');  
$curl = curl_init();

curl_setopt_array($curl, array(
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_URL => 'https://api.eventix.io/3.0.0/order/'.$eventixOrderId.'/downloadlink',
    CURLOPT_USERAGENT => 'example',
    CURLOPT_HTTPHEADER => array(                                                                          
    'Content-Type: application/json',  
    'Authorization: ' . $accessToken) 
));

$ticketPdf = curl_exec($curl);
curl_close($curl);
update_post_meta( $orderId, 'eventix_pdf_ticket', $ticketPdf ); 
header("Location: $ticketPdf");
exit;

Now, for the most part, this actually works excellent. But in a few cases this script messes up, throws me to the 404 page of example and doesn't load the PDF. On the other hand, if I visit the link incognito; no problems.

My first thought was that it might be caused by header cache. I tried numerous ways to clear header cache, but didn't work.

Share Improve this question asked Jan 11, 2019 at 14:52 KevsterKevster 331 silver badge9 bronze badges 3
  • Additional comment: I added header('Content-type: application/pdf'); to the code which seems to have solved the issue. Any comments in regards to the code, and if it's a best practice to do it this way.. much much appreciated. – Kevster Commented Jan 11, 2019 at 14:56
  • I was going to mention the Content-type header, but looks like you've done that. Other than that, your code looks OK. I would probably also add the Content-disposition header so you can provide a more consistent user experience. Use "inline" for opening PDF in the browser, or "attachment" for serving a "save as" dialog. i.e. ('Content-disposition: inline'; ). As for best practices, if it doesn't need to be portable, it's OK (although better methods exist). Just be aware that if you move it, the path to wp-load.php will be invalid. – butlerblog Commented Jan 11, 2019 at 15:18
  • Changed my mind on what I said about best practices. You really should go ahead and work it in so you don't have to directly hit the file and include wp-load.php. I put in an answer below that will get you started in that direction. It might need a little work. As-is, it is a drop-in code snippet for your theme's functions.php file. But add a proper plugin header and you can load it as a plugin. I'd go the plugin route since that would make it more portable (not theme dependent). – butlerblog Commented Jan 11, 2019 at 15:42
Add a comment  | 

1 Answer 1

Reset to default 1

Here's an approach that would be more portable (so you don't have to call wp-load.php directly, which is something you want to avoid) and also would allow you to revise the URL to not point to the /wp-content/plugins/ directory (also something you want to avoid):

add_action( 'init', 'my_pdf_generator' );
function my_pdf_generator() {

    // sniff out query args to see if this is a pdf request.
    // Note that you should probably add a unique query arg to make sure this is a ticket request.
    // Mabye something like "?eventix_order=true" or something just in case order_id and key exist in 
    // some other kind of instance.
    if ( isset( $_GET['order_id'] ) && isset( $_GET['key'] ) ) {

        nocache_headers();

        // Don't forget to sanitize 
        $orderId = $_GET['order_id'];
        $key = $_GET['key'];

        $eventixOrderId = get_post_meta( $orderId, 'eventix_order_id', true );

        if($eventixOrderId != $key){
            echo "These are not the tickets you're looking for.";
            exit;
        }

        $accessToken = get_option('eventix_access_token');  
        $curl = curl_init();

        curl_setopt_array($curl, array(
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_CUSTOMREQUEST => "GET",
            CURLOPT_URL => 'https://api.eventix.io/3.0.0/order/'.$eventixOrderId.'/downloadlink',
            CURLOPT_USERAGENT => 'example',
            CURLOPT_HTTPHEADER => array(                                                                          
            'Content-Type: application/json',  
            'Authorization: ' . $accessToken) 
        ));

        $ticketPdf = curl_exec($curl);
        curl_close($curl);
        update_post_meta( $orderId, 'eventix_pdf_ticket', $ticketPdf ); 

        header( 'Content-Description: File Transfer' );
        header( 'Content-Type: application/pdf' );
        header( 'Content-Disposition: inline' );
        header( 'Content-Transfer-Encoding: binary' );
        header( 'Cache-Control: must-revalidate' );
        header( 'Pragma: public' );
        header( "Location: $ticketPdf" );
        exit();

    }
}

Doing it this way would make your link as follows:

https://example/?order_id=1553&key=d5df1b20-15a9-11e9-ad15-c704673daa98

What it's doing is hooking to the 'init' action to check if this is a key request, and if so, it runs your process and exits at that end (so no additional WP output is sent).

That's cleaner than putting it in a custom file, directly calling that custom file, and needing to include wp-load.php.

To use it this way, you can either just drop it in your theme's functions.php file OR add a plugin file header to it and load it as a plugin. I'd recommend loading it as a plugin so that it is portable and not theme dependent, just in case you change things theme-wise down the road.

This would also be a starting point for other learning. This example just uses a raw query arg, but with additional research and work, you could probably learn to build it into a functional WooCommerce endpoint like:

https://example/eventix_order/1553/d5df1b20-15a9-11e9-ad15-c704673daa98/

Obviously, I can't test it as is, so you may need to tweak it to make it fully functional. I also noted in the code comments that I would probably work in an additional query argument that is unique just in case "order_id" and "key" may exist together as query args somewhere else (something like "eventix_order=true" or something). You could add that to the "if" condition.

I also added some additional headers that I think make it cleaner - you may need to experiment and/or revise as needed since as I mentioned, I can't test it exactly. But I have personally built download plugins and this comes from that work, so I think they should be correct for your purpose.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1749021441a315687.html

最新回复(0)