Ad

October CMS - Custom Plugin: JSON Recursion Detected

I want to develop a plugin that extends RainLab.Blog in October CMS.

My plugin's database appears in the SQL database and backend form that takes the new input while editing a blog post renders just fine, but the issue appears when trying to save the changes to SQL, wheree they appear NULL:

"Method OleMol\BlogExtensions\Models\Extension::__toString() must not throw an exception, caught Illuminate\Database\Eloquent\JsonEncodingException: Error encoding model [OleMol\BlogExtensions\Models\Extension] with ID [2] to JSON: Recursion detected" on line 0 of C:\xampp\htdocs\vendor\laravel\framework\src\Illuminate\Support\Str.php

This seems to be a Laravel problem and it's the first time I'm using October in a professional project. Initially, I tried to use a table with a bunch of columns, but for troubleshooting, I have stripped it down to one custom column until I can find an answer.

I am trying to follow along to this video tutorial, but extending RainLab.Blog instead of RainLab.User.

cd C:\xampp\htdocs
php artisan create:plugin OleMol.BlogExtensions

plugins\olemol\blogextensions\Plugin.php

<?php namespace OleMol\BlogExtensions;
                                                                                                   
use Backend;
use System\Classes\PluginBase;
use RainLab\Blog\Models\Post as PostModel;
use RainLab\Blog\Controllers\Posts as PostsController;
use OleMol\BlogExtensions\Models\Extension as ExtensionModel;
                                                                                                   
/**
 * BlogExtensions Plugin Information File
 */
class Plugin extends PluginBase    {
    /* RainLab.Blog is a dependency for this plugin. */
    public $require = [ 'RainLab.Blog' ];

    public function boot()    {
        PostModel::extend(function($model)  {
            $model -> hasOne[ 'blogextension' ] = [ 'OleMol\BlogExtensions\Models\Extension' ];
        });
        
        PostsController::extendFormFields(function($form, $model, $context) {
            //Only extend this controller if the model is a post.
            if (!$model instanceof PostModel)   { return; }
            
            //Don't create an extension to a model that does not exist.
            if (!$model -> exists)  { return; }
            
            //Ensure that the post always has an extension before adding fields.
            ExtensionModel::getFromPost($model);
            
            $form -> addTabFields([ 'blogextension[business_name ]' => [ 'label' => 'Business Name', 'tab' => 'Business' ]);
        });
    }                                                                                                
}                                                                                                    }

plugins\olemol\blogextensions\updates\version.yaml

1.0.1:
- First version of BlogExtensions
1.0.2:
- create_business_table.php

plugins\olemol\blogextensions\updates\create_business_table.php

<?php namespace OleMol\BlogExtensions\Updates;
                                                                                                   
use Schema;
use October\Rain\Database\Schema\Blueprint;
use October\Rain\Database\Updates\Migration;
                                                                                                 
class CreateBusinessTable extends Migration    {
    public function up()    {
        Schema::create('olemol_blogextensions_business', function (Blueprint $table) {
            $table -> engine = 'InnoDB';
            $table -> increments('id');
            $table -> integer('post_id') -> unsigned() -> index();
            
            /*
             * This always ends up as NULL!
             * (Or default value in case it's not nullable).
             */
            $table -> string('business_name') -> nullable();
            
            $table -> timestamps();
        });
    }
                                                                                                
    public function down()    {
        Schema::dropIfExists('olemol_blogextensions_busiit's not nullable).
             */
            $table -> string('business_name') -> nullable();
            
            $table -> timestamps();
        });
    }
                                                                                                
    public function down()    {
        Schema::dropIfExists('olemol_blogextensions_business');
    }
}

plugins\olemol\blogextensions\models\Extension.php

<?php namespace OleMol\BlogExtensions\Models;
                                                                                                   
use Model;
                                                                                                   
/**
 * Extension Model
 */
class Extension extends Model    {
    use \October\Rain\Database\Traits\Validation;
    
    /**
     * @var string table associated with the model
     */
    public $table = 'olemol_blogextensions_business';
    
    /**
     * @var array dates attributes that should be mutated to dates
     */
    protected $dates = [ 'created_at', 'updated_at' ];

    public $belongsTo = [ 'post' => [ 'RainLab\Blog\Models\Post' ]];

    /* Helper-function to ensure that post always has an extension. */
    public static function getFromPost($post)   {
        if ($post -> extension) { return $post -> extension; }
        
        $extension = new static;
        $extension -> post = $post;
        $extension -> save();

        $post -> extension = $extension;
        
        return $extension;
    }
}

I have included the code I think is necessary. The files still contain auto-generated empty blocks which are omitted.

php artisan plugin:refresh OleMol.BlogExtensions
php artisan project:sync
php artisan october:migrate

I'm on a tight schedule and I feel like I'm lost at this point. Please reach out if more information is needed. I would appreciate any help coming my way.

Ad

Answer

I think in your code Extension.php-> getFromPost method need some corrections

// plugins\olemol\blogextensions\models\Extension.php: getFromPost method: 
$post->extension = $extension;

It should be: blogextension instead of only extension

$post->blogextension = $extension;
//     ^ HERE

You need to specify your hasOne relation name there

if any doubt please comment

Ad
source: stackoverflow.com
Ad