简体   繁体   中英

“Message: Undefined property: stdClass” codeigniter controller issue

First of all, I inherited the code for this site so I'm having trouble figuring out some of it. The problem is with our blog page creation. When I try to create a new blog page (using an admin site) I get an error before each element. It only appears on the create side and works fine on the edit side. I'm also still able to create the new post, it just has the notices. It was working as of about 24 hours ago and nothing was changed in any of the code.

The errors I'm getting are :   
> A PHP Error was encountered  
>Severity: Notice  
>Message: Undefined property: stdClass::$keywords    
>Filename: admin/form.php    
>Line Number: 94    

as well as:

> $title, Line Number: 28    
> $comments_enabled, line 122  
>$slug, line 33     
>$status, line 38     
>$body, line 53     
>$preview_hash, line 58

I've narrowed it down to the $extra array code that doesn't seem to be getting read (maybe?). Here is my create function:

public function create()
{

    // They are trying to put this live
    if ($this->input->post('status') == 'live')
    {
        role_or_die('blog', 'put_live');

        $hash = "";
    }
    else
    {
        $hash = $this->_preview_hash();
    }

    $post = new stdClass();

    // Get the blog stream.
    $this->load->driver('Streams');
    $stream = $this->streams->streams->get_stream('blog', 'blogs');
    $stream_fields = $this->streams_m->get_stream_fields($stream->id, $stream->stream_namespace);

    // Get the validation for our custom blog fields.
    $blog_validation = $this->streams->streams->validation_array($stream->stream_slug, $stream->stream_namespace, 'new');

    // Combine our validation rules.
    $rules = array_merge($this->validation_rules, $blog_validation);

    // Set our validation rules
    $this->form_validation->set_rules($rules);

    if ($this->input->post('created_on'))
    {
        $created_on = strtotime(sprintf('%s %s:%s', $this->input->post('created_on'), $this->input->post('created_on_hour'), $this->input->post('created_on_minute')));
    }
    else
    {
        $created_on = now();
    }

    if ($this->form_validation->run())
    {
        // Insert a new blog entry.
        // These are the values that we don't pass through streams processing.
        $extra = array(
            'title'            => $this->input->post('title'),
            'slug'             => $this->input->post('slug'),
            'category_id'      => $this->input->post('category_id'),
            'keywords'         => Keywords::process($this->input->post('keywords')),
            'body'             => $this->input->post('body'),
            'status'           => $this->input->post('status'),
            'created_on'       => $created_on,
            'created'          => date('Y-m-d H:i:s', $created_on),
            'comments_enabled' => $this->input->post('comments_enabled'),
            'author_id'        => $this->current_user->id,
            'type'             => $this->input->post('type'),
            'parsed'           => ($this->input->post('type') == 'markdown') ? parse_markdown($this->input->post('body')) : '',
            'preview_hash'     => $hash
        );  

        if ($id = $this->streams->entries->insert_entry($_POST, 'blog', 'blogs', array('created'), $extra))
        {
            $this->pyrocache->delete_all('blog_m');
            $this->session->set_flashdata('success', sprintf($this->lang->line('blog:post_add_success'), $this->input->post('title')));

            // Blog article has been updated, may not be anything to do with publishing though
            Events::trigger('post_created', $id);

            // They are trying to put this live
            if ($this->input->post('status') == 'live')
            {
                // Fire an event, we're posting a new blog!
                Events::trigger('post_published', $id);
            }
        }
        else
        {
            $this->session->set_flashdata('error', lang('blog:post_add_error'));
        }

        // Redirect back to the form or main page
        ($this->input->post('btnAction') == 'save_exit') ? redirect('admin/blog') : redirect('admin/blog/edit/'.$id);
    }
    else
    {
        // Go through all the known fields and get the post values
        $post = new stdClass;
        /* 
        ---------Gives array to string error without the if statement-------

        foreach ($this->validation_rules as $key => $field)
        {
            $post->$field['field'] = set_value($field['field']);
        }*/

        foreach ($this->validation_rules as $key => $field)
    {
        if (isset($_POST[$field['field']]))
        {
            $post->$field['field'] = set_value($field['field']);
        }
    } 

        $post->created_on = $created_on;

        // if it's a fresh new article lets show them the advanced editor
        $post->type or $post->type = 'wysiwyg-advanced';
    }

    // Set Values
    $values = $this->fields->set_values($stream_fields, null, 'new');

    // Run stream field events
    $this->fields->run_field_events($stream_fields, array(), $values);

    $this->template
        ->title($this->module_details['name'], lang('blog:create_title'))
        ->append_metadata($this->load->view('fragments/wysiwyg', array(), true))
        ->append_js('jquery/jquery.tagsinput.js')
        ->append_js('module::blog_form.js')
        ->append_js('module::blog_category_form.js')
        ->append_css('jquery/jquery.tagsinput.css')
        ->set('stream_fields', $this->streams->fields->get_stream_fields($stream->stream_slug, $stream->stream_namespace, $values))
        ->set('post', $post)
        ->build('admin/form');
}

The $extra array doesn't seem to be getting read. These errors also came about at the same time as an array to string error. I was hoping the fix for that would fix both but so far no good. The errors are coming from two sources as well. I was thinking it might be the if statement not being read? Or maybe it has something to do with the $validation_rules at the beginning of the file?

This bit of code is the first one to fail (for $type ) and the only one through the actual controller.php file and the rest (keywords, title, slug, etc) fail under the form.php file.

$post->type or $post->type = 'wysiwyg-advanced';

Any advice or help is appreciated. I'm still fairly new to PHP and CodeIgniter but it looks like it'll be to much work to overhaul the website.

Thank you.

Edit: I've added my edit function below, maybe someone else can see why it works but not my create function.

    public function edit($id = 0)
{
    $id or redirect('admin/blog');

    $post = $this->blog_m->get($id);

    // They are trying to put this live
    if ($post->status != 'live' and $this->input->post('status') == 'live')
    {
        role_or_die('blog', 'put_live');
    }

    // If we have keywords before the update, we'll want to remove them from keywords_applied
    $old_keywords_hash = (trim($post->keywords) != '') ? $post->keywords : null;

    $post->keywords = Keywords::get_string($post->keywords);

    // If we have a useful date, use it
    if ($this->input->post('created_on'))
    {
        $created_on = strtotime(sprintf('%s %s:%s', $this->input->post('created_on'), $this->input->post('created_on_hour'), $this->input->post('created_on_minute')));
    }
    else
    {
        $created_on = $post->created_on;
    }

    // Load up streams
    $this->load->driver('Streams');
    $stream = $this->streams->streams->get_stream('blog', 'blogs');
    $stream_fields = $this->streams_m->get_stream_fields($stream->id, $stream->stream_namespace);

    // Get the validation for our custom blog fields.
    $blog_validation = $this->streams->streams->validation_array($stream->stream_slug, $stream->stream_namespace, 'new');

    $blog_validation = array_merge($this->validation_rules, array(
        'title' => array(
            'field' => 'title',
            'label' => 'lang:global:title',
            'rules' => 'trim|htmlspecialchars|required|max_length[100]|callback__check_title['.$id.']'
        ),
        'slug' => array(
            'field' => 'slug',
            'label' => 'lang:global:slug',
            'rules' => 'trim|required|alpha_dot_dash|max_length[100]|callback__check_slug['.$id.']'
        ),
    ));

    // Merge and set our validation rules
    $this->form_validation->set_rules(array_merge($this->validation_rules, $blog_validation));

    $hash = $this->input->post('preview_hash');

    if ($this->input->post('status') == 'draft' and $this->input->post('preview_hash') == '')
    {
        $hash = $this->_preview_hash();
    }
    //it is going to be published we don't need the hash
    elseif ($this->input->post('status') == 'live')
    {
        $hash = '';
    }

    if ($this->form_validation->run())
    {
        $author_id = empty($post->display_name) ? $this->current_user->id : $post->author_id;

        $extra = array(
            'title'            => $this->input->post('title'),
            'slug'             => $this->input->post('slug'),
            'category_id'      => $this->input->post('category_id'),
            'keywords'         => Keywords::process($this->input->post('keywords'), $old_keywords_hash),
            'body'             => $this->input->post('body'),
            'status'           => $this->input->post('status'),
            'created_on'       => $created_on,
            'updated_on'       => $created_on,
            'created'          => date('Y-m-d H:i:s', $created_on),
            'updated'          => date('Y-m-d H:i:s', $created_on),
            'comments_enabled' => $this->input->post('comments_enabled'),
            'author_id'        => $author_id,
            'type'             => $this->input->post('type'),
            'parsed'           => ($this->input->post('type') == 'markdown') ? parse_markdown($this->input->post('body')) : '',
            'preview_hash'     => $hash,
        );

        if ($this->streams->entries->update_entry($id, $_POST, 'blog', 'blogs', array('updated'), $extra))
        {
            $this->session->set_flashdata(array('success' => sprintf(lang('blog:edit_success'), $this->input->post('title'))));

            // Blog article has been updated, may not be anything to do with publishing though
            Events::trigger('post_updated', $id);

            // They are trying to put this live
            if ($post->status != 'live' and $this->input->post('status') == 'live')
            {
                // Fire an event, we're posting a new blog!
                Events::trigger('post_published', $id);
            }
        }
        else
        {
            $this->session->set_flashdata('error', lang('blog:edit_error'));
        }

        // Redirect back to the form or main page
        ($this->input->post('btnAction') == 'save_exit') ? redirect('admin/blog') : redirect('admin/blog/edit/'.$id);
    }

    // Go through all the known fields and get the post values
    foreach ($this->validation_rules as $key => $field)
    {
        if (isset($_POST[$field['field']]))
        {
            $post->$field['field'] = set_value($field['field']);
        }
    }

    $post->created_on = $created_on;

    // Set Values
    $values = $this->fields->set_values($stream_fields, $post, 'edit');

    // Run stream field events
    $this->fields->run_field_events($stream_fields, array(), $values);

    $this->template
        ->title($this->module_details['name'], sprintf(lang('blog:edit_title'), $post->title))
        ->append_metadata($this->load->view('fragments/wysiwyg', array(), true))
        ->append_js('jquery/jquery.tagsinput.js')
        ->append_js('module::blog_form.js')
        ->set('stream_fields', $this->streams->fields->get_stream_fields($stream->stream_slug, $stream->stream_namespace, $values, $post->id))
        ->append_css('jquery/jquery.tagsinput.css')
        ->set('post', $post)
        ->build('admin/form');
}

Edit2: I've added the whole form.php that is sending most of the errors.

    <section class="title">
<?php if ($this->method == 'create'): ?>
    <h4><?php echo lang('blog:create_title') ?></h4>
<?php else: ?>
    <h4><?php echo sprintf(lang('blog:edit_title'), $post->title) ?></h4>
<?php endif ?>
</section>

<section class="item">
<div class="content">

<?php echo form_open_multipart() ?>

<div class="tabs">

    <ul class="tab-menu">
        <li><a href="#blog-content-tab"><span><?php echo lang('blog:content_label') ?></span></a></li>
        <?php if ($stream_fields): ?><li><a href="#blog-custom-fields"><span><?php echo lang('global:custom_fields') ?></span></a></li><?php endif; ?>
        <li><a href="#blog-options-tab"><span><?php echo lang('blog:options_label') ?></span></a></li>
    </ul>

    <!-- Content tab -->
    <div class="form_inputs" id="blog-content-tab">
        <fieldset>
            <ul>
                <li>
                    <label for="title"><?php echo lang('global:title') ?> <span>*</span></label>
                    <div class="input"><?php echo form_input('title', htmlspecialchars_decode($post->title), 'maxlength="100" id="title"') ?></div>
                </li>

                <li>
                    <label for="slug"><?php echo lang('global:slug') ?> <span>*</span></label>
                    <div class="input"><?php echo form_input('slug', $post->slug, 'maxlength="100" class="width-20"') ?></div>
                </li>

                <li>
                    <label for="status"><?php echo lang('blog:status_label') ?></label>
                    <div class="input"><?php echo form_dropdown('status', array('draft' => lang('blog:draft_label'), 'live' => lang('blog:live_label')), $post->status) ?></div>
                </li>

                <li class="editor">
                    <label for="body"><?php echo lang('blog:content_label') ?> <span>*</span></label><br>
                    <div class="input small-side">
                        <?php echo form_dropdown('type', array(
                            'html' => 'html',
                            'markdown' => 'markdown',
                            'wysiwyg-simple' => 'wysiwyg-simple',
                            'wysiwyg-advanced' => 'wysiwyg-advanced',
                        ), $post->type) ?>
                    </div>

                    <div class="edit-content">
                        <?php echo form_textarea(array('id' => 'body', 'name' => 'body', 'value' => $post->body, 'rows' => 30, 'class' => $post->type)) ?>
                    </div>
                </li>

            </ul>
        <?php echo form_hidden('preview_hash', $post->preview_hash)?>
        </fieldset>
    </div>

    <?php if ($stream_fields): ?>

    <div class="form_inputs" id="blog-custom-fields">
        <fieldset>
            <ul>

                <?php foreach ($stream_fields as $field) echo $this->load->view('admin/partials/streams/form_single_display', array('field' => $field), true) ?>

            </ul>
        </fieldset>
    </div>

    <?php endif; ?>

    <!-- Options tab -->
    <div class="form_inputs" id="blog-options-tab">
        <fieldset>
            <ul>

                <li>
                    <label for="category_id"><?php echo lang('blog:category_label') ?></label>
                    <div class="input">
                    <?php echo form_dropdown('category_id', array(lang('blog:no_category_select_label')) + $categories, @$post->category_id) ?>
                        [ <?php echo anchor('admin/blog/categories/create', lang('blog:new_category_label'), 'target="_blank"') ?> ]
                    </div>
                </li>

                <?php if ( !module_enabled('keywords')): ?>
                    <?php echo form_hidden('keywords'); ?>
                <?php else: ?>
                    <li>
                        <label for="keywords"><?php echo lang('global:keywords') ?></label>
                        <div class="input"><?php echo form_input('keywords', $post->keywords, 'id="keywords"') ?></div>
                    </li>
                <?php endif; ?>

                <li class="date-meta">
                    <label><?php echo lang('blog:date_label') ?></label>

                    <div class="input datetime_input">
                        <?php echo form_input('created_on', date('Y-m-d', $post->created_on), 'maxlength="10" id="datepicker" class="text width-20"') ?> &nbsp;
                        <?php echo form_dropdown('created_on_hour', $hours, date('H', $post->created_on)) ?> :
                        <?php echo form_dropdown('created_on_minute', $minutes, date('i', ltrim($post->created_on, '0'))) ?>
                    </div>
                </li>

                <?php if ( ! module_enabled('comments')): ?>
                    <?php echo form_hidden('comments_enabled', 'no'); ?>
                <?php else: ?>
                    <li>
                        <label for="comments_enabled"><?php echo lang('blog:comments_enabled_label');?></label>
                        <div class="input">
                            <?php echo form_dropdown('comments_enabled', array(
                                'no' => lang('global:no'),
                                '1 day' => lang('global:duration:1-day'),
                                '1 week' => lang('global:duration:1-week'),
                                '2 weeks' => lang('global:duration:2-weeks'),
                                '1 month' => lang('global:duration:1-month'),
                                '3 months' => lang('global:duration:3-months'),
                                'always' => lang('global:duration:always'),
                            ), $post->comments_enabled ? $post->comments_enabled : '3 months') ?>
                        </div>
                    </li>
                <?php endif; ?>
            </ul>
        </fieldset>
    </div>

</div>

<input type="hidden" name="row_edit_id" value="<?php if ($this->method != 'create'): echo $post->id; endif; ?>" />

<div class="buttons">
    <?php $this->load->view('admin/partials/buttons', array('buttons' => array('save', 'save_exit', 'cancel'))) ?>
</div>

<?php echo form_close() ?>

</div>
</section>

Replace

$post->type or $post->type = 'wysiwyg-advanced';

with

$post->type = 'wysiwyg-advanced';

hope it works..

In your code:

$post->type or $post->type = 'wysiwyg-advanced';

PHP will first evaluate $post->type , and if that returns false, the second part of your or statement will be run. Since PHP has to evaluate it, it will attempt to access the property, and since it's not set, the interpreter throws a notice and assumes it's false.

The proper way to do this is:

if (!isset($post->type)) {
    $post->type = 'wysiwyg-advanced';
}
// Or in PHP 7:
$post->type = $post->type ?? 'nobody';

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM