Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

MaktubBruno

[Resolvido] Class 'ActiveRecord\Model' not found

Recommended Posts

Boa Tarde a todos!!!

 

Bom, estou iniciando em ActiveRecord e estou tendo um pequeno problema em receber um objeto através de uma função.

O engraçado é que se eu retiro o parâmetro tudo funciona normalmente o que quer dizer que não é problema de configuração.

 

Bom esse é o meu Model

<?php
class Usuarios extends ActiveRecord\Model
{
public $COD_USUARIO; // tinyint
public $NOM_USUARIO; // varchar
public $TXT_SENHA;	 // varchar
}

 

Esta é minha classe

<?php
require_once 'settings/ClassConecta.php';
require_once 'model/Usuarios.php';

class Usuario
{
private $baseConecta;

function __construct()
{
	$this->baseConecta = new ClassConecta();
}

public function login(Usuarios $usuario)
{
	return $usuario;
}
}

 

Estou tentando testando:

<?php
require_once 'model/Usuarios.php';

$obj = new Usuarios();
$obj->NOM_USUARIO = 'teste';
$obj->TXT_SENHA   = '123';

$model = new Usuario();
$return = $model->login($obj);

echo $return;

 

Eis que me retorna o seguinte erro:

Fatal error: Class 'ActiveRecord\Model' not found in C:\xampp\htdocs\...\model\Usuarios.php on line 3

 

Alguém poderia me ajudar a entender isso, desde já muito obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

se a classe não foi encontrada significa que o caminho do require esta errado, verifique direito o caminho.

 

para não ter problemas como é trabalhe com caminho inteiro, crie uma variável global e defina ela sua raiz exemplo

 

$config['raiz'] = "localhost/site";

 

e no PHP você utiliza

<img src="{$config['raiz']}/img/imagem1.jpg">

 

quando colocar no ar basta mudar a var raiz e tudo vai continuar normal.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Uma vez corrigido isso, você tem de corrigir VÁRIAS outras deficiências no seu código:

 

1. Não devem existir propriedades públicas e sim getters e setters para elas.

 

2. Classe Usuarios, no plural, caracteriza um grupo de Usuários, que deveria ser uma coleção de vários objetos Usuario. Logo ela está nomeada errada e mesmo que pareça frescura, você vai agradecer essa padronização no futuro.

 

3. Classe Usuarios conhece sua classe de conexão o que não deveria acontecer. A ação deve ocorrer com QUALQUER meio de armazenamento de dados e é aí que entram interfaces e polimorfismo, já que isso:

 

function __construct() {
   $this->baseConecta = new ClassConecta();
}

Passaria a ser isso:

 

function __construct( Connection $connection ) {
   $this->baseConecta = $connection();
}

sendo Connection uma interface:

 

interface Connection {}

Composta por todos os métodos públicos que um motor de armazenamento usaria, como query(), prepare(), lastInsertId() e etc.

 

Dessa forma, você permite que seus usuários sejam hoje armazenados no MySQL, mas amanhã pode ser feito no MongoDB, num arquivo de texto, num servidor remoto autenticado e etc. sem precisa mudar a classe Usuarios

 

4. Em você seguindo a dica #2, você teria uma terceira classe OU essa ActiveRecord\Model por hora desconhecida recebendo o objeto Usuarios, iterando sobre ele e fazendo algo com cada Usuario, este um objeto distinto.

 

A chance disso acontecer com um ActiveRecord acredito eu ser pequena pois o propósito dele é criar e construir um objeto, fazer a interação com o banco e pá-pum fim da história.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Uma vez corrigido isso, você tem de corrigir VÁRIAS outras deficiências no seu código:

 

1. Não devem existir propriedades públicas e sim getters e setters para elas.

 

2. Classe Usuarios, no plural, caracteriza um grupo de Usuários, que deveria ser uma coleção de vários objetos Usuario. Logo ela está nomeada errada e mesmo que pareça frescura, você vai agradecer essa padronização no futuro.

 

3. Classe Usuarios conhece sua classe de conexão o que não deveria acontecer. A ação deve ocorrer com QUALQUER meio de armazenamento de dados e é aí que entram interfaces e polimorfismo, já que isso:

 

function __construct() {
   $this->baseConecta = new ClassConecta();
}

Passaria a ser isso:

 

function __construct( Connection $connection ) {
   $this->baseConecta = $connection();
}

sendo Connection uma interface:

 

interface Connection {}

Composta por todos os métodos públicos que um motor de armazenamento usaria, como query(), prepare(), lastInsertId() e etc.

 

Dessa forma, você permite que seus usuários sejam hoje armazenados no MySQL, mas amanhã pode ser feito no MongoDB, num arquivo de texto, num servidor remoto autenticado e etc. sem precisa mudar a classe Usuarios

 

4. Em você seguindo a dica #2, você teria uma terceira classe OU essa ActiveRecord\Model por hora desconhecida recebendo o objeto Usuarios, iterando sobre ele e fazendo algo com cada Usuario, este um objeto distinto.

 

A chance disso acontecer com um ActiveRecord acredito eu ser pequena pois o propósito dele é criar e construir um objeto, fazer a interação com o banco e pá-pum fim da história.

 

Com certeza não é frescura, agradeço muito pelas dicas.

 

Entendi, vou fazer as correções, mais como disse estou iniciando em ActiveRecord e montei essa base para poder testar o código, e como deu errado já no início nem mexi no resto, o que é mais estranho que se eu retirar o parâmetro da função login(), ou seja, não passar nada o código funciona.

 

Sabe se é algum erro na passagem de parâmetros tipo (Usuarios $usuario)?

 

Att

Bruno Sanches

Compartilhar este post


Link para o post
Compartilhar em outros sites

Uma vez corrigido isso, você tem de corrigir VÁRIAS outras deficiências no seu código:

 

1. Não devem existir propriedades públicas e sim getters e setters para elas.

 

2. Classe Usuarios, no plural, caracteriza um grupo de Usuários, que deveria ser uma coleção de vários objetos Usuario. Logo ela está nomeada errada e mesmo que pareça frescura, você vai agradecer essa padronização no futuro.

 

3. Classe Usuarios conhece sua classe de conexão o que não deveria acontecer. A ação deve ocorrer com QUALQUER meio de armazenamento de dados e é aí que entram interfaces e polimorfismo, já que isso:

 

function __construct() {
   $this->baseConecta = new ClassConecta();
}

Passaria a ser isso:

 

function __construct( Connection $connection ) {
   $this->baseConecta = $connection();
}

sendo Connection uma interface:

 

interface Connection {}

Composta por todos os métodos públicos que um motor de armazenamento usaria, como query(), prepare(), lastInsertId() e etc.

 

Dessa forma, você permite que seus usuários sejam hoje armazenados no MySQL, mas amanhã pode ser feito no MongoDB, num arquivo de texto, num servidor remoto autenticado e etc. sem precisa mudar a classe Usuarios

 

4. Em você seguindo a dica #2, você teria uma terceira classe OU essa ActiveRecord\Model por hora desconhecida recebendo o objeto Usuarios, iterando sobre ele e fazendo algo com cada Usuario, este um objeto distinto.

 

A chance disso acontecer com um ActiveRecord acredito eu ser pequena pois o propósito dele é criar e construir um objeto, fazer a interação com o banco e pá-pum fim da história.

 

Então, fiz as alterações que você mencionou.

 

Interface Usuário

<?php
interface IUsuario
{
public function login(Usuarios $usuario, $NOM_BANCO_DADOS);
}

 

UsuárioVO

<?php
class UsuarioVO extends ActiveRecord\Model
{
private $COD_USUARIO; // tinyint
private $NOM_USUARIO; // varchar
private $TXT_SENHA;	 // varchar

public function setCOD_USUARIO( $COD_USUARIO )
{
	$this->COD_USUARIO = $COD_USUARIO;
}

public function setNOM_USUARIO( $NOM_USUARIO )
{
	$this->NOM_USUARIO = $NOM_USUARIO;
}

public function setTXT_SENHA( $TXT_SENHA )
{
	$this->TXT_SENHA = $TXT_SENHA;
}

public function getCOD_USUARIO()
{
	return $this->COD_USUARIO;
}

public function getNOM_USUARIO()
{
	return $this->NOM_USUARIO;
}

public function getTXT_SENHA()
{
	return $this->TXT_SENHA;
}
}

 

Usuário

<?php
require_once 'interface/IClassConecta.php';
require_once 'models/UsuarioVO.php';

class Usuario implements IUsuario
{
private $baseConecta;

function __construct( IClassConecta $connection )
{
	$this->baseConecta = $connection;
}

public function login(UsuarioVO $usuario, $NOM_BANCO_DADOS)
{
	$this->baseConecta->selecionarBanco($NOM_BANCO_DADOS);		

	$cond  = array( 'conditions' => array('NOM_USUARIO = ?', $usuario->getNOM_USUARIO() ));
	$model = UsuarioVO::all($cond);
	if ( $model == NULL )
	{
		$retorno = "Usuário não Encontrado";
	}
	else
	{
		$cond  = array( 'conditions' => array('NOM_USUARIO = ? AND TXT_SENHA = ?', $usuario->getNOM_USUARIO(), md5( $usuario->getTXT_SENHA() ) ));
		$model = Usuarios::all($cond);
		if ( $model == NULL )
		{
			$retorno = "Senha Incorreta";
		}
		else
		{
			$retorno = new UsuarioVO();
			$retorno->setNOM_USUARIO( $model->nom_usuario) ;
			$retorno->setTXT_SENHA( $model->txt_senha );
		}
	}
}
}

 

Arquivo de Teste

<?php
require_once 'interface/IUsuario.php';
require_once 'models/UsuarioVO.php';

$obj = new UsuarioVO();
$obj->setNOM_USUARIO('teste');
$obj->setTXT_SENHA('123');

$usuario = new IUsuario;
$usuario->login($obj, 'banco_dados01');

 

De qualquer jeito está dando a mensagem:

Fatal error: Class 'ActiveRecord\Model' not found in C:\xampp\htdocs\escolahouse.com.br\escolahouse-php\models\UsuarioVO.php on line 3

Compartilhar este post


Link para o post
Compartilhar em outros sites

Melhorou bastante mas ainda tem uns problemas ( maioria num único método):

 

Usuario::login() não recebe o nome do banco de dados, não é responsabilidade dele saber disso. Imagina que amanhã você por algum motivo bizarro e sinistro resolva usar um arquivo XML.

 

Essa variável passaria a se referenciar ao nome do arquivo, e não ao banco de dados em si. Funcionaria (em teoria), mas variáveis devem ser auto-descritivas sempre.

 

Essa informação você pertence ao objeto de conexão ao banco de dados, o qual implementa a sua interface IConecta

 

Usuario::login() não deveria receber o VO. Isso porque a classe Usuario trata de um único usuário e a informação vital para que ela funcione faz parte da construção do objeto.

 

Usuario::login() não seleciona o banco. Na bem da verdade nema própria classe Usuario faz isso. Também é responsabilidade do objeto de conexão escolher sobre qual banco operar antes de, de fato, fazê-lo.

 

No teste você instancia IUsuario que é uma interface e interfaces não são instanciáveis.

 

Mas, vamos nos voltar ao problema mais básico que está tendo: paths

 

Como você ainda faz include/require manual, uma dica valiosa que me ajudou muito no passado é você definir explicitamente a raiz do seu ambiente de trabalho através de uma constante.

 

No primeiro arquivo da aplicação, que pode ser o próprio index.php ou, de repente, algum config.php você adiciona:

 

define( 'BASE_DIR', __DIR__ . DIRECTORY_SEPARATOR ); // PHP 5.3+

define( 'BASE_DIR', dirname( __FILE__ ) . DIRECTORY_SEPARATOR ); // Outras versões abaixo

E então cada include/require que você fizer você inicia com essa constante.

 

Isso fará com todo processo de inclusão SEMPRE comece a procurar aquilo que estiver à frente dessa constante a partir do diretório raiz.

 

Sendo assim:

 

require BASE_DIR . 'path/to/my/classes.php';

Vai incluir o arquivo classes.php que deve estar dentro do subdiretório my, que por sua vez está dentro de to e por fim dentro de path que é um diretório presente na raiz da aplicação, junto com o index.php.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vou modificar de acordo com o "define( 'BASE_DIR', __DIR__ . DIRECTORY_SEPARATOR );" que você sugeriu, assim que testar dou um feedback.

 

Referente aos pontos que você mencionou eis os esclarecimentos para melhorar o entendimento do que estou fazendo e do que preciso, de ante mão muito obrigado pelas dicas, tem me ajudado muito.

 

Vamos lá:


  1.  
  2. Eu passo o nome do Banco devido ao fato de o sistema ter vários bancos de dados.
  3. É exatamente o IConceta que faz todo trabalho, eu apenas passo a informação de qual Banco ele deve trabalhar;
  4. Na tela de login há um combo onde cada opção se refere a um banco de dados diferente, foi a princípio a forma que encontrei de resolver isso, uma outra coisa que não comentei ainda é que este é um back-end de um sistema web, onde utilizo como front-end, Flex.
  5. Eu utilizo uma instancia do ClassConecta para chamar a função que seta o banco a ser utilizado antes de fazer qualquer manipulação;
  6. Há uma forma melhor (sempre há) de fazer isso?
     

 

Bons vamos agora a algumas dúvidas que tive, agradeço se esclarecer.

 

Usuario::login() não deveria receber o VO. Isso porque a classe Usuario trata de um único usuário e a informação vital para que ela funcione faz parte da construção do objeto.

Isso é uma má pratica ou se refere apenas ao Usuario? Utilizo isso em praticamente tudo que faço, recebo o VO nas classes e trato a informação, somente não uso para excluir, onde passo apenas o ID.

 

No teste você instancia IUsuario que é uma interface e interfaces não são instanciáveis.

Neste caso diferentemente do IConecta eu posso instanciar diretamente a Classe Usuario?

-- Bobagem, eu não instanciei o IConceta, apenas passei uma referencia, entendi melhor agora o uso da interface.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isso é uma má pratica ou se refere apenas ao Usuario? Utilizo isso em praticamente tudo que faço, recebo o VO nas classes e trato a informação, somente não uso para excluir, onde passo apenas o ID.

 

o PHP é uma linguagem excelente e ao mesmo tempo muito ruim por ser muito livre, você pode desenvolver o código do jeito que você quiser.

 

bom se isso é uma má pratica não sei mas costumo ver com certa frequência, o que posso te informar é que para o Orientando a Objeto é sim uma péssima prática.

 

eu pego bastante referencias do Neto pois aprendi quase tudo com ele sobre OO, um ponto importante foi que é muito comum ver uma classe desempenhando mais de uma função o que é errado(para o OO, certamente não da erro se você fizer), no caso um usuário deve ser nada mais e nada menos do que getters e setters onde irão receber dados do usuário em questão, depois teria que um outro objeto que poderia se chamar InsertUsers e receberia todos essas propriedades e passaria a inserir elas no seu banco de dados junto a sua conexão com o banco de dados.

 

Se em seu objeto existir 2 métodos que não se relacionam significa que desempenham tarefas diferentes portanto já quebrou uma regra do OO.

 

Segundo caso é que um interface é implementada pense nela como algo que vá definir um objeto.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isso é uma má pratica ou se refere apenas ao Usuario? Utilizo isso em praticamente tudo que faço, recebo o VO nas classes e trato a informação, somente não uso para excluir, onde passo apenas o ID.

 

o PHP é uma linguagem excelente e ao mesmo tempo muito ruim por ser muito livre, você pode desenvolver o código do jeito que você quiser.

 

bom se isso é uma má pratica não sei mas costumo ver com certa frequência, o que posso te informar é que para o Orientando a Objeto é sim uma péssima prática.

 

eu pego bastante referencias do Neto pois aprendi quase tudo com ele sobre OO, um ponto importante foi que é muito comum ver uma classe desempenhando mais de uma função o que é errado(para o OO, certamente não da erro se você fizer), no caso um usuário deve ser nada mais e nada menos do que getters e setters onde irão receber dados do usuário em questão, depois teria que um outro objeto que poderia se chamar InsertUsers e receberia todos essas propriedades e passaria a inserir elas no seu banco de dados junto a sua conexão com o banco de dados.

 

Se em seu objeto existir 2 métodos que não se relacionam significa que desempenham tarefas diferentes portanto já quebrou uma regra do OO.

 

Segundo caso é que um interface é implementada pense nela como algo que vá definir um objeto.

 

 

Então eu deveria setar (setters) os valor no UsuarioVO e buscar com (getter)? Seria isso?

Minha dúvida é neste ponto, pois na minha visão de qualquer forma tenho de passar estes dados de alguma forma?

Por se tratar de um sistema flex onde é chamado métodos de uma função complica um pouco, pelo menos pra mim, acho que estou começando a entender mais tenho dúvida de como implementar!!!

Compartilhar este post


Link para o post
Compartilhar em outros sites
Eu passo o nome do Banco devido ao fato de o sistema ter vários bancos de dados.

Isso é indiferente, veja:

 

A classe Usuario vai, dentre outras coisas autenticar o usuário. A lógica em que essa operação vai acontecer não deve ser conhecida pela classe. Contanto que a interface IConecta esteja bem definida, ela vai funcionar de forma completamente ignorante do meio externo.

 

Como eu disse, é responsabilidade da classe que implementa IConecta selecionar o banco.

 

Vou supor que você esteja usando funções mysql_*, já que você seleciona o banco manualmente.Imagina amanhã seu sistema cresce e você sente a necessidade de usar a PDO para abstrair a interface (não o SQL) para vários bancos de dados.

 

A PDO não tem seleção de banco. Na hora que você constrói o objeto PDO, você informa uma string que servirá de DSN e parte dessa string é o nome do banco.

 

Quando você informa um objeto IConecta para classe Usuario, este objeto tem de vir pronto para ser usado.

 

Uma boa forma de centrar essa operação é utilizar um Registry. Por esse Design Pattern utilizar-se do de outro, o malfalado Singleton, a instância do objeto será sempre a mesma, não importa onde o objeto de conexão tenha sido criado.

 

Por exemplo. Suponhamos que você já tenha uma implementação do padrão Singleton e no index.php você efetua a conexão:

 

$link = mysql_connect( 'localhost', 'user', 'password');

if( ! $link ) {
   die( 'Could not connect: ' . mysql_error() );
}

$db = mysql_select_db( 'usuarios', $link );

if( ! $db ) {
   die( 'Can\'t use usuarios: ' . mysql_error() );
}

Você armazenaria esse link específico no Registry:

 

Registry::getInstance():: set( 'usuarios', $link );

E você pode repetir isso para tantos objetos de conexão,de tantos banco de dados diferentes quantos você precisar.

 

Com isso você dispensa o argumento do tipo IConecta, informando apenas uma string para você buscar no Registry:

 

class Usuario implements IUsuario {

   public function __construct( $link ) {

       $this -> baseConecta = Registry::getInstance() -> get( $link );
   }
}

O único porém aqui, é que você perde parte da confiança (gostaria de saber como não perdê-la) no seu objeto porque o Registry aceita qualquer coisa, mas Usuario espera um IConecta, então você deve verificar:

 

class Usuario implements IUsuario {

   public function __construct( $link ) {

       $connection = Registry::getInstance() -> get( $link );

       if( ! $connection instanceof IConecta ) {
           // Dispara um erro
       }

       $this -> baseConecta = $connection;
   }
}

E pronto!

 

Isso é uma má pratica ou se refere apenas ao Usuario? Utilizo isso em praticamente tudo que faço, recebo o VO nas classes e trato a informação, somente não uso para excluir, onde passo apenas o ID.

Já ouviu falar de DRY (Don't Repeat Yourself - Não se repita). O que você acha melhor:

 

class Usuario implements IUsuario {

   public function __construct( $link ) {
       // Repete bloco do código anterior
   }

   public function login( UsuarioVO $vo ) {}

   public function logout( UsuarioVO $vo ) {}

   public function update( UsuarioVO $vo, array $data ) {}

   public function delete( UsuarioVO $vo ) {

       // Usa: $vo -> getID();
   }
}

Ou esse:

 

class Usuario implements IUsuario {

   public function __construct( $link, UsuarioVO $vo ) {
       // Repete bloco do código anterior

       $this -> vo = $vo;
   }

   public function login() {}

   public function logout() {}

   public function update( $data ) {

       /**
        * Aqui você itera $data e redefine o VO recebido
        * exceto o ID pois o ID é imutável
        *
        * Se nulo, ao invés de um update, você faz um insert
        */
   }

   public function delete() {

       // Usa: $this -> vo -> getID();
   }
}

A última explicação ficou meio vaga, mas as idéias principais foram ditas.

 

Bons estudo :thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Novamente muito obrigado, com essas ideias tudo vai se clareando um pouco.

Quando fui utilizar o "define", percebi o erro principal e o porque de o ActiveRecord não está funcionando.

Eu tenho um método: selecionaBanco() dentro da classe Conecta, e dentro dele que colocava o cfg do ActiveRecord, ou seja, quando chamava o metodo login() dentro de Usuario ele tentava fazer um cast de UsuarioVO e como o UsuarioVO extend ActiveRecord\Model, dava erro pois o ActiveRecord ainda não havia sido iniciado, ou seja estava tentando utilizar um recurso que ainda não estava pronto para ser usado.

 

É apenas um explicação para ajudar caso alguém passar pelo mesmo problema ou algo parecido.

 

No mais, vou dar uma estudado em suas dicas, tem me ajudado muito, o único porém é que como o sistema é Flex estou enfrentando dificuldades em implementar tais técnicas.

 

Valeu pela força, muito obrigado.

 

Att

Bruno Sanches

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.