Illegal string offset in PHP function

I'm creating a metabox to upload PDF files.

I have the following warning notice for this line of code: $this_file = $filearray['url'];

Warning: Illegal string offset ‘url’ in...

The complete function code:

function wp_custom_attachment() {
    wp_nonce_field( plugin_basename(__FILE__), 'wp_custom_attachment_nonce' );
    $html = 'p class=descriptionUpload your PDF here./p';
    $html .= 'input id=wp_custom_attachment name=wp_custom_attachment size=25 type=file value= /';

    $filearray = get_post_meta( get_the_ID(), 'wp_custom_attachment', true );
    $this_file = $filearray['url'];
    
    if ( $this_file != '' ) { 
         $html .= 'divpCurrent file: ' . $this_file . '/p/div'; 
    }
    echo $html; 
}

Thanks in advance for the help.

EDIT

function add_custom_meta_boxes() {
    add_meta_box( 
        'wp_custom_attachment',
        'PDF File',
        'wp_custom_attachment',
        'workshop',
        'normal'
    ) ;
}
add_action( 'add_meta_boxes', 'add_custom_meta_boxes' );

function wp_custom_attachment() {
    wp_nonce_field( plugin_basename(__FILE__), 'wp_custom_attachment_nonce' );
    $html = 'p class=descriptionUpload your PDF here./p';
    $html .= 'input id=wp_custom_attachment name=wp_custom_attachment size=25 type=file value= /';

    $filearray = get_post_meta( get_the_ID(), 'wp_custom_attachment', true );
    $this_file = $filearray['url'];
    
    if ( $this_file != '' ) { 
         $html .= 'divpCurrent file: ' . $this_file . '/p/div'; 
    }
    echo $html; 
}

function save_custom_meta_data( $id ) {
    if ( ! empty( $_FILES['wp_custom_attachment']['name'] ) ) {
        $supported_types = array( 'application/pdf' );
        $arr_file_type = wp_check_filetype( basename( $_FILES['wp_custom_attachment']['name'] ) );
        $uploaded_type = $arr_file_type['type'];

        if ( in_array( $uploaded_type, $supported_types ) ) {
            $upload = wp_upload_bits($_FILES['wp_custom_attachment']['name'], null, file_get_contents($_FILES['wp_custom_attachment']['tmp_name']));
            if ( isset( $upload['error'] )  $upload['error'] != 0 ) {
                wp_die( 'There was an error uploading your file. The error is: ' . $upload['error'] );
            } else {
                add_post_meta( $id, 'wp_custom_attachment', $upload );
                update_post_meta( $id, 'wp_custom_attachment', $upload );
            }
        }
        else {
            wp_die( The file type that you've uploaded is not a PDF. );
        }
    }
}
add_action( 'save_post', 'save_custom_meta_data' );

function update_edit_form() {
    echo ' enctype=multipart/form-data';
}
add_action( 'post_edit_form_tag', 'update_edit_form' );

Topic warnings functions php metabox Wordpress

Category Web


You need to be validating a couple of parts about $filearray before you use it.

There are some good suggestions in the comments, I think a couple of robust examples would serve you well too:

Using empty()

function wp_custom_attachment() {
    wp_nonce_field( plugin_basename(__FILE__), 'wp_custom_attachment_nonce' );
    $html = '<p class="description">Upload your PDF here.</p>';
    $html .= '<input id="wp_custom_attachment" name="wp_custom_attachment" size="25" type="file" value="" />';

    $filearray = get_post_meta( get_the_ID(), 'wp_custom_attachment', true );
    
    if ( ! empty( $filearray['url'] ) ) { 
         $html .= '<div><p>Current file: ' . $filearray['url'] . '</p></div>'; 
    }
    echo $html; 
}

empty() is great because it implicitly works like isset, whereby if the value isn't set it just returns false. Another benefit of empty is that you can test for structures like array keys without worrying about whether the object is an array at all:

php > var_dump( empty( $a['foo'] ) ); // $a is undefined
php shell code:1:
bool(true)
php > var_dump( empty( $a['foo']['bar'][32] ) ); // $a is undefined
php shell code:1:
bool(true)
php > var_dump( empty( $o->foo ) ); // $o is undefined
php shell code:1:
bool(true)

Above, you can see that PHP isn't complaining about the lack of $a or $o being undefined, it just tells us "yes that is empty" and carries on.

Using isset and is_array

function wp_custom_attachment() {
    wp_nonce_field( plugin_basename(__FILE__), 'wp_custom_attachment_nonce' );
    $html = '<p class="description">Upload your PDF here.</p>';
    $html .= '<input id="wp_custom_attachment" name="wp_custom_attachment" size="25" type="file" value="" />';

    $filearray = get_post_meta( get_the_ID(), 'wp_custom_attachment', true );

    if ( is_array( $filearray) && isset( $filearray['url'] ) ) { 
         $html .= '<div><p>Current file: ' . $filearray['url'] . '</p></div>'; 
    }
    echo $html; 
}

This approach does two parts of validation - first, we ensure that $filearray is indeed an array, and then we validate that the url key exists. This is more verbose than empty, and has the added benefit of a type check. It should be noted that empty( $filearray['url'] ) will only work if $filearray is an array because the syntax dictates it, however, this check is not explicit.

A note on ternary and null-coalesce

Some people suggested using a ternary:

$this_file = ! empty( $filearray['url'] ) ? $filearray['url'] : '';

This is fine, though it's a bit hard to grok at first. You could also use null-coalescing if your PHP version supports it:

$this_file = $filearray['url'] ?? '';

While these work fine, again, I'd avoid them until you're more comfortable in PHP. It stinks to come back to old code a few months later to try and remember what the heck you did when your code looks like

$foo = $bar ? ( $baz ?? false ) : ( $done ?: 'Waiting' );

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.