<< Click to Display Table of Contents >> Modelo.php |
![]() ![]() ![]() |
<?php
namespace persistencia;
abstract class Modelo {
private $mensagemValidacao;
// array das propriedades publicas que foram implementadas
private function getPublicVars() {
$publicVars = create_function('$obj', 'return get_object_vars($obj);');
return $publicVars($this);
}
public function __toString() {
return get_called_class();
}
private function isPossuiAnotacao($nomeProp, $anotacao): bool {
$propriedade = new \ReflectionProperty(get_called_class(), $nomeProp);
return strpos($propriedade->getDocComment(), "@" . $anotacao) !== false;
}
private function isKey($prop): bool {
return $this->isPossuiAnotacao($prop, "pk");
}
private function isAutoInc($prop): bool {
return $this->isPossuiAnotacao($prop, "autoinc");
}
private function isNull($prop): bool {
return $this->isPossuiAnotacao($prop, "null");
}
private function isOnlyInsert($prop): bool {
return $this->isPossuiAnotacao($prop, "onlyinsert");
}
private function isOnlyUpdate($prop): bool {
return $this->isPossuiAnotacao($prop, "onlyupdate");
}
public function getCampoValores(): array {
$update = $this->isKeyContemValor();
$propriedades = $this->getPublicVars();
$saida = array();
foreach ($propriedades as $k => $v) {
if ($update) {
// se for update, ignora os campos only-insert
if ($this->isOnlyInsert($k)) {
continue;
}
} else {
// se for insert, ignora auto-inc e only-update
if ($this->isOnlyUpdate($k) || $this->isAutoInc($k)) {
continue;
}
}
$saida[$k] = $v;
}
return $saida;
}
public function getMensagemValidacao() {
return $this->mensagemValidacao;
}
/**
* Valida se todas as propriedades que são NOT null estão preenchidas
* @return string
*/
public function isTodasPropriedadesValidas($modo_update): bool {
$this->mensagemValidacao = "";
$modo_insert = !$modo_update;
// pega todas as propriedades publicas e seus valores
$propriedades = $this->getPublicVars();
foreach ($propriedades as $k => $v) {
// valor não tá nulo, ignora?
if (isset($v)) {
continue;
}
// campo permite nulo? então ignora
if ($this->isNull($k)) {
continue;
}
// se estamos no modo update
if ($modo_update) {
// se o campo é somente insert, ignora
if ($this->isOnlyInsert($k)) {
contineu;
}
$this->mensagemValidacao = "Campo '{$k}' está vazio (" . get_called_class() . ")u";
break;
}
// se estamos no modo insert
if ($modo_insert) {
// se é campo somente insert ou auto-inc ignora
if ($this->isOnlyUpdate($k) || $this->isAutoInc($k)) {
continue;
}
$this->mensagemValidacao = "Campo '{$k}' está vazio (" . get_called_class() . ")i";
break;
}
}
return (empty($this->mensagemValidacao));
}
public function getTabela(): string {
$prop = new \ReflectionClass($this);
// pega o comentário
$comentario = $prop->getDocComment();
// separa por espaço
$p = explode(" ", $comentario);
// tem 2 itens e o segundo item começa com @ ?
if (count($p) > 1 && $p[1][0] == "@") {
// copia do segundo caracter até o fim
return substr($p[1], 1);
} else {
return "";
}
}
/** retorna TRUE se o campo chave não é nulo */
public function isKeyContemValor(): bool {
$propriedades = $this->getPublicVars();
foreach ($propriedades as $k => $v) {
if ($this->isKey($k)) {
return !($v == null || $v == 0);
}
}
return false;
}
public function getCampoChave(): string {
$propriedades = $this->getPublicVars();
// pega só as chaves
$keys = array_keys($propriedades);
foreach ($keys as $k) {
if ($this->isKey($k)) {
return $k;
}
}
throw new Exception("Campo chave não localizado (" . get_called_class() . ")");
}
public function getInsertSQL() {
$sql_campos = "INSERT INTO " . $this->getTabela() . " (";
$sql_valores = ") VALUES (";
// $propriedades retorna nome_propriedade => valor; nome_propriedade => valor; ...
$propriedades = $this->getPublicVars();
// pega só as chaves
$keys = array_keys($propriedades);
foreach ($keys as $k) {
// se não é para entrar no insert e se é autoinc ignora
if ($this->isOnlyUpdate($k) || $this->isAutoInc($k)) {
continue;
}
$sql_campos .= $k . ",";
$sql_valores .= ":{$k},";
}
return rtrim($sql_campos, ',') . rtrim($sql_valores, ',') . ")";
}
public function getUpdateSQL() {
$sql = "UPDATE " . $this->getTabela() . " SET ";
$sql_where = " WHERE ";
// $propriedades retorna nome_propriedade => valor; nome_propriedade => valor; ...
$propriedades = $this->getPublicVars();
// pega só as chaves
$keys = array_keys($propriedades);
foreach ($keys as $k) {
if ($this->isOnlyInsert($k)) {
continue;
}
if ($this->isKey($k)) {
$sql_where .= "{$k}=:{$k}";
} else {
$sql .= "{$k}=:{$k},";
}
}
return rtrim($sql, ',') . $sql_where;
}
private function getSelectDelete($id): string {
$sql = " FROM " . $this->getTabela() . " WHERE ";
$propriedades = $this->getPublicVars();
// pega só as chaves
$keys = array_keys($propriedades);
foreach ($keys as $k) {
if ($this->isKey($k)) {
$sql .= "{$k}=:{$k}";
break;
}
}
return $sql;
}
public function getSelectSQL($id) {
return "SELECT *" . $this->getSelectDelete($id);
}
public function getDeleteSQL($id) {
return "DELETE" . $this->getSelectDelete($id);
}
public function getSelectSQLSemWhere() {
return "SELECT * FROM " . $this->getTabela() . " ";
}
// isso aqui vai mostrar um erro sempre que for tentado
// setar uma propriedade que não existe -- é importante
// para enviar erro de digitação
public function __set($name, $value) {
$this->naoEncontrado(__FUNCTION__, $name);
echo "Valor: {$value}";
}
// se tentar obter uma propriedade que não existe
// esse método é executado informando erro
public function __get($name) {
$this->naoEncontrado(__FUNCTION__, $name);
}
// é chamado sempre que é testado uma propriedade
// com o método isset($class->prop)
public function __isset($name) {
$this->naoEncontrado(__FUNCTION__, $name);
}
// se chamar uma função que não existe ou não é pública
// isso aqui será chamado
public function __call($name, $arguments) {
$this->naoEncontrado(__FUNCTION__, $name);
var_dump($arguments);
}
// esse é executado quando chama o unset($var) com propridade
// inválida ou privado
public function __unset($name) {
$this->naoEncontrado(__FUNCTION__, $name);
}
private function naoEncontrado($metodo, $nome) {
throw new \Exception("{$metodo}: A propriedade {$nome} não existe em " . __CLASS__);
}
}