• I am converting sql statements to $wpdb methods and getting the same error in different contexts, Fatal error on Call to a member function show_errors() on null in /home4/hsysgrpc/public_html/wp-content/themes/twentytwelve-child/DownloadCommitteesFile. If I comment out show_errors it fails at get_results, so I am missing something basic. I have a page that displays data that attempts to download the data into a csv file. The code for the download file is:

    <?php
    //DownloadCommitteesFile.php 3/17/2022
    
    global $wpdb;
    $wpdb->show_errors(true);
    include 'myFuncs.php' ;
    $link = connect() ;
    if($link === false){    die("ERROR: Could not connect. " . mysqli_connect_error());} 
    header('Content-Type: text/csv');
    $FileName = 'Content-Disposition: attachment; filename="'. 'Committees.csv"';
    header($FileName);
    	
    $SQL =	"SELECT FirstName, LastName, AAUWDatabase, DiversityInclusion, InternationalRelations, Membership, 
    	ProgramPlanning, PublicPolicy, Website, Zoom FROM AAUW_Members WHERE (((AAUWDatabase)=1)) OR (((DiversityInclusion)=1)) OR (((InternationalRelations)=1))
    	 OR (((Membership)=1)) OR (((ProgramPlanning)=1)) OR (((PublicPolicy)=1)) OR (((Website)=1)) OR (((Zoom)=1)) ORDER BY Lastname ";
    	
    	$result = $wpdb->get_results($SQL, ARRAY_A
    );
    
    $output = fopen('php://output', 'w');
    
    // Download file header record
    
    fputcsv($output, array(
    	'FirstName',
    	'LastName',
    	'AAUWDatabase',
    	'DiversityInclusion',
    	'InternationalRelations',
    	'Membership',
    	'ProgramPlanning',
    	'PublicPolicy',
    	'Website',
    	'Zoom',
    	));
    
    foreach($result as $row){
    	
    	fputcsv($output, array(
    		$row['FirstName'],
    		$row['LastName'],
    		$row['AAUWDatabase'],
    		$row['DiversityInclusion'],
    		$row['InternationalRelations'],
    		$row['Membership'],
    		$row['ProgramPlanning'],
    		$row['PublicPolicy'],
    		$row['Website'],
    		$row['Zoom'],
    	));	
    		
    } //end foreach
    
    fclose($output);						  		 	
    ?>
    
    • This topic was modified 2 years, 7 months ago by Jan Dembowski. Reason: Formatting

    The page I need help with: [log in to see the link]

