Ir para conteúdo

POWERED BY:

Arquivado

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

Tiago Souza Ribeiro

Criar funções que usam blocos entre chaves

Recommended Posts

Olá. Estou precisando criar uma função (na verdade um método), que tenha uma estrutura parecida com a do if na hora de uso. Estou fazendo uma classe chamada HTMLGenerator, dentro dela tenho os métodos head(), meta()... Quero que ao executar:

$html = new HTMLGenerator;
$html->head() {
$html->meta("Content-Type", "text/html");
$html->meta("Cache-Control", "no-cache");
}

Seja gerado:

<head>
<meta http-equiv="Content-Type" content="text/html" />
<meta http-equiv="Cache-Control" content="no-cache" />
</head>

Podem haver vários outros métodos alí junto dos meta()'s, por isso não quero passar isso como parâmetros da função, mas sim dessa forma que mostrei, pra ficar mais organizado e bonito :D

Porém não sei como fazer funções com blocos entre chaves, mesmo usando OOP. Alguém poderia me ensinar, se possível? :D

 

Até mais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Esse tipo de coisa você tem que fazer na DECLARAÇÃO do método, não quando o invoca... O PHP não permite você definir métodos em tempo de execução...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não, dessa forma que quer fazer é impossível...

 

Você pode fazer algo do tipo:

$html = new HTMLGenerator;
$html->head();
$html->meta("Content-Type", "text/html");
$html->meta("Cache-Control", "no-cache");
$html->endHead();

Onde endHead fecha a tag head...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ah, assim fica meio feio e não é do jeito que eu quero.

Acho que vou passar os meta()'s como parâmetros... é o jeito mais próximo do que eu quero. Agora entendo porque os "Javars" dizem que PHP é movido a arrays '-'

Primeira vez que PHP não pode fazer algo que eu quero :(

 

Obrigado aí, reputado!

Até mais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

O que eu queria fazer é criar uma função, que na hora de usar, pudesse ter a mesma estrutura do if, podendo executar códigos dentro de um bloco de chaves { }.

O problema do que o Henrique sugeriu é que a estrutura não é igual a do if, como eu queria, nem chega perto, aí vou passar os meta()'s como parâmetro do head() mesmo, pois é o jeito mais próximo do que eu queria.

A intensão disso tudo era apenas ter um código bonito e organizado :)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Cara, essa construção que você deseja eu nunca vi em NENHUMA linguagem...

 

A intensão disso tudo era apenas ter um código bonito e organizado

Adicionando chaves ao código vai deixar ele mais bonito??? ahsuhsashua... Não deixem os fãs de Python e Ruby ouvirem isso...

 

Agora entendo porque os "Javars" dizem que PHP é movido a arrays '-'

Isso dá uma longa discussão, mas, realmente, a melhor coisa do PHP são os arrays associativos. Nada de structs ou classes desnecessárias, nem de implementações de um Map.

 

Já vou entrar em outro aspecto aqui: fazendo desse jeito que está querendo, gerando todo o seu HTML com PHP acaba com a performance da sua aplicação.

HTML é código estático, logo, pode ser cacheado. Como o PHP é dinâmico, toda vez que o script rodar, você vai gerar TODO o HTML de novo...

Pra fazer dessa forma aí, vai ter que construir um bom sistema de cache para o HTML gerado...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olha cara, você pode conseguir algo parecido usando a função func_get_args.

 

Exemplo:

<?php

class HTML
{
   public function head( )
   {
       $args = func_get_args( );
       $head = "<head>\n";

       if( ! empty( $args ) )
       {
           foreach( $args as $arg )
           {
               $head .= sprintf( "\t%s\n", $arg );
           }
       }

       $head .= "</head>\n";

       return $head;
   }

   public function meta( $name, $value )
   {
       return sprintf( '<meta http-equiv="%s" content="%s" />', $name, $value );
   }
}

$obj = new HTML( );


echo $obj->head(
           $obj->meta( 'Content-Type', 'text/html' ),
           $obj->meta( 'Cache-Control', 'no-cache' )
       );

?>

 

Saída:

<head>
   <meta http-equiv="Content-Type" content="text/html" />
   <meta http-equiv="Cache-Control" content="no-cache" />
</head>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Cara, essa construção que você deseja eu nunca vi em NENHUMA linguagem...

Seria interessante se houvesse :) Nesse caso meu aí, fica estranho passar as tags internas por parâmetros...

No método para gerar a tag <html> por exemplo, eu pretendia passar parâmetros (lang, dir, xml:lang, xmlns...) como parâmetros da função, num array associativo parâmetro=>valor. Aí passar o que está entre <html> e </html> também como parâmetros seria estranho...

 

Adicionando chaves ao código vai deixar ele mais bonito??? ahsuhsashua... Não deixem os fãs de Python e Ruby ouvirem isso...

Ah, só porque a sintaxe deles é horrível e eles não ligam pra legibilidade, não quer dizer que eu também não vou ligar, kk

 

Já vou entrar em outro aspecto aqui: fazendo desse jeito que está querendo, gerando todo o seu HTML com PHP acaba com a performance da sua aplicação.

HTML é código estático, logo, pode ser cacheado. Como o PHP é dinâmico, toda vez que o script rodar, você vai gerar TODO o HTML de novo...

Pra fazer dessa forma aí, vai ter que construir um bom sistema de cache para o HTML gerado...

Pois é, eu já tenho em mente aqui uma forma de cachear tudo. A intensão de fazer essa classe aí, é para que se eu quiser mudar meu html todo de xhtml pra html5 por exemplo, basta mudar um parâmetro em um método e todo o código é adaptado, bem mais prático :)

 

Olha cara, você pode conseguir algo parecido usando a função func_get_args.

 

Exemplo:

<?php

class HTML
{
   public function head( )
   {
       $args = func_get_args( );
       $head = "<head>\n";

       if( ! empty( $args ) )
       {
           foreach( $args as $arg )
           {
               $head .= sprintf( "\t%s\n", $arg );
           }
       }

       $head .= "</head>\n";

       return $head;
   }

   public function meta( $name, $value )
   {
       return sprintf( '<meta http-equiv="%s" content="%s" />', $name, $value );
   }
}

$obj = new HTML( );


echo $obj->head(
           $obj->meta( 'Content-Type', 'text/html' ),
           $obj->meta( 'Cache-Control', 'no-cache' )
       );

?>

 

Saída:

<head>
   <meta http-equiv="Content-Type" content="text/html" />
   <meta http-equiv="Cache-Control" content="no-cache" />
</head>

 

Pois é, como eu disse lá no post #7, essa aí foi a forma mais próxima do que eu queria, mas ainda não me agrada. Mas vai ser o jeito fazer assim mesmo... Acho que algum ano, década, sei lá que eu tiver bastante tempo livre, vou estudar os fontes do PHP e modificar/implementar ele para ficar como gosto/quero :D

 

Até mais povo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acho que algum ano, década, sei lá que eu tiver bastante tempo livre, vou estudar os fontes do PHP e modificar/implementar ele para ficar como gosto/quero 

 

rsss.. quando você chegar a esse nível perceberá o que está dizendo hoje rssssss

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acho que algum ano, década, sei lá que eu tiver bastante tempo livre, vou estudar os fontes do PHP e modificar/implementar ele para ficar como gosto/quero 

 

rsss.. quando você chegar a esse nível perceberá o que está dizendo hoje rssssss

 

Não entendi.

Acho que eu não soube explicar bem a minha dúvida, aí por não entenderem, concluíram por si sós que eu estava perguntando alguma noobice, kkk

Explica melhor o que tu disse, não entendi e me deixou curioso...

 

Ah, não sei se foi isso que tu quis dizer, mas... eu sei que os fontes do PHP são em C e tudo mais relacionado. Enfim, não entendi o que tu quis dizer.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você conhece a classe DOMDocument? Com ela você consegue gerar HTML a partir do PHP.

 

<?php

$DOMDocument = new DOMDocument( '1.0', 'UTF-8' );
$DOMDocument->formatOutput = true;

$html = $DOMDocument->createElement( 'html' );
$head = $DOMDocument->createElement( 'head' );

$meta_content_type = $DOMDocument->createElement( 'meta' );
$meta_content_type->setAttribute( 'http-equiv', 'Content-Type' );
$meta_content_type->setAttribute( 'content', 'text/html' );

$meta_cache_control = $DOMDocument->createElement( 'meta' );
$meta_cache_control->setAttribute( 'http-equiv', 'Cache-Control' );
$meta_cache_control->setAttribute( 'content', 'no-cache' );


$head->appendChild( $meta_content_type );
$head->appendChild( $meta_cache_control );
$html->appendChild( $head );
$DOMDocument->appendChild( $html );

echo $DOMDocument->saveHTML( );

?>

 

Saída:

<html>
 <head>
   <meta http-equiv="Content-Type" content="text/html">
   <meta http-equiv="Cache-Control" content="no-cache">
 </head>
</html>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você ainda pode trabalhar com Composição de Objetos.

 

Cada metatag possui uma definição única, logo cada uma delas é um objeto diferente todos agregados ao objeto Head.

 

O objeto Head, por ser composto de diferentes elementos possuiria um método para cada agregação e, no caso das metatags, tal método esperaria receber um objeto Meta

 

Por fim, toda tag HTML precisa ser renderizada, logo criamos uma interface que garanta um método de renderização em todas as classes de tags HTML:

 

<?php

interface Tag {

   public function draw();
}

class Meta implements Tag {

   protected $name;
   protected $content;

   public function __construct( $name, $content ) {

       $this -> name    =& $name;
       $this -> content =& $content;
   }

   public function draw() {

       return sprintf(

           "<meta name=\"%s\" content=\"%s\" />\n",

           $this -> name, $this -> content
       );
   }
}

class Head implements Tag {

   private $meta = array();

