How can I use and array instead of DB table?

I have and static array that could fullfill my Resultset and my model instance.

Is there a way to use it instead of my database? Of course it is a read-only model. I want the benefits of has-many object relation.

$array = [
    [1,'name1','color1'],
    [2,'name2','color2'],
    [3,'name3','color3'],
    [4,'name4','color4'],
]

class Color extends \Phalcon\Mvc\Models {
    public $id;
    public $name;
    public $color

    public function initialize() {
        // Convert $array and use it as db
    }
}

What you mean as DB ? You wanna do find and fine records in this array ? Cant you just insert this data into db ?

Yes, I can use from DB (as I am using now).

But my colors are pre-defined (50 records, not changeable) and when I query mainModel::find() it will consume one more query just to get the color associated model.

What you mean as DB ? You wanna do find and fine records in this array ? Cant you just insert this data into db ?

Sounds like you actually want this in your controller. You could declare a variable in your controller class and set it equal to the array you want on initialize. Then it is always available.



44.7k
edited Dec '15

You could also store that in an array and then have that loaded into a Config object from your main services file. Its static data but its probably best to access it through the DI system. So get it with $this->getDI()->getColorConfig().

edited Dec '15

I figured another solution (and it's working). If you can say pros and cons I would be glad!

    class ColorSet extends \GC\Models\ModelBase implements \GC\Interfaces\IModel
    {

      public static $color_sets = [
            [ 0 ], // There is no id 0. This key will be unset later
            [ 1, 'Red 1', '#FFEBEE', '#FF8A80', 1, 0 ],
            [ 2, 'Red 2', '#FFEBEE', '#FF5252', 1, 0 ],
            [ 3, 'Red 3', '#FFEBEE', '#FF1744', 1, 0 ],
            [ 4, 'Red 4', '#FFEBEE', '#D50000', 1, 0 ],
            [ 5, 'Pink 1', '#FCE4EC', '#FF80AB', 1, 0 ],
            [ 6, 'Pink 2', '#FCE4EC', '#FF4081', 1, 0 ],
            [ 7, 'Pink 3', '#FCE4EC', '#F50057', 1, 0 ],
            ...
        ];


    public static function findFirst($params = null)
    {
        // Of course $params will not work
        // This is how I get id value, in findFirstById or findFirst
        $id = $params['bind']['APR0'];
        // Define a default value if id is not found
        if (!isset(self::$color_sets[$id])) {
            $id = 47;
        }
        $color = new ColorSet();
        $color->setId(self::$color_sets[$id][0]);
        $color->setName(self::$color_sets[$id][1]);
        $color->setFrontColor(self::$color_sets[$id][2]);
        $color->setBackColor(self::$color_sets[$id][3]);
        $color->setSystem(self::$color_sets[$id][4]);
        $color->setDeleted(self::$color_sets[$id][5]);

        return $color;
    }

    public static function find($params = null)
    {
        // Of course $params will not work
        $return = [ ];
        foreach (self::$color_sets as $color_set) {
            $color = new ColorSet();
            $color->setId($color_set[0]);
            $color->setName($color_set[1]);
            $color->setFrontColor($color_set[2]);
            $color->setBackColor($color_set[3]);
            $color->setSystem($color_set[4]);
            $color->setDeleted($color_set[5]);
            $return[] = $color;
        }
        // Removing first key from array (id = 0 cannot exist)
        unset($return[0]);

        return $return;

    }

Sounds interesting, but does not improve performance as expected (that is my main problem).

Sqlite: https://docs.phalconphp.com/en/latest/api/Phalcon%5Db%5Adapter%5Pdo%5Sqlite.html

If I load data from config, it will be a config object without model properties.

You could also store that in an array and then have that loaded into a Config object from your main services file. Its static data but its probably best to access it through the DI system. So get it with $this->getDI()->getColorConfig().



44.7k

Why does it need to be a model if you are aren't going to be calling update, insert or delete on the records? Additionally it won't be receiving events either since it is static data.

If you are going to overload the static methods then perhaps you could combine the two approaches and store the constant data in a file and load it through the config in the DI like my example. That way you have a more efficient model system and without the inflexibility of having so much arbitrary data hard coded into your model. So you could do both.



44.7k

Just move this data to be loaded into a config object through the DI:

      // Icky static data stored in the model should be moved to a config.
      public static $color_sets = [
            [ 0 ], // There is no id 0. This key will be unset later
            [ 1, 'Red 1', '#FFEBEE', '#FF8A80', 1, 0 ],
            [ 2, 'Red 2', '#FFEBEE', '#FF5252', 1, 0 ],
            [ 3, 'Red 3', '#FFEBEE', '#FF1744', 1, 0 ],
            [ 4, 'Red 4', '#FFEBEE', '#D50000', 1, 0 ],
            [ 5, 'Pink 1', '#FCE4EC', '#FF80AB', 1, 0 ],
            [ 6, 'Pink 2', '#FCE4EC', '#FF4081', 1, 0 ],
            [ 7, 'Pink 3', '#FCE4EC', '#F50057', 1, 0 ],
            ...
        ];
edited Dec '15

Interesting! And when shoud I load? initialize() method? onContruct() ? Or when I declare/load services and components?

I have just inserted in DI and worked perfectly:

    // In services declaration
    ColorSet::$color_sets = new \Phalcon\Config\Adapter\Php(APPLICATION_PATH . '/app/Config/colorSet.php');

    // colorSet.php in config folder
    return [
        [ 0 ],
        [ 1, 'Red 1', '#FFEBEE', '#FF8A80', 1, 0 ],
        [ 2, 'Red 2', '#FFEBEE', '#FF5252', 1, 0 ],
        [ 3, 'Red 3', '#FFEBEE', '#FF1744', 1, 0 ],
        ...

php

Just move this data to be loaded into a config object through the DI:

```php

 // Icky static data stored in the model should be moved to a config.
 public static $color_sets = [
     [ 0 ], // There is no id 0. This key will be unset later
     [ 1, 'Red 1', '#FFEBEE', '#FF8A80', 1, 0 ],
     [ 2, 'Red 2', '#FFEBEE', '#FF5252', 1, 0 ],
     [ 3, 'Red 3', '#FFEBEE', '#FF1744', 1, 0 ],
     [ 4, 'Red 4', '#FFEBEE', '#D50000', 1, 0 ],
     [ 5, 'Pink 1', '#FCE4EC', '#FF80AB', 1, 0 ],
     [ 6, 'Pink 2', '#FCE4EC', '#FF4081', 1, 0 ],
     [ 7, 'Pink 3', '#FCE4EC', '#F50057', 1, 0 ],
     ...
 ];

```

The main reason is that I can call $model->getColorSet() and take benefits from loading related "model".

Why does it need to be a model if you are aren't going to be calling update, insert or delete on the records? Additionally it won't be receiving events either since it is static data.



44.7k

No don't set a class constant from outside of the class (I didn't know you could do that).

$di->setShared('colorConfig', function() {
    // Wrap this data in a Phalcon config object or just use load PHP array file, JSON or YAML files.
    $colorConfig = require(__DIR__ . "/config.php");
    return $colorConfig;
});

The main reason is that I can call $model->getColorSet() and take benefits from loading related "model".

Just do something like:

    public function getColorSet()
    {
        return $this->getDI()->getColorConfig()->colorSet;
    }

That way your user code doesn't need to know how stuff is configured and all of the other benefits. By setting the class constant from within the service definition you are unnecessarily tightly binding it together.

Interesting! And when shoud I load? initialize() method? onContruct() ? Or when I declare/load services and components?

If you do it the way that I said then it will just happen automatically and you don't need to set it up. Your static overloaded find methods will access the DI (use DI::getDefault()) and will return models and they will initialize themselves. You might want to manually trigger 'afterFetch' if you want the model to dress up the data differently than the way it is stored. You could also dress it up in Colorset::find.