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="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 );
    $this_file = $filearray['url'];
    
    if ( $this_file != '' ) { 
         $html .= '<div><p>Current 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="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 );
    $this_file = $filearray['url'];
    
    if ( $this_file != '' ) { 
         $html .= '<div><p>Current 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' );

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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' );


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x