Nícolas 4 Denunciar post Postado Abril 9, 2010 Bom pessoal, seguinte. A um bom tempo trabalho com classes, e já fiz até mesmo sistemas complexos com elas e tudo mais. Mas agora minha dúvida é a seguinte, estou criando um projeto na empresa que trabalho que será um dos maiores e mais complexos que já fiz. No momento estou programando sozinho mas a idéia é que futuramente haja uma equipe aqui, e como o sistema que estou criando será um novo serviço que a empresa que trabalho irá comercializar, quero fazer tudo da forma mais organizada possível para facilitar o entendimento de até mesmo futuros integrantes da equipe. No inicio eu ia desenvolver em CakePHP, estava estudando ele e tudo mais, peguei bem o conceito e a idéia mas na prática a dificuldade para lidar com novos comandos com o prazo que tenho me fizeram optar em voltar para o "PHP cru". Minha dúvida é a seguinte, no CakePHP vi uma coisa que achei muito interessante. A forma com que tudo ficava organizado pelas classes serem estanciadas em variaveis que podem ser chamadas de qualquer lugar da aplicação. Ou seja. Função Link na Class HTML era chamada dessa forma em qualquer local da aplicação. $html->link() Eu gostei da forma com que ficou tudo organizado para fazer o uso das funções criadas. Eu gostaria de fazer isso no sistema que estou gerando. Então criei uma Class chamada Configurações e instanciei ela assim na minha index. (Obs: estou utilizando a função __autoload) $config = new Configuracoes(); Dentro da index eu consigo chamar as funções dela. Exemplo: $config->erros(); Agora dentro de outras classes e includes ele não executa. A forma que sempre fazia era usando o extends das classes, então tudo ficava dentro de $this Exemplo: $this->erros(); Todo o lugar era this, this, this as vezes tinha que deixar funções com nomes diferentes do que eu queria para não conflitar com outra de outra classe. As duas únicas formas que encontrei para fazer isso foram. Declarando as classes novamente em cada função. $config = new Configuracoes(); Ou utilizando a variavel global, que das duas opções é a melhor mais ainda assim tem que ser usada dentro de cada função que eu precisar chamar a variavel. O que acaba sendo muito chato além de poluir o código. global $config; Alguém conhece alguma forma de fazer isso de forma automatizada (como o autoload) ou mais simples? Porque dessa forma pra mim não está compensando. Vlw a atenção. To no aguardo, até mais. Compartilhar este post Link para o post Compartilhar em outros sites
Evandro Oliveira 331 Denunciar post Postado Abril 9, 2010 você pode definir classes estáticas ou se utilizar do padrão de design 'Singleton' class MySQLConnection { private static $hostname; private static $username; private static $password; private static $database; private static $connection; public static function start(array $config = null){ if(!empty($config)) foreach($config as $param=>$value) self::setParam($param,$value); } static function setParam($param,$value){ if(isset(self::$param)) self::$param = $value; } public static function connect(){ self::$connection = mysql_connect(self::$hostname,self::$username,self::$password); if(!self::$connection) die(mysql_error()); $db = mysql_select_db(self::$database,self::$connection); if(!$db) die(mysql_error()); return self::$connection; } public static function stop(){ mysql_close(self::$connection); self::$connection = null; } } Manipulações estáticas interferem diretamente na classe, e não nas instâncias da mesma, como a classe é uma só, os atributos se tornam globais $config = array( 'hostname'=>'localhost', 'username'=>'root', 'password'=>'', 'database'=>'mysql' ); MySQLConnection::start($config); $link_resource = MySQLConnection::connect(); mysql_query('select * from `tabela`',$link_resource); Existe ainda uma outra maneira que é utilizando-se de Singleton Bolei aqui uma espécie de superclasse que combina Singleton com Registry: class Singleton { private static $instances = array(); private final __construct(){} // impedimos as classes herdeiras de serem instanciadas via new $classname; public final start(){ $classname = get_called_class(); if(!isset(self::$instances[$classname])) self::$instances[$classname] = new $classname; return $classname; } } sempre que quiser uma classe 'global', basta extendê-la a partir da Singleton class MySQLConnection extends Singleton { private $conn; public function connect(){ if(empty($conn)) { $conn = mysql_connect('localhost','root',''); if(!$conn) die(mysql_error()); $db = mysql_select_db('mysql',$conn); if(!$db) die(mysql_error()); $this->conn = $conn; } return $this->conn; } } você pode instanciar a classe várias vezes em várias variáveis diferentes, mas elas sempre alterarão o mesmo parâmetro: $mysql1 = MySQLConnection::start(); $conn1 = $mysql1->connect(); $mysql2 = MySQLConnection::start(); $conn2 = $mysql2->connect(); var_dump($conn1 === $conn2); // (bool)true Óbviamente que os pedaços de código acima são meramente ilustrativos e devem ser adaptados de maneira correta e coerente às suas aplicações ;) Compartilhar este post Link para o post Compartilhar em outros sites
João Batista Neto 448 Denunciar post Postado Abril 10, 2010 class Singleton { } class MySQLConnection extends Singleton { } http://forum.imasters.com.br/public/style_emoticons/default/joia.gif Interessante, só um detalhe que poderá fazer seu Singleton ficar ainda mais legal... Algumas vezes, precisamos configurar algumas coisas no ato da criação da instância do objeto, utilizando seu Singleton basta que criemos uma interface IConfigurable e verifiquemos no construtor do seu Singleton: Se a classe que será instanciada implementa essa interface, chamemos o método configure: <?php interface IConfigurable { public function configure( $argc , array $argv ); } abstract class Singleton { private static $instances; private function __construct( $argc = 0 , array $argv ){ self::$instances = array(); if ( in_array( 'IConfigurable' , class_implements( get_class( $this ) , false ) ) ){ $this->configure( $argc , $argv ); } } public static function getInstance(){ $class = get_called_class(); if ( !isset( self::$instances[ $class ] ) ){ $argc = func_num_args(); $argv = func_get_args(); self::$instances[ $class ] = new $class( $argc , $argv ); } return self::$instances[ $class ]; } } final class MyConfigurableSingleton extends Singleton implements IConfigurable { public function configure( $argc , array $argv ){ printf( "%s( %s ) foi chamado.\n" , __METHOD__ , implode( ' , ' , $argv ) ); } } final class MySimpleSingleton extends Singleton { } $instance1 = MyConfigurableSingleton::getInstance( 1 , 2 , 3 ); $instance2 = MyConfigurableSingleton::getInstance(); var_dump( $instance1 , $instance2 ); Dessa forma, a MyConfigurableSingleton por implementar IConfigurable, terá seu método configure chamado no ato da instanciação, já a MySimpleSingleton terá o mesmo comportamento que ocorreria da forma como você a escreveu, isso dará a oportunidade do objeto se configurar adequadamente quando uma instância for criada. A saída do fragmento acima será: MyConfigurableSingleton::configure( 1 , 2 , 3 ) foi chamado. object(MyConfigurableSingleton)#1 (0) { } object(MyConfigurableSingleton)#1 (0) { } ;) Compartilhar este post Link para o post Compartilhar em outros sites
Evandro Oliveira 331 Denunciar post Postado Abril 10, 2010 Aprimoração excepcional! Obrigado. Só uma dúvida. Porque zerar $instances dentro de __construct? Se eu quisesse futuramente criar um método Singleton::getInstances() ele me retornaria apenas o último objeto instanciado Compartilhar este post Link para o post Compartilhar em outros sites
Nícolas 4 Denunciar post Postado Abril 14, 2010 Putz pra mim complicou, trabalho com classes, já fiz sistemas, mas nunca me aprofundei em comandos avançados. Alguem sabe um bom tutorial ai pra eu dar uma lida em artigos avançados? Porque isso pra mim foi grego ^^ Mas vlw aee a resposta Compartilhar este post Link para o post Compartilhar em outros sites
João Batista Neto 448 Denunciar post Postado Abril 14, 2010 Só uma dúvida. Porque zerar $instances dentro de __construct? Na verdade, isso foi um equivoco de minha parte, o correto seria: abstract class Singleton { private static $instances; private function __construct( $argc = 0 , array $argv ){ if ( !is_array( self::$instances ) ){ self::$instances = array(); } if ( in_array( 'IConfigurable' , class_implements( get_class( $this ) , false ) ) ){ $this->configure( $argc , $argv ); } } //... } Alguem sabe um bom tutorial ai pra eu dar uma lida em artigos avançados? Nicolas, temos o fórum de Modelagem e Design Patterns onde dúvidas sobre padrões de projeto podem ser tiradas, no mais, trabalhar com classe não significa trabalhar com orientação a objetos. Compartilhar este post Link para o post Compartilhar em outros sites