Browse Source

* Fix up base being set on apps
* Allow releasing relationships from memory
* properly handle quoting of data
* force routes to find /path/ and /path as different again
* Make routers chainable
* add EArray->to_array()
* Add some offset overrides to Relationship so that you can check to see if an object exists by it's id
* better Table error handling

Nathaniel van Diepen 7 years ago
parent
commit
5b95f9b694
8 changed files with 95 additions and 16 deletions
  1. 1 1
      App/dypath.class.php
  2. 4 1
      App/router.class.php
  3. 3 0
      Data/earray.class.php
  4. 23 1
      ORM/relationship.class.php
  5. 5 3
      PDO/table.class.php
  6. 23 4
      app.class.php
  7. 7 2
      orm.abstract.class.php
  8. 29 4
      pdo.class.php

+ 1 - 1
App/dypath.class.php

@@ -24,7 +24,7 @@
 					return $m;
 				break;
 				case 'regex':
-					return '/^'.preg_replace('/\\\{[^#\/][^}\n]+?\\\}/','([^\/]+)', preg_quote($this->path,'/')).'\/?$/';
+					return '/^'.preg_replace('/\\\{[^#\/][^}\n]+?\\\}/','([^\/]*)', preg_quote($this->path,'/')).'\/?$/';
 				break;
 			}
 		}

+ 4 - 1
App/router.class.php

@@ -44,6 +44,7 @@
 		}
 		public function base(string $base){
 			$this->_base = $base;
+			return $this;
 		}
 		public static function url(string $url){
 			return preg_replace('/(\/+)/','/',$url);
@@ -62,6 +63,7 @@
 				$this->_routers[] = $router;
 				$fn($router);
 			}
+			return $this;
 		}
 		public function path(string $path, callable $fn){
 			$obj = false;
@@ -160,10 +162,11 @@
 		}
 		public function clear(){
 			$this->_paths = [];
+			return $this;
 		}
 		public function handle(string $path, Request $req = null, Response $res = null, callable $fn = null, callable $onerror = null){
 			if(strpos($path, $this->base) !== false){
-				$path = substr($path,strpos($path,$this->base)+strlen($this->base));
+				$path = ltrim($path, $this->base);
 				if($path[0] != '/'){
 					$path = '/'.$path;
 				}

+ 3 - 0
Data/earray.class.php

@@ -39,5 +39,8 @@
 			}
 			return $this;
 		}
+		public function to_array(){
+			return $this->data;
+		}
 	}
 ?>

+ 23 - 1
ORM/relationship.class.php

@@ -38,7 +38,7 @@
 				});
 		}
 		public function add(ORM $model){
-			$this[] = $model;
+			$this[$model->id] = $model;
 			return $this;
 		}
 		public function remove(ORM $model){
@@ -117,5 +117,27 @@
 				$this->added = [];
 			}
 		}
+		public function offsetSet($offset, $value){
+			$this->fire('set', $value->id, $value);
+			$this->data[$value->id] = $value;
+		}
+		public function filter(array $filter){
+			$items = [];
+			foreach($this->data as $item){
+				$item->load();
+				foreach($filter as $key => $value){
+					$val = $item[$key];
+					if($val !== $value){
+						unset($item);
+						break;
+					}
+				}
+				if(isset($item)){
+					$items[$item->id] = $item;
+				}
+			}
+			unset($item);
+			return $items;
+		}
 	}
 ?>

+ 5 - 3
PDO/table.class.php

@@ -150,13 +150,15 @@
 				foreach($this->foreignKeys as $name => $k){
 					$fk .= ", {$pdo->stringForeignKey($name, $k)}";
 				}
-				$count = $pdo->exec("create table `{$this->name}` ({$columns}{$pk}{$index}{$fk})");
+				$sql = "create table `{$this->name}` ({$columns}{$pk}{$index}{$fk})";
+				$count = $pdo->exec($sql);
 				if($count === false){
 					throw $pdo->getError();
 				}
 				if(!$this->exists()){
-					throw new \Exception("Unable to create table {$this->name}");
+					throw new \Exception("Unable to create table {$this->name}. Generated SQL: {$sql}");
 				}
+				unset($sql);
 				$this->exists();
 			}else{
 				$columns = array_filter($this->columns, function($item){
@@ -265,7 +267,7 @@
 			}
 			return $this;
 		}
-		public function column(string $name, string $type = null, string $default = null, bool $null = false, bool $increment = false){
+		public function column(string $name, string $type = null, $default = null, bool $null = false, bool $increment = false){
 			if(!is_null($type)){
 				$new = [
 					'type'=> $type,

+ 23 - 4
app.class.php

@@ -108,8 +108,10 @@
 				}
 				// Prefixed path routers
 				foreach($this->routers as $prefix => $router){
-					$router->handle($url["path"], $req, $res, null, $onerror);
-					$handled = $handled || $router->handled;
+					if(strpos($url["path"], $prefix, 0 ) == 0){
+						$router->handle($url["path"], $req, $res, null, $onerror);
+						$handled = $handled || $router->handled;
+					}
 				}
 				// Base router for non-prefixed paths
 				$this->router->handle($url["path"], $req, $res, function($req, $res) use($handled, $self, $url){
@@ -125,20 +127,36 @@
 			$this->_onerror = $fn;
 			return $this;
 		}
+		public function base(string $base = null){
+			if(is_null($base)){
+				return $this->router->base;
+			}else{
+				foreach($this->domains as &$router){
+					if($router instanceof Router){
+						$router->base($base);
+					}
+				}
+				foreach($this->routers as $prefix => &$router){
+					$router->base("{$base}/{$prefix}");
+				}
+				$this->router->base($base);
+				return $this;
+			}
+		}
 		public function route(string $path, callable $fn){
 			$this->router->path($path, $fn);
 			return $this;
 		}
 		public function prefix(string $prefix, callable $fn){
 			if(!$this->routers[$prefix]){
-				$this->routers[$prefix] = new Router($prefix);
+				$this->routers[$prefix] = new Router("{$this->router->base}/{$prefix}");
 			}
 			$fn($this->routers[$prefix]);
 			return $this;
 		}
 		public function domain(string $host, callable $fn){
 			if(!isset($this->domains[$host])){
-				$this->domains[$host] = new Router();
+				$this->domains[$host] = new Router($this->router->base);
 			}
 			$fn($this->domains[$host]);
 			return $this;
@@ -184,4 +202,5 @@
 			App::shutdown_error(new App\Exception($error->getMessage(), $error->getCode(), $error, $error->getFile(), $error->getLine(), $error->getTrace()));
 		}
 	});
+	gc_enable();
 ?>

+ 7 - 2
orm.abstract.class.php

@@ -158,7 +158,7 @@
 		public static function table_name(){
 			if(is_null(static::$table_name)){
 				$name = get_called_class();
-				static::$table_name = substr($name, strrpos($name, '\\') + 1);
+				return substr($name, strrpos($name, '\\') + 1);
 			}
 			return static::$table_name;
 		}
@@ -399,7 +399,7 @@
 					$related = [];
 					$query = self::query($sql);
 					foreach($query->fetchAll() as $row){
-						$related[] = new $class($row['id']);
+						$related[$row['id']] = new $class($row['id']);
 					}
 					$query->closeCursor();
 					$this->_related[$name] = Relationship::from($this, $name, $alias, $related);
@@ -411,5 +411,10 @@
 				throw new \Exception("Relationship {$name} does not exist");
 			}
 		}
+		public function release(string $name){
+			if(isset($this->_related[$name])){
+				unset($this->_related[$name]);
+			}
+		}
 	}
 ?>

+ 29 - 4
pdo.class.php

@@ -111,8 +111,15 @@
 			$query->execute();
 			return $query;
 		}
-		public function quote(...$args){
-			return $this->pdo->quote(...$args);
+		public function quote($value, $type = \PDO::PARAM_STR){
+			if($type == \PDO::PARAM_INT){
+				return (int)$value;
+			}elseif($type == \PDO::PARAM_BOOL){
+				return (bool)$value ? "b'1'" : "b'0'";
+			}elseif($type == \PDO::PARAM_NULL){
+				return 'null';
+			}
+			return $this->pdo->quote($value, $type);
 		}
 		public function beginTransaction(...$args){
 			return $this->pdo->beginTransaction(...$args);
@@ -141,7 +148,17 @@
 			if(!is_null($filter)){
 				$where = 'where ';
 				foreach($filter as $name => $value){
-					$where .= "`{$name}` = {$this->quote($value)} and";
+					$value = $column['default'];
+					if(is_integer($value)){
+						$type = \PDO::PARAM_INT;
+					}elseif(is_bool($value)){
+						$type = \PDO::PARAM_BOOL;
+					}elseif(is_null($value)){
+						$type = \PDO::PARAM_NULL;
+					}else{
+						$type = \PDO::PARAM_STR;
+					}
+					$where .= "`{$name}` = {$this->quote($value, $type)} and";
 				}
 				$where = rtrim($where, ' and');
 			}
@@ -160,7 +177,15 @@
 		public function stringColumn(string $name, array $column){
 			$default = '';
 			if(!is_null($column['default'])){
-				$default .= " DEFAULT {$this->quote($column['default'])}";
+				$value = $column['default'];
+				if(is_integer($value)){
+					$type = \PDO::PARAM_INT;
+				}elseif(is_bool($value)){
+					$type = \PDO::PARAM_BOOL;
+				}else{
+					$type = \PDO::PARAM_STR;
+				}
+				$default .= " DEFAULT {$this->quote($value, $type)}";
 			}
 			$null = $column['null'] ? ' NULL' : ' NOT NULL';
 			$ai = $column['increment'] ? ' AUTO_INCREMENT' : '';