LilOrm.php

<?php

namespace Tlf;

/**
 * Minimal ORM implementation.
 *
 * @tagline (Alpha version) A minimalist ORM for mapping arrays of data to objects with magic getters & some convenience methods
 */
#[\AllowDynamicProperties]
class LilOrm {

    public $_cache = [];

    public function __construct($row){
        foreach ($row??[] as $k=>$v){
            $this->$k = $v;
        }
    }

    protected function get_ldb(): \Tlf\LilDb {
        return \ldb();
    }

    /**
     * Get an object with the given id
     *
     * @tip you could just use $id & $id_column as `select * from $name where $id_column = $id, though this is not the intended use
     *
     * @param $name the table name
     * @param $id the id of the row to retrieve
     * @param $id_column the id_column of the target row
     *
     * @return a LilOrm object or null if no rows found
     */
    public function one($name, $id, $id_column='id'){
        if (isset($this->_cache[$name.'-'.$id]))return $this->_cache[$name.'-'.$id];

        $row = $this->get_ldb()->select($name,[$id_column=>$id])[0]??null;

        if ($row==null)return null;

        $obj = $this->object($name, $row);
        $this->_cache[$name.'-'.$id] = $obj;
        return $obj;
    }

    /**
     * Get an array of objects that point to this item
     *
     * @param $that the table name to select from
     * @param $id_column the column to select against. Ex: `item_id` thus `this.id = that.item_id
     *
     * @return an array of rows
     */
    public function many($that, $id_column=null, $this_table=null){
        $id = $this->id;
        if (isset($this->_cache[$that.'-'.$id]))return $this->_cache[$that.'-'.$id];


        if ($id_column == null){
            $fqn = strtolower(get_class($this));
            $pos = strrpos($fqn, "\\");
            $table = substr($fqn,$pos+1);
            $id_column = $table.'_id';
        } 
        if ($this_table == null) $this_table = strtolower(get_class($this));


        $rows = $this->get_ldb()->select($that,[$id_column=>$id]);

        $this->_cache[$that.'-'.$id] = $rows ?? [];

        return $this->_cache[$that.'-'.$id];

        // return;
        // if ($rows==null)return [];
//
        // $objects = [];
        // foreach ($rows as $row){
            // $objects[] = $this->object($that,$row);
        // }
//
        // $this->_cache[$that.'-'.$id] = $objects;
//
        // return $objects;
        // $obj = $this->object($that, $row);
        // return $obj;
    }

    public function object($name, array $row){
        $class = get_class($this);
        $parts = explode("\\",$class);
        array_pop($parts);
        $namespace = implode("\\", $parts);
        $class = $namespace.'\\'.ucfirst($name);
        if (class_exists($class)){
            return new $class($row);
        }

        return (object)$row;
    }

    /**
     * Get an array of objects from rows
     * @param $rows an array of rows
     * @return array of objects
     */
    static public function from_rows(array $rows){
        $list = [];
        foreach ($rows as $r){
            $class = static::class;
            $list[] = new $class($r);
        }
        return $list;
    }

    public function __get($prop){
        if (substr($prop,0,1)=='_')return false;
        if (method_exists($this,$mthd='get'.ucfirst($prop))){
            return $this->$mthd();
        }

        return '';
        // trigger_error("Property '$prop' does not exist on ".get_class($this));
        throw new \Exception("Property '$prop' does not exist on ".get_class($this));
        return null;
    }
}