   public function addMeta( Meta $meta ) {

       $this -> meta[] = $meta;

       return $this;
   }

   public function draw() {

       $meta = NULL;

       array_walk(

           $this -> meta,

           function( $metaTag ) use( &$meta ) {

               $meta .= $metaTag -> draw();
           }
       );

       return $meta;
   }
}

$head = new Head;

$head -> addMeta( new Meta( 'Content-Type', 'text/html' ) )
     -> addMeta( new Meta( 'keywords', 'wikipedia,encyclopedia' ) );

echo $head -> draw();

Saída:

 

<meta name="Content-Type" content="text/html" />
<meta name="keywords" content="wikipedia,encyclopedia" />

Aqui, como só estou ilustrando as metatags, Head::draw() apenas retorna a renderização dessas tags.

 

Em produção, com tags <title>, <script>, <style> e etc. esse método renderizaria tudo e retornaria todo HTML da tag <head>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você conhece a classe DOMDocument? Com ela você consegue gerar HTML a partir do PHP.

 

<?php

$DOMDocument = new DOMDocument( '1.0', 'UTF-8' );
$DOMDocument->formatOutput = true;

$html = $DOMDocument->createElement( 'html' );
$head = $DOMDocument->createElement( 'head' );

$meta_content_type = $DOMDocument->createElement( 'meta' );
$meta_content_type->setAttribute( 'http-equiv', 'Content-Type' );
$meta_content_type->setAttribute( 'content', 'text/html' );

$meta_cache_control = $DOMDocument->createElement( 'meta' );
$meta_cache_control->setAttribute( 'http-equiv', 'Cache-Control' );
$meta_cache_control->setAttribute( 'content', 'no-cache' );


$head->appendChild( $meta_content_type );
$head->appendChild( $meta_cache_control );
$html->appendChild( $head );
$DOMDocument->appendChild( $html );

echo $DOMDocument->saveHTML( );

?>

 

Saída:

<html>
 <head>
   <meta http-equiv="Content-Type" content="text/html">
   <meta http-equiv="Cache-Control" content="no-cache">
 </head>
</html>

Ah, já tinha visto falar dessa classe mas nunca procurei saber nada sobre ela, nem sabia o que ela fazia, hehe. Essa classe tem algum tipo de cache ou otimização nativa pra não ficar gerando o HTML novamente a todo acesso? Se tiver, vou usar ela como back-end da minha classe :D Se não tiver, muito pouco provavelmente vou usá-la, já que como o Henrique falou vou precisar de um bom sistema de cache, e é mais fácil fazer com uma classe que eu mesmo criei :)

 

Você ainda pode trabalhar com Composição de Objetos.

 

Cada metatag possui uma definição única, logo cada uma delas é um objeto diferente todos agregados ao objeto Head.

 

O objeto Head, por ser composto de diferentes elementos possuiria um método para cada agregação e, no caso das metatags, tal método esperaria receber um objeto Meta

 

Por fim, toda tag HTML precisa ser renderizada, logo criamos uma interface que garanta um método de renderização em todas as classes de tags HTML:

 

<?php

interface Tag {

   public function draw();
}

class Meta implements Tag {

   protected $name;
   protected $content;

   public function __construct( $name, $content ) {

       $this -> name    =& $name;
       $this -> content =& $content;
   }

   public function draw() {

       return sprintf(

           "<meta name=\"%s\" content=\"%s\" />\n",

           $this -> name, $this -> content
       );
   }
}

class Head implements Tag {

   private $meta = array();

   public function addMeta( Meta $meta ) {

       $this -> meta[] = $meta;

       return $this;
   }

   public function draw() {

       $meta = NULL;

       array_walk(

           $this -> meta,

           function( $metaTag ) use( &$meta ) {

               $meta .= $metaTag -> draw();
           }
       );

       return $meta;
   }
}

$head = new Head;

$head -> addMeta( new Meta( 'Content-Type', 'text/html' ) )
     -> addMeta( new Meta( 'keywords', 'wikipedia,encyclopedia' ) );

echo $head -> draw();

Saída:

 

<meta name="Content-Type" content="text/html" />
<meta name="keywords" content="wikipedia,encyclopedia" />

Aqui, como só estou ilustrando as metatags, Head::draw() apenas retorna a renderização dessas tags.

 

Em produção, com tags <title>, <script>, <style> e etc. esse método renderizaria tudo e retornaria todo HTML da tag <head>

Legal seu modo. Só não estou acostumado ainda a criar várias classes pra uma coisa só, mas um dia acostumo. O problema é que quero usar isso aí com todas tags html, se possível... acho que vou pegar como exemplo o DOMDocument e usar um método só pra criar qualquer tag senão vão ser muuuuitas classes :s

Vou usar algumas idéias que eu não me lembrava mais e tirei do seu código no meu :)

 

Obrigado aí, até mais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isso é só a pontinha do Composite. ^_^

 

O Padrão mesmo exige alguns cuidados adicionais entre os ramos e as folhas.

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.