├── .gitignore ├── LICENSE ├── README.md ├── app ├── controller │ └── UsersController.php ├── model │ ├── App.php │ ├── Users.php │ └── contracts │ │ └── Users.php └── view │ └── Users │ ├── get.php │ └── index.php ├── composer.json ├── composer.lock ├── config.sample.ini ├── constants.php ├── core ├── controller │ └── Controller.php ├── helper │ └── Helper.php └── model │ ├── Database.php │ └── Model.php └── index.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | config.ini 3 | .DS_Store 4 | .idea 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Junior Oliveira 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Installing via composer and using as a lib 2 | 3 | ```shell 4 | composer require arojunior/php-orm-pdo 5 | ``` 6 | 7 | ### create a file to overwrite the database config 8 | 9 | ```php 10 | use SimpleORM\core\model\Model; 11 | 12 | class AppModel extends Model 13 | { 14 | public $db_config = [ 15 | 'db_host' => '192.168.1.1', 16 | 'db_name' => 'test', 17 | 'db_user' => 'root', 18 | 'db_pass' => '' 19 | ]; 20 | } 21 | 22 | ``` 23 | 24 | #### And then you can extend this class in your classes 25 | 26 | ```php 27 | use YourNamespace\AppModel; 28 | 29 | class Example extends AppModel 30 | { 31 | public $table = 't_user'; 32 | public $pk = 'user_id'; 33 | 34 | public function getAll() 35 | { 36 | return $this->findAll(); 37 | } 38 | } 39 | ``` 40 | 41 | ### CRUD 42 | 43 | ```php 44 | 45 | namespace SimpleORM\app\model; 46 | 47 | use SimpleORM\core\model\Model; 48 | 49 | class Users extends Model 50 | { 51 | /* 52 | * * Basic configuration 53 | * These arguments are optionals 54 | * protected $table = 'users'; //just if the class name a table name are different 55 | * protected $pk = 'id'; //just if the primary key name is not id 56 | */ 57 | } 58 | 59 | ``` 60 | 61 | ### Creating a new user (without check) 62 | 63 | ```php 64 | $this->Users->create([ 65 | 'name' => 'Junior Oliveira', 66 | 'email' => 'arojunior@gmail.com' 67 | ]); 68 | ``` 69 | 70 | **Let the ORM choose if it will be created or updated. The ORM will execute the find method before to decide if will create or update data** 71 | 72 | ### Saving data 73 | 74 | ```php 75 | $this->Users->save([ 76 | 'id' => 1, 77 | 'name' => 'Junior Oliveira' 78 | ]); 79 | ``` 80 | 81 | ### Retrieving the id 82 | 83 | ```php 84 | $this->Users->lastSavedId(); 85 | ``` 86 | 87 | ### Updating a user with id = 1 88 | 89 | ```php 90 | $this->Users->update([ 91 | 'id' => 1, 92 | 'email' => 'contato@arojunior.com' 93 | ]); 94 | ``` 95 | 96 | ### Delete 97 | 98 | ```php 99 | $this->Users->delete(['id' => 1]); 100 | ``` 101 | 102 | ## Read 103 | 104 | ```php 105 | $this->Users->findAll(); // fetchAll 106 | 107 | $this->Users->findOne(['email' => 'arojunior@gmail.com']); 108 | 109 | $this->Users->findById($id); 110 | ``` 111 | 112 | ### Checking 113 | 114 | ```php 115 | $this->Users->exists($id); 116 | ``` 117 | 118 | in case of true, you cat get the data with: 119 | 120 | ```php 121 | $this->Users->fetch(); 122 | ``` 123 | 124 | ### Functionalities if used as Framework 125 | 126 | - CRUD functions 127 | - Auto load Model classes in Controllers 128 | - To use the automatic functions you should use the filename and structure conventions 129 | - Just follow the example on /controller/UsersController.php 130 | - All controllers in /app/controllers folder 131 | - All models in /app/models folder 132 | 133 | ### Convetions 134 | 135 | - All controllers in /app/controller path 136 | - All models in /app/model path 137 | - All views in /app/view path 138 | - Filenames and classes must has the same name 139 | -------------------------------------------------------------------------------- /app/controller/UsersController.php: -------------------------------------------------------------------------------- 1 | 'teste']; 13 | } 14 | 15 | public function get() 16 | { 17 | $result = $this->Users->findById('arojunior@gmail.com'); 18 | 19 | return ['list' => $this->Helper->toJson($result)]; 20 | } 21 | 22 | public function add() 23 | { 24 | $data = ['email' => 'arojunior@gmail.com']; 25 | $this->Users->store($data); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /app/model/App.php: -------------------------------------------------------------------------------- 1 | save($data); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/model/contracts/Users.php: -------------------------------------------------------------------------------- 1 | =5.6.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "381040a2c4e0bdde41b75eb5022341f0", 8 | "content-hash": "5fa41390419ea72e7c7c5c3e80523d8c", 9 | "packages": [], 10 | "packages-dev": [], 11 | "aliases": [], 12 | "minimum-stability": "stable", 13 | "stability-flags": [], 14 | "prefer-stable": false, 15 | "prefer-lowest": false, 16 | "platform": { 17 | "php": ">=5.6.0" 18 | }, 19 | "platform-dev": [] 20 | } 21 | -------------------------------------------------------------------------------- /config.sample.ini: -------------------------------------------------------------------------------- 1 | db_host = 'localhost' 2 | db_user = 'root' 3 | db_pass = '' 4 | db_name = 'site' 5 | -------------------------------------------------------------------------------- /constants.php: -------------------------------------------------------------------------------- 1 | Helper = new Helper(); 16 | 17 | $this->class = self::setClass(); 18 | self::loadModels(); 19 | self::loadHelpers(); 20 | } 21 | 22 | private function setClass() 23 | { 24 | $className = (new \ReflectionClass($this))->getShortName(); 25 | 26 | return str_replace('Controller', '', $className); 27 | } 28 | 29 | /* 30 | * create instances of models with different names when set $this->use = [] 31 | */ 32 | private function loadModels() 33 | { 34 | $this->use = ( ! isset($this->use)) ? [$this->class] : $this->use; 35 | 36 | if ($this->use) { 37 | foreach ($this->use as $model) { 38 | self::load('model', $model); 39 | } 40 | } 41 | } 42 | 43 | private function loadHelpers() 44 | { 45 | if (isset($this->helpers)) { 46 | foreach ($this->helpers as $helper) { 47 | self::load('helper', $helper); 48 | } 49 | } 50 | } 51 | 52 | private function load($path, $class) 53 | { 54 | $load_class = 'SimpleORM\app\\' . $path . '\\' . $class; 55 | $this->{$class} = new $load_class(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /core/helper/Helper.php: -------------------------------------------------------------------------------- 1 | 'UFT-8') { 11 | array_walk_recursive($dados, function(&$value, $key) { 12 | if (is_string($value)) { 13 | $value = utf8_encode(self::clean($value)); 14 | } 15 | }); 16 | } 17 | 18 | return json_encode($dados); 19 | } 20 | 21 | public function clean($string) 22 | { 23 | $table = array( 24 | '?' => 'S', '?' => 's', '?' => 'Dj', '?' => 'dj', '?' => 'Z', 25 | '?' => 'z', '?' => 'C', '?' => 'c', '?' => 'C', '?' => 'c', 26 | 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 27 | 'Å' => 'A', 'Æ' => 'A', 'Ç' => 'C', 'È' => 'E', 'É' => 'E', 28 | 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 29 | 'Ï' => 'I', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 30 | 'Õ' => 'O', 'Ö' => 'O', 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 31 | 'Û' => 'U', 'Ü' => 'U', 'Ý' => 'Y', 'Þ' => 'B', 'ß' => 'Ss', 32 | 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 33 | 'å' => 'a', 'æ' => 'a', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 34 | 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 35 | 'ï' => 'i', 'ð' => 'o', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 36 | 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ø' => 'o', 'ù' => 'u', 37 | 'ú' => 'u', 'û' => 'u', 'ý' => 'y', 'ý' => 'y', 'þ' => 'b', 38 | 'ÿ' => 'y', '?' => 'R', '?' => 'r', 'ü' => 'u', 'º' => '', 39 | 'ª' => '', 40 | ); 41 | 42 | $string = strtr($string, $table); 43 | 44 | return $string; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/model/Database.php: -------------------------------------------------------------------------------- 1 | db_config)) { 16 | $this->db_config = parse_ini_file('config.ini'); 17 | } 18 | 19 | $this->conn = new \PDO("mysql:host={$this->db_config['db_host']};" . 20 | "dbname={$this->db_config['db_name']}", 21 | $this->db_config['db_user'], 22 | $this->db_config['db_pass'] 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /core/model/Model.php: -------------------------------------------------------------------------------- 1 | table)) { 29 | $modelName = (new \ReflectionClass($this))->getShortName(); 30 | $this->table = strtolower($modelName); 31 | } 32 | } 33 | 34 | private function setPrimaryKey() 35 | { 36 | if ( ! isset($this->pk)) { 37 | $this->pk = 'id'; 38 | } 39 | } 40 | 41 | private function param($data = null) 42 | { 43 | if (empty($data)) { 44 | $data = $this->data['conditions']; 45 | } 46 | 47 | foreach ($data as $k => $v) { 48 | $tipo = (is_int($v)) ? PDO::PARAM_INT : PDO::PARAM_STR; 49 | $this->stmt->bindValue(":{$k}", $v, $tipo); 50 | } 51 | } 52 | 53 | private function fields($data = null) 54 | { 55 | if (empty($data) && isset($this->data['fields'])) { 56 | return implode(',', $this->data['fields']); 57 | } 58 | 59 | if ( ! empty($data)) { 60 | foreach ($data as $k => $v) { 61 | $fields[] = $k; 62 | } 63 | return implode(',', $fields); 64 | } 65 | 66 | return '*'; 67 | } 68 | 69 | private function conditions($separator) 70 | { 71 | $param = []; 72 | foreach ($this->data['conditions'] as $k => $v) { 73 | $param[] = "{$k} = :{$k}"; 74 | } 75 | 76 | return implode($separator, $param); 77 | } 78 | 79 | private function where() 80 | { 81 | return $this->where = (isset($this->data['conditions'])) 82 | ? 'WHERE ' . self::conditions(' AND ') 83 | : ''; 84 | } 85 | 86 | private function find() 87 | { 88 | $sql = "SELECT " . self::fields() . " FROM {$this->table} " . self::where(); 89 | 90 | $this->stmt = $this->conn->prepare($sql); 91 | 92 | if ( ! empty($this->where)) { 93 | self::param(); 94 | } 95 | 96 | $this->stmt->execute(); 97 | return $this; 98 | } 99 | 100 | private function values() 101 | { 102 | foreach ($this->data as $k => $v) { 103 | $values[] = ":{$k}"; 104 | } 105 | 106 | return implode(',', $values); 107 | } 108 | 109 | private function insertQueryString() 110 | { 111 | $fields = self::fields($this->data); 112 | $values = self::values(); 113 | 114 | return "INSERT INTO {$this->table} ({$fields}) VALUES ({$values})"; 115 | } 116 | 117 | private function updateWhere($data) 118 | { 119 | $this->data['conditions'] = [$this->pk => $data[$this->pk]]; 120 | $where = 'WHERE ' . self::conditions(''); 121 | unset($data[$this->pk]); 122 | 123 | return $where; 124 | } 125 | 126 | private function updateQueryString($data) 127 | { 128 | $this->data['conditions'] = $data; 129 | $fields = self::conditions(','); 130 | 131 | return "UPDATE {$this->table} SET {$fields} {$this->where}"; 132 | } 133 | 134 | public function findAll($data = null) 135 | { 136 | $this->data = $data; 137 | return $this->find() 138 | ->stmt->fetchAll(PDO::FETCH_ASSOC); 139 | } 140 | 141 | public function findOne($data) 142 | { 143 | $this->data['conditions'] = $data; 144 | return $this->fetch = $this->find() 145 | ->stmt->fetch(PDO::FETCH_ASSOC); 146 | } 147 | 148 | public function findById($id) 149 | { 150 | return self::findOne([$this->pk => $id]); 151 | } 152 | 153 | public function exists($id) 154 | { 155 | if (is_array($id)) { 156 | return (self::findOne($id)); 157 | } 158 | 159 | return (self::findById($id)); 160 | } 161 | 162 | public function fetch() 163 | { 164 | return $this->fetch; 165 | } 166 | 167 | public function lastSavedId() 168 | { 169 | $id = $this->conn->lastInsertId(); 170 | return ($id) ? $id : $this->lastId; 171 | } 172 | 173 | public function query($sql) 174 | { 175 | $this->stmt = $this->conn->prepare($sql); 176 | $this->stmt->execute(); 177 | $result = $this->stmt->fetchAll(PDO::FETCH_ASSOC); 178 | $this->count = count($result); 179 | 180 | return $result; 181 | } 182 | 183 | public function save($data) 184 | { 185 | if (array_key_exists($this->pk, $data)) { 186 | $this->count = $this->findOne([$this->pk => $data[$this->pk]]); 187 | $this->lastId = $data[$this->pk]; 188 | } 189 | 190 | if ( ! empty($this->count)) { 191 | return $this->update($data); 192 | } 193 | 194 | return $this->create($data); 195 | } 196 | 197 | public function update($data) 198 | { 199 | if ( ! array_key_exists($this->pk, $data)) { 200 | return false; 201 | } 202 | 203 | $param = $data; 204 | $this->where = self::updateWhere($data); 205 | $this->stmt = $this->conn->prepare(self::updateQueryString($data)); 206 | self::param($param); 207 | $this->stmt->execute(); 208 | $this->count = $this->stmt->rowCount(); 209 | } 210 | 211 | public function create($data) 212 | { 213 | $this->data = $data; 214 | 215 | $this->stmt = $this->conn->prepare(self::insertQueryString()); 216 | self::param($data); 217 | 218 | $this->stmt->execute(); 219 | $this->count = $this->stmt->rowCount(); 220 | } 221 | 222 | public function delete($data) 223 | { 224 | $this->data['conditions'] = $data; 225 | 226 | $sql = "DELETE FROM {$this->table} " . self::where(); 227 | $this->stmt = $this->conn->prepare($sql); 228 | 229 | if ( ! empty($this->where)) { 230 | self::param(); 231 | } 232 | 233 | $this->stmt->execute(); 234 | $this->count = $this->stmt->rowCount(); 235 | } 236 | 237 | } 238 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 'No content to show']; 24 | echo json_encode($response); 25 | exit; 26 | } 27 | 28 | $src = explode('/', $uri); 29 | $model = ucfirst($src[1]); 30 | $controller = $model . 'Controller'; 31 | $method = (isset($src[2])) ? $src[2] : 'index'; 32 | 33 | if (isset($src[3]) && empty($the_request)) { 34 | $the_request = filter_var($src[3], FILTER_SANITIZE_STRING); 35 | } 36 | 37 | /* 38 | * call current class/method 39 | */ 40 | try { 41 | $load_class = 'SimpleORM\app\controller\\' . $controller; 42 | $class = new $load_class(); 43 | $set = $class->$method($the_request); 44 | } catch (Exception $e) { 45 | echo 'No ' . $controller . ' found for this route', $e->getMessage(), "\n"; 46 | } 47 | 48 | /* 49 | * Declare all variables if passed in return 50 | */ 51 | if ( ! empty($set) && is_array($set)) { 52 | foreach ($set as $k => $v) { 53 | ${$k} = $v; 54 | } 55 | } 56 | 57 | /* 58 | * If method has a view file, include 59 | */ 60 | $view_file = APP_VIEW . $model . DS . $method . PHP; 61 | 62 | if (file_exists($view_file)) { 63 | include $view_file; 64 | } 65 | --------------------------------------------------------------------------------