Viewing 14 replies - 1 through 14 (of 14 total)
  • Dion

    (@diondesigns)

    If this is a standalone script, $wpdb will not be available because WordPress is not loaded. You might want to insert the following line immediately after global $wpdb;:

    if (!defined('ABSPATH') || empty($wpdb)) {die('WordPress not loaded.');}
    

    Your script will then abort if WordPress is not loaded.

    Thread Starter hsysgrp

    (@hsysgrp)

    Thank you, You are right, I got ‘WordPress not loaded’. So how do I load it, I have tried
    include ‘../wp-load.php’; and got error include(): Failed opening ‘../wp-load.php’ for inclusion (include_path=’.:/opt/cpanel/ea-php73/root/usr/share/pear’) in /home4/hsysgrpc/public_html/wp-content/themes/twentytwelve-child/DownloadCommitteesFile.php on line 3

    Also, I am working in a WordPress website; the code for a page on the website contains
    global $wpdb; displays the results of $wpdb->get_results(…
    the results are displayed,
    a form is displayed:

    <form method = “post” action = “/wp-content/themes/twentytwelve-child/DownloadCommitteesFile.php”>
    <input type = “submit” name = “export” value = “CSV Export” />
    </form>
    DownloadCommitteesFile.php is called from the /home4/hsysgrpc/public_html/wp-content/themes/twentytwelve-child/folder (from the code listed above)
    so what point did we lose $wpdb, and why?

    Dion

    (@diondesigns)

    I will preface that what I’m about to suggest is bad coding, but I’m providing it in the hope that it gives you some ideas to find an alternate solution.

    Based on the directory structure you provided, I believe the following will load WordPress:

    include('../../../wp-load.php');

    The wp-load.php file is in the WordPress root directory, so you must provide a path from your theme directory to the WP root directory.

    Since you are loading the script from a form submission, you can use server variables such as DOCUMENT_ROOT and REQUEST_URI to generate the full path to the WP root directory. That can be used to load wp-load.php. Hopefully this gives you a start…

    Moderator bcworkz

    (@bcworkz)

    Hi hsysgrp,
    The reason including wp-load.php is considered bad coding is because it will not be 100% portable to any WP installation because site owners could possibly alter relative paths to different resources. Hence relative references in general are a bad idea in the WP environment. If you’re doing this for your own site only and will never use it elsewhere, then do as you wish.

    There are actually only a few ways to properly initialize the WP environment in order to run custom code. HTTPS requests must go through either admin-ajax.php or admin-post.php. Or go to a page with a custom template or the REST API. Requests directly to your own custom .php file is strongly discouraged for the above stated reason. Dion’s suggestion of passing the full path back and forth will work as well, but IMO it’s not an optimal solution when other methods are available.

    Dion

    (@diondesigns)

    PHP scripts that load WordPress via wp-load.php are fine; I personally do this in a number of custom plugins. Howver, I always make sure the custom script is properly hardened, and to avoid portability issues, I always place the scripts in a custom-created directory directly beneath the WP root directory (same level as /wp-includes). Placing the scripts in a theme/plugin directory is asking for trouble since those directories can be moved via constants.

    One must keep in mind that requests to /wp-admin scripts to handle simple form submissions and AJAX requests (meaning, no theme/plugin dependencies) is overkill and will waste (an oftentimes large amount of) server resources. In this specific case, I would use the WP_INSTALLING constant to block wp-load.php from loading the theme and plugins, use $wpdb->__get('dbh') to obtain the DB handle, and then continue to use the mysqli code that was already written. Any opportunity I have to bypass the archaic and incredibly-inefficient code in wp-db.php, I will take it. ??

    Thread Starter hsysgrp

    (@hsysgrp)

    I attempted to provide a path so $wpdb would load, and got the
    “/home4/hsysgrpc/public_html/wp-content/themes/twentytwelve-child/DownloadCommitteesFile.phpWordPress not loaded” error.
    I added the $path statement but was not successful, can you give me more guidance?
    <?php
    //DownloadCommitteesFile.php 3/17/2022
    $path = $_SERVER[‘DOCUMENT_ROOT’] . “/wp-content/themes/twentytwelve-child/DownloadCommitteesFile.php”;
    echo $path;
    global $wpdb;
    if (!defined(‘ABSPATH’) || empty($wpdb)) {die(‘WordPress not loaded.’);}
    $wpdb->show_errors(true);
    include ‘myFuncs.php’ ;
    $link = connect() ;
    if($link === false){ die(“ERROR: Could not connect. ” . mysqli_connect_error());}
    header(‘Content-Type: text/csv’);
    $FileName = ‘Content-Disposition: attachment; filename=”‘. ‘Committees.csv”‘;
    header($FileName);

    $SQL = “SELECT FirstName, LastName, AAUWDatabase, DiversityInclusion, InternationalRelations, Membership,
    ProgramPlanning, PublicPolicy, Website, Zoom FROM AAUW_Members WHERE (((AAUWDatabase)=1)) OR (((DiversityInclusion)=1)) OR (((InternationalRelations)=1))
    OR (((Membership)=1)) OR (((ProgramPlanning)=1)) OR (((PublicPolicy)=1)) OR (((Website)=1)) OR (((Zoom)=1)) ORDER BY Lastname “;

    $result = $wpdb->get_results($SQL, ARRAY_A
    );

    Dion

    (@diondesigns)

    You need line at the start of your script such as:

    require($_SERVER['DOCUMENT_ROOT'] . '/wp-load.php');

    If WordPress is located at $_SERVER['DOCUMENT_ROOT'], the above line will load WordPress.

    FYI, please consider placing your code in CODE blocks when posting it here. Not only will the formatting be retained, the “texturize” junk done by WordPress will be blocked and your code will not be edited.

    Thread Starter hsysgrp

    (@hsysgrp)

    Oh, we are getting close! WordPress loaded, output for the csv file is listed, but: error message:
    Warning: Cannot modify header information – headers already sent by (output started at /home4/hsysgrpc/public_html/wp-content/themes/twentytwelve-child/myFuncs.php:13) in /home4/hsysgrpc/public_html/wp-content/themes/twentytwelve-child/DownloadCommitteesFile.php on line 12

    Warning: Cannot modify header information – headers already sent by (output started at /home4/hsysgrpc/public_html/wp-content/themes/twentytwelve-child/myFuncs.php:13) in /home4/hsysgrpc/public_html/wp-content/themes/twentytwelve-child/DownloadCommitteesFile.php on line 14
    FirstName,LastName,AAUWDatabase,DiversityInclusion,InternationalRelations,Membership,ProgramPlanning,PublicPolicy,Website,Zoom Lula,Allen,0,1,0,0,0,0,0,0 etc.

    myFuncs.php contains the connect function.
    I commented out the header ($FileName) and got the same error. I think it is the order in which the statements are added?, but I am ignorant here.

    <?php
    //DownloadCommitteesFile.php 3/19/2022
    require($_SERVER['DOCUMENT_ROOT'] . '/wp-load.php');
    //$path = $_SERVER['DOCUMENT_ROOT'] . "/wp-content/themes/twentytwelve-child/DownloadCommitteesFile.php";
    //echo $path;
    global $wpdb;
    if (!defined('ABSPATH') || empty($wpdb)) {die('WordPress not loaded.');}
    $wpdb->show_errors(true);
    include 'myFuncs.php' ;
    $link = connect() ;
    if($link === false){    die("ERROR: Could not connect. " . mysqli_connect_error());} 
    header('Content-Type: text/csv');
    $FileName = 'Content-Disposition: attachment; filename="'. 'Committees.csv"';
    //header($FileName);
    	
    Moderator bcworkz

    (@bcworkz)

    You can only call PHP’s header() before any output has been sent out. If you’re unable to set a header prior to output, you’d need to use JS to set the header.

    Thread Starter hsysgrp

    (@hsysgrp)

    Thank you. OK. I moved the header statement to above the “require($_SERVER[‘DOCUMENT_ROOT’] . ‘/wp-load.php’);” statement and ran it. I got a downloaded file named “DownloadCommitteesFile.php”. I manually changed the name to “CommitteesFile.csv” and saved it, and voila! got my desired output. I don’t know JS. How can I set my desired filename programmatically?

    <?php
    //DownloadCommitteesFile.php 3/19/2022
    header('Content-Type: text/csv');
    require($_SERVER['DOCUMENT_ROOT'] . '/wp-load.php');
    //$path = $_SERVER['DOCUMENT_ROOT'] . "/wp-content/themes/twentytwelve-child/DownloadCommitteesFile.php";
    //echo $path;
    global $wpdb;
    if (!defined('ABSPATH') || empty($wpdb)) {die('WordPress not loaded.');}
    $wpdb->show_errors(true);
    include 'myFuncs.php' ;
    $link = connect() ;
    if($link === false){    die("ERROR: Could not connect. " . mysqli_connect_error());} 
    
    $FileName = 'Content-Disposition: attachment; filename="'. 'Committees.csv"';
    	
    $SQL =	"SELECT FirstName, LastName, AAUWDatabase, DiversityInclusion, InternationalRelations, Membership, 
    	ProgramPlanning, PublicPolicy, Website, Zoom FROM AAUW_Members WHERE (((AAUWDatabase)=1)) OR (((DiversityInclusion)=1)) OR (((InternationalRelations)=1))
    	 OR (((Membership)=1)) OR (((ProgramPlanning)=1)) OR (((PublicPolicy)=1)) OR (((Website)=1)) OR (((Zoom)=1)) ORDER BY Lastname ";
    	
    	$result = $wpdb->get_results($SQL, ARRAY_A
    );
    
    $output = fopen('php://output', 'w');
    
    // Download file header record
    
    fputcsv($output, array(
    	'FirstName',
    	'LastName',
    	'AAUWDatabase',
    	'DiversityInclusion',
    	'InternationalRelations',
    	'Membership',
    	'ProgramPlanning',
    	'PublicPolicy',
    	'Website',
    	'Zoom',
    	));
    
    foreach($result as $row){
    	
    	fputcsv($output, array(
    		$row['FirstName'],
    		$row['LastName'],
    		$row['AAUWDatabase'],
    		$row['DiversityInclusion'],
    		$row['InternationalRelations'],
    		$row['Membership'],
    		$row['ProgramPlanning'],
    		$row['PublicPolicy'],
    		$row['Website'],
    		$row['Zoom'],
    	));	
    		
    } //end foreach
    
    fclose($output);						  		 	
    ?>
    
    Dion

    (@diondesigns)

    Your code already defines the correct header information to set a download filename. I suggest you use a header() statement to send it. ??

    The header() statements should be immediately before the $output = fopen() line.

    Thread Starter hsysgrp

    (@hsysgrp)

    placing the header statement before the $output = fopen() line elicits an error saying headers are already sent.

    Dion

    (@diondesigns)

    If so, then something in your code is outputting text when it shouldn’t be. I’ll leave that for you to debug…in the meantime, I guess you can put your header statements at the top of the script.

    Thread Starter hsysgrp

    (@hsysgrp)

    Success! thank you all. Below is the complete file, if that will help anybody else. To review, this file is called by a form to download data displayed on a webpage. The difficulty was that $wpdb was not loading, hence the call to wp-load.php. Additionally, the header information had to be placed above the require line or the output file was named “DownloadCommitteesFile.php” for reasons totally obscure to me.

    <?php
    //DownloadCommitteesFile.php 3/21/2022
    //Called by form on custom-page_Download_Committees-wpdb.php
    header('Content-Type: text/csv');
    
    $filename = 'Committees.csv';
    
    header("Content-Disposition: attachment; filename= $filename " );
    
    $output = fopen('php://output', 'w');
    require($_SERVER['DOCUMENT_ROOT'] . '/wp-load.php');
    
    global $wpdb;
    if (!defined('ABSPATH') || empty($wpdb)) {die('WordPress not loaded.');}
    $wpdb->show_errors(true);
    include 'myFuncs.php' ;
    $link = connect() ;
    if($link === false){    die("ERROR: Could not connect. " . mysqli_connect_error());} 
    	
    $SQL =	"SELECT FirstName, LastName, AAUWDatabase, DiversityInclusion, InternationalRelations, Membership, 
    	ProgramPlanning, PublicPolicy, Website, Zoom FROM AAUW_Members WHERE (((AAUWDatabase)=1)) OR (((DiversityInclusion)=1)) OR (((InternationalRelations)=1))
    	 OR (((Membership)=1)) OR (((ProgramPlanning)=1)) OR (((PublicPolicy)=1)) OR (((Website)=1)) OR (((Zoom)=1)) ORDER BY Lastname ";
    	
    	$result = $wpdb->get_results($SQL, ARRAY_A
    );
    
    // Download file header record
    
    fputcsv($output, array(
    	'FirstName',
    	'LastName',
    	'AAUWDatabase',
    	'DiversityInclusion',
    	'InternationalRelations',
    	'Membership',
    	'ProgramPlanning',
    	'PublicPolicy',
    	'Website',
    	'Zoom',
    	));
    
    foreach($result as $row){
    	
    	fputcsv($output, array(
    		$row['FirstName'],
    		$row['LastName'],
    		$row['AAUWDatabase'],
    		$row['DiversityInclusion'],
    		$row['InternationalRelations'],
    		$row['Membership'],
    		$row['ProgramPlanning'],
    		$row['PublicPolicy'],
    		$row['Website'],
    		$row['Zoom'],
    	));	
    		
    } //end foreach
    
    fclose($output);
    
    ?>
    • This reply was modified 2 years, 7 months ago by Jan Dembowski. Reason: Formatting
Viewing 14 replies - 1 through 14 (of 14 total)
  • The topic ‘$wpdb’ is closed to new replies.