Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save non-searchable unstructured data/settings in DB #158

Open
dhoomm opened this issue Nov 24, 2016 · 5 comments
Open

Save non-searchable unstructured data/settings in DB #158

dhoomm opened this issue Nov 24, 2016 · 5 comments

Comments

@dhoomm
Copy link
Contributor

dhoomm commented Nov 24, 2016

Many times we need to save user editable options in DB. We would have to create a table to save a single record. Instead, this is what i use at the moment.

DB:

CREATE TABLE options (
	name VARCHAR(20) NOT NULL,
	value TEXT NOT NULL,
	PRIMARY KEY (name)
)

Create a base class.

class OptionRecord extends \yii\base\Model
{
    public static function optionName()
    {
        return false;
    }
    public static function tableName()
    {
        return 'options';
    }
    public static function find()
    {
        $model = new static();
        $value = (new Query())->select(['value'])->from(static::tableName())->where(['name' => static::optionName()])->scalar();
        if ($value) {
            $values = unserialize($value);
            foreach ($model->getAttributes() as $key => $value) {
                if (isset($values[$key])) {
                    $model->$key = $values[$key];
                }
            }
        }
        return $model;
    }
    public function save($runValidation = true, $attributeNames = null)
    {
        if ($runValidation && !$this->validate($attributeNames)) {
            return false;
        }
        $sql = 'INSERT INTO `' . static::tableName() . '` (`name`, `value`) VALUES (:name,:value) ON DUPLICATE KEY UPDATE `value`=VALUES(`value`);';
        return \Yii::$app->getDb()->createCommand($sql, [':name' => static::optionName(), ':value' => serialize($this->getAttributes())])->execute();
    }
}

Useage:
Create a new Class, e.g.

class SmsSetup extends OptionRecord
{
    public $api;
    public $sender;
    public function rules()
    {
        return [
          [['api', 'sender'], 'required'],
          [['api', 'sender'], 'string', 'max' => 10]
        ];
    }
    public static function optionName()
    {
        return 'sms_setup';
    }
}

Now this can be used in controller as:

    public function actionUpdate()
    {
      $model = SmsSetup::find();
       if ($model->load(Yii::$app->request->post()) && $model->save()) 
       {
         //...
       }
    }
    public function actionDoSomething()
    {
        $settings = SmsSetup::find();
        \Yii::$app->smsService->send($settings->api, $settings->sender, 'SMS Content');
      //...
    }

Of course this won't work for wordpress type requirement where multiple options need to be loaded on each request, enable autoload, etc.
Expecting suggestions...

@samdark
Copy link
Owner

samdark commented Nov 24, 2016

Recently almost all databases started to support JSON including searching. Should be better than serialize, unserialize. Another way is normalized version of it called EAV.

@dhoomm
Copy link
Contributor Author

dhoomm commented Nov 26, 2016

Thanks for the info about JSON support even in relational databases. My vendor has old version of MySql DB, will use this for now...

@thiagotalma
Copy link

@samdark, this is certainly a good recipe.
A lot of system runs on old databases but they are still in full development.

Therefore, you should accept the colleague's suggestion with praise.
Be careful not to prune the suggestions based solely on your personal opinion. The world is much more complex than that 😉

@samdark
Copy link
Owner

samdark commented Nov 26, 2016

I'm not declining it. Just mentioned that there could be better ways doing that.

@samdark
Copy link
Owner

samdark commented Nov 28, 2016

https://github.com/yii2tech/ar-dynattribute

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants