Dev & EngARTIGO

Como realizar a integração do CodeIgniter com Doctrine 2 – Buscas – #Melhores2013

Recebi várias perguntas relacionadas a como fazer consultas nos dados armazenados e escrevi este artigo para dar continuidade ao primeiro.

Tenho recebido diversos e-mails com perguntas relacionadas a como fazer consultas nos dados armazenados. Então, resolvi escrever este artigo para dar continuidade ao primeiro. A base dos arquivos que vou utilizar são os apresentados no artigo anterior.

Preparações

1. Bootstrap

É interessante fazermos um bootstrap, assim, quando instanciarmos uma entidade, o arquivo será carregado automaticamente e não precisaremos nos preocupar com includes. Para isso, utilizarei a função spl_autoload_register.

Vamos então criar um arquivo chamado “autoload_register”, que deve ficar dentro de “/application/libraries” com o seguinte código:

//Registra o autoload das classes
spl_autoload_register('Autoload_Register::register');

/**
 * Executa o autoload de classes que não são do CI nem de PEAR
 */
class Autoload_Register
{

    const CI_PREFIX = "CI_";
    const PEAR = 'PEAR';

    /**
     * Faz o registro
     *
     * @param string $classe
     * @return void
     */
    public static function register($classe)
    {
        $paths = array();        
        $paths[] = APPPATH . 'models/Entities';

        //Classes do CI e do PEAR são ignoradas
        if (strstr($classe, self::CI_PREFIX) || stristr($classe, self::PEAR))
        {
            //Nada a fazer
            return;
        }

        //Remove o namesapce
        $vetClasse = explode('\\', $classe);
        $classe = $vetClasse[count($vetClasse)-1];

        //Garante que "$paths" seja um array
        if (is_array($paths) && count($paths) > 0)
        {
            //Localiza arquivos nos paths determinados no inicio da classe
            foreach ($paths as $dir)
            {
                $files = self::find($dir, $classe . EXT);

                //Se tiver arquivos a serem incluidos, executa o require_once para cada um deles
                if (is_array($files) && count($files) > 0)
                {
                    foreach ($files as $file)
                    {
                        if (is_file($file))
                        require_once $file;
                    }
                }
            }
        }
    }

    // ------------------------------------------------------------------------

    /**
     * Procura por arquivos
     *
     * @param string $dir
     * @param string $pattern
     * @return array
     */
    private function find($dir, $pattern)
    {
        // Elimina caracteres inválidos para comandos shell
        $dir = escapeshellcmd($dir);

        // pega a lista de todas as coincidencias no diretorio corrente
        $files = glob("$dir/$pattern");

        // procura a lista de todos os sub diretorios no diretorio corrente
        // diretorios iniciados por um ponto também são incluidos
        foreach (glob("$dir/{.[^.]*,*}", GLOB_BRACE | GLOB_ONLYDIR) as $sub_dir)
        {
            $arr = self::find($sub_dir, $pattern);  // chamada revursiva
            $files = array_merge($files, $arr); // faz um merge no array com os arquivos do sub diretorio
        }

        // retorna todos os arquivos encontrados
        return $files;
    }

}

Criado o arquivo, precisamos colocá-lo no autoload do CI. A chave ‘libraries’ da matriz $autoload deve ficar da seguinte forma:

$autoload['libraries'] = array('database', 'Doctrine', 'autoload_register');

Pronto, quando o CI carregar essa library, a primeira coisa que ela vai fazer é registrar no SPL_AUTOLAD o método “register” da classe “Autoload_Register”. E sempre que for criada uma nova instância de uma classe, o PHP↳PHP44 conteúdosPadronizando seu código com PHP CS FixerDev (Back & Front) · mai 2019Docker de imagem. Para rodar projetos PHP em menos de 30 segundosDev (Back & Front) · jan 2026PHP 7.3: conheça as novidades desta versãoDev (Back & Front) · abr 2019Ver tudo em Dev (Back & Front) → vai passar primeiro por esse método “register”, que por sua vez vai procurar dentro na pasta “models/Entities” o arquivo que ele deve fazer o require.

2. Preparando os dados

Antes de fazer o teste, vou adicionar um campo no banco de dados↳Banco de dados134 conteúdosSQL ou NoSQL: eis a questão!!Data · mar 2020Banco de dados: como organizar e dar segurança para milhões de dados de loteriasData · mai 20215 serviços gratuitos na cloud para bancos de dados PostgresData · fev 2025Ver tudo em Data → chamado “idade”. Para isso vou adicionar a propriedade $idade na classe “usuário”. Isso vai facilitar explicações futuras.

/**
 * @Column(type="integer", nullable=true)
 * @var type
 */
public $idade;

E vou rodar um comando do doctrine para atualizar a base de dados:

php doctrine orm:schema-tool:update --force

Feito isso, podemos fazer um teste alterando a forma popular do objeto “usuário” para o seguinte:

public function index()
{
    $usuario = new usuario();
    $usuario->set_nome('Ricardo');
    $usuario->set_email('meuemail@mail.com.br');
    $usuario->set_telefone('11-1122-3345');
    $usuario->set_celular('11-9988-7765');
    $usuario->set_idade(25);

    $this->doctrine->em->persist($usuario);
    $this->doctrine->em->flush();
}

Repare que foi retirado o “$this->load->model(‘Entities/usuario’, ‘usuario’);” do arquivo que fizemos no artigo anterior. Tembém foram implementados os getters e setters da classe “usuario”.

Para melhorar os testes e não precisar gastar a criatividade inserindo diversos usuários, podemos utilizar o site http://www.generatedata.com para gerar dados aleatórios e popular o banco.

Mão na massa

Finalmente vamos ao que interessa: fazer as consultas. Existem diversas formas de consultar um dado com o Doctrine. Vou citar aqui as que mais utilizo e a partir daí cada um poderá utilizar o que achar mais adequado para cada situação.

A documentação está disponível no site do Doctrine.

1. find()

A sintaxe é: $em->find($entidade, $id). A função find() vai procurar na entidade informada o registro com o ID solicitado. Podemos utilizar da segunte forma:

    /**
     * Localiza o usuario para ser editado
     * 
     * @param int $id
     */
    public function editar($id)
    {
        $usuario = $this->doctrine->em->find('usuario', $id);

        if ($usuario instanceof usuario)
        {
            echo 'Nome: ' . $usuario->get_nome() . '<br>';
            //Aqui pode carregar a view para editar o usuário
        }
        else
        {
            echo 'Usuário não localizado';
            //Volta para a listagem informando que o usuário não existe
        }
    }

 

2. findOneBy()

A sintaxe é: $em->getRepository($entidade)->findOneBy(array($campo => $valor)). Esta função faz uma busca na entidade informada buscando pelo campo e valores solicitados. Veja um exemplo:

    /**
     * Consulta pelo campo e valor solicitado
     *
     * @param string $campo Nome do campo onde se deseja fazer a busca
     * @param mixed $valor Valor que deve ser localizado
     * @link http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-objects.html#by-simple-conditions
     */
    public function localizar($campo, $valor)
    {
        $usuario = $this->doctrine
                        ->em
                        ->getRepository('usuario')
                        ->findOneBy(array($campo => $valor));

        if ($usuario instanceof usuario)
        {
            echo 'Nome: ' . $usuario->get_nome() . '<br>';
        }
        else
        {
            echo 'Usuário não localizado';
        }
    }

Então, para buscar o usuário “ricardo” basta fazer o seguinte:

$this->localizar('nome', 'ricardo');

Isto irá gerar uma SQL assim: SELECT * FROM usuario WHERE nome = ‘ricardo’.

3. DQL – Doctrine Query Language

Para fazermos buscas mais avançadas, podemos utilizar as DQLs (Doctrine Query Language), onde iremos escrever um código muito parecido com a SQL com pequenos detalhe de diferença, veja:

    /**
     * Localiza um usuário que tenha a idade entre dois valores
     *
     * @param type $idade_menor
     * @param type $idade_maior
     * @link http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-objects.html#by-dql DQL
     */
    public function localizar_por_idade($idade_menor, $idade_maior)
    {
        $usrs = $this->doctrine
                ->em
                ->createQuery("SELECT u FROM usuario u WHERE u.idade >= {$idade_menor} and u.idade <= {$idade_maior}")
                ->getResult();

        if (is_array($usrs) && count($usrs) > 0)
        {
            foreach ($usrs as $i => $usuario)
            {
                if ($usuario instanceof usuario)
                {
                    echo "{$i} - Nome: {$usuario->get_nome()}<br>";
                }
            }
        }

    }

Veja que interessante, na SQL, no lugar do nome da tabela, utilizei o nome da entidade que criamos e em vez de utilizar um * para trazer todos os campos, utilizei o apelido dado à entidade.

Dessa forma, poderemos inclusive fazer joins quando necessário. No próximo artigo vou escrever sobre o relacionamento de entidades. Vamos gerar a entidade “endereco” e por fim faremos uma busca com join entre as tabelas para mostrar o poder da DQL.

Conclusão

O Doctrine nos dá muita rapidez no desenvolvimento – isso será percebido mais ainda no próximo artigo, quando eu mostrar os relacionamentos entre entidades e a facilidade de acesso aos dados.

Existem outras forma de fazer busca no Doctrine, mas espero que com essas que apresentei aqui, seja possível você começar a entender melhor como ele funciona e partir para novas implementações. Os arquivos do artigo estão disponíveis aqui.

No próximo artigo irei abordar o relacionamento entre entidades.

Espero que esse artigo possa ajudar vocês. Um abraço e até o próximo!

é formado em Engenharia Elétrica e pós-graduado em Análise de Sistemas, ambos pelo Mackenzie. Trabalha desde 2007 como desenvolvedor web, com conhecimentos em PHP, MySQL, SQLServer, jQuery, CSS. Atualmente também desenvolve aplicativos Android.

Mais de Ricardo Mendes
Ver perfil →