Created
March 11, 2012 16:10
-
-
Save lm/2016976 to your computer and use it in GitHub Desktop.
PHPClosure2SQL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Collection | |
{ | |
private $items = array(); | |
function add($item) | |
{ | |
$this->items[] = $item; | |
} | |
function select($closure) | |
{ | |
$selected = array(); | |
foreach ($this->items as $item) { | |
if ($closure($item)) { | |
$selected[] = $item; | |
} | |
} | |
return $selected; | |
} | |
} | |
class DatabaseCollection | |
{ | |
function select($closure) | |
{ | |
echo $this->buildSql($closure), "\n"; | |
} | |
function buildSql($closure) | |
{ | |
$reflection = new ReflectionFunction($closure); | |
$parameters = $reflection->getParameters(); | |
$staticVars = $reflection->getStaticVariables(); | |
$table = reset($parameters)->name; | |
$sql = "SELECT *\nFROM " . $table; | |
$where = ''; | |
$skip = TRUE; | |
$expectProperty = FALSE; | |
$join = NULL; | |
foreach (token_get_all('<?php ' . $this->getSourceOf($reflection)) as $token) { | |
if (is_string($token)) { | |
$token = array($token, $token, NULL); | |
} | |
//echo @token_name($token[0]), ' ', $token[1], "\n"; | |
if ($skip) { | |
switch ($token[0]) { | |
case T_RETURN: | |
$skip = FALSE; | |
break; | |
} | |
} else { | |
switch ($token[0]) { | |
case T_VARIABLE: | |
$var = substr($token[1], 1); | |
$where .= isset($staticVars[$var]) ? '"' . $staticVars[$var] . '"' : $var; | |
break; | |
case T_OBJECT_OPERATOR: | |
if ($join) { | |
$sql .= "\nINNER JOIN $join ON $join.id = $table.{$join}_id "; | |
} | |
$where .= '.'; | |
break; | |
case T_IS_IDENTICAL: | |
$where .= '='; | |
break; | |
case '}': | |
break 2; | |
case ';': | |
break; | |
case T_STRING: | |
if ($expectProperty) { | |
$join = $token[1]; | |
} | |
default: | |
$where .= $token[1]; | |
break; | |
} | |
$expectProperty = $token[0] === T_OBJECT_OPERATOR; | |
} | |
} | |
return $sql . "\nWHERE " . trim($where); | |
} | |
function getSourceOf($reflection) | |
{ | |
$f = fopen($reflection->getFileName(), 'r'); | |
$source = ''; | |
for ($i = 1; $i <= $reflection->getEndLine(); $i++) { | |
$line = fgets($f); | |
if ($i >= $reflection->getStartLine()) { | |
$source .= $line; | |
} | |
} | |
return $source; | |
} | |
} | |
$pages = new DatabaseCollection; | |
$catName = 'news'; | |
$pages->select(function($page) use ($catName) | |
{ | |
return $page->category->name === $catName; | |
}); | |
/* Output: | |
SELECT * | |
FROM page | |
INNER JOIN category ON category.id = page.category_id | |
WHERE page.category.name = "news" | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment