Ir para conteúdo

POWERED BY:

Arquivado

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

vieira.rrafael

[Resolvido] Apanhando do namespace e autoload

Recommended Posts

<?php

namespace Util;
/* 
* Essa função vai carregar as classes automaticamente
* é chamada pelo php5.3
*/
class AutoLoad {

   function __autoload($class) {
       #require_once($class); #não funciona
       #require_once($class."php"); #não funciona
       #spl_autoload($class); # não funciona
       include_once (\str_replace('\\', '/', $class).'php'); #não funciona
   }

}
?>

<?php

namespace Util;

#use Util\AutoLoad; não funciona
include_once 'AutoLoad.php';

class ConnectionManager extends \Util\AutoLoad {

   static function connect() {
       return new \PDO("mysql:host=localhost;dbname=test", "root", "", array());
   }

   static function disconnect($link = null) {
       $link = null;
   }

}
?>

/*index.php*/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
       <title></title>
   </head>
   <body>
       <?php
       #use Util\ConnectionManager; #não funciona
       include_once 'util/ConnectionManager.php';

       /*essa é a linha 12*/$connection = \Util\ConnectionManager::connect();
       $em = $connection->query("show tables");
       $em->execute();
       var_dump($em->fetchAll(PDO::FETCH_ASSOC));
       \Util\ConnectionManager::disconnect($connection);
       ?>
   </body>
</html>

 

Não sei onde está errado. Se é o namespace que não estou usando corretamente ou se é a função __autoload.

A estrutura das pastas é a seguinte:

 

meu_projeto/
   util/
       AutoLoad.php
       ConnectionManager.php
index.php

 

Quando uso include_once, funciona. Mas isso já é esperado.

Quando não uso include_once, mas sim o use Util\ConnectionManager em index.php,por exemplo, o erro é esse:

Fatal error: Class 'Util\ConnectionManager' not found in caminho\para\o\projeto\meu_projeto\index.php on line 12

A versão que uso do php é 5.3.0

Compartilhar este post


Link para o post
Compartilhar em outros sites

ate onde sei o metodo magico autoload nao funciona dentro de uma classe e sim fora dela, procura a funcao spl_autoload...

Mudei. Ficou assim:

#estrutura
meu_projeto/
   classes/
       util/
           ConnectionManager.php
   autoload.php
   index.php
#fim da estrutura

<?php

include_once '../autoload.php';

namespace Classes\Util;

class ConnectionManager {

   public static function connect() {
       return new PDO("mysql:host=localhost;dbname=test", "root", "", array());
   }

   public static function disconnect($link) {
       $link = null;
   }

}
?>

#index.php
<?php
#com essas linhas, também não funcionou
#set_include_path(get_include_path() . PATH_SEPARATOR . "/classes");
#spl_autoload_register("autoload");

/* linha 2 */use Classes\Util\ConnectionManager;

$link = ConnectionManager::connect();

ConnectionManager::disconnect($link);

?>

#autoload.php
<?php

function __autoload($class) {
   #$class = str_replace("\\", "/", $class); com essa linha, também não funcionou
   require_once ("classes/$class.php");
}
?>

 

O erro agora é Parse error: parse error, unexpected T_STRING, expecting T_CONSTANT_ENCAPSED_STRING or '(' in caminho\para\meu_projeto\meu_projeto\index.php on line 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tudo o que você precisa para ter autoload com suporte à NameSpaces é disso:

 

spl_autoload_register(

   function( $classname ) {

       require_once str_replace( '\\', DIRECTORY_SEPARATOR, $classname ) . '.php';
   }

);

Usar o __autoload() é um literalmente um saco, uma vez que se você, por exemplo, precisar usar algum componente terceirizado que também use esse método mágico, vai dar pau xD.

 

O que não ocorre com spl_autoload_register(), já que pode haver diversos registrados.

 

Observe apenas que esse exemplo é voltado para PHP 5.3, já que usei uma Closure ali. Se for menos que 5.3 (mas ainda 5), basta trocar a Closure por uma chamada de função, valendo das mesmas regras de call_user_func().

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não funcionou? Como?

 

Primeiro: Onde você colocou esse código? Espero que no começo do primeiro arquivo, index.php ou config.php, desde que seja carregado antes de chamar cada classe.

 

Segundo: Essa abordagem sugere que cada barra invertida de um namespace seja convertida num separador de diretório. Isto significa que cada barra invertida será uma nova pasta e o últim termo, o nome da classe.

 

Terceiro: Para usar as classes você tem duas alternativas: Chamar o namespace logo após o operador new ou declarar seu uso antes da classe, com a palavra-chave use:

 

namespace Foo;

use Foo/Bar/Baaz;

class Test {

   public function __construct() {

       $baaz = new \Foo\Bar\Baaz;

       /**
        * É o mesmo que $baaz = new Baaz;
        * já quele foi declarado ali em cima
        */
   }
}

Esse fragmento de código vai buscar a classe Baaz na seguinte estrutura:

 

/Foo/Test.php => Arquivo do fragmento acima
/Foo/Bar/Baaz.php => Classe que estamos declarando

Acontece que, tem um detalhe que, desculpe minha falha, esqueci de comentar.

 

A declaração de namespace vai buscar no include_path que você definiu então, adicionalmente e antes da chamada a spl_autoload_register() você deve, se necessário, modificar o seu include_path adicionando uma entrada a mais:

 

set_include_path( '.'
                        . PATH_SEPARATOR . realpath( '../common' ) . DIRECTORY_SEPARATOR

                        . PATH_SEPARATOR . get_include_path() );

Esse é o meu,de uso particular.

 

Significa que um diretório acima (ou atrás) de onde meu index.php estiver haverá um diretório chamado common onde ficarão todas as bibliotecas do sistema (Zend, Cake, Symofony, Smarty, PEAR ou qualquer coisa que você necessite).

 

No fragmento de exemplo, dentro de common haveria um diretório Foo e assim por diante, para respeitar a estrutura que postei logo acima.

 

Espero que agora ajude.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Atualizei tudo!

A versão do php é 5.3.3.

load/
   classes/
       util/
           ConnectionManager.class.php
   Usuario.class.php
index.php

#index.php
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
       <title></title>
   </head>
   <body>
       <?php
       spl_autoload_register(function ($class) {
                   require_once(str_replace('\\', '/', $class . '.class.php'));
               });

use classes\Usuario;
use classes\util\ConnectionManager;

$connection = new ConnectionManager();
       $usuario = new Usuario();

       var_dump($connection->getConnection());
       var_dump($usuario->getIdade());
       ?>
   </body>
</html>

<?php
namespace classes;

class Usuario{


   function getIdade() {
       return 8;
   }
}

?>

<?php
namespace classes\util;

class ConnectionManager{

   function getConnection() {
       return 'is connected!';
   }

}
?>

#o resultado é
string(13) "is connected!" int(8)

 

Tá resolvido! Valeu pessoal!

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.