Padrão de Codificação do Zend Framework para PHPVisão geralEscopo
Este documento fornece instruções para formatação e documentação de código a
indivíduos e times que contribuem com o Zend Framework. Muitos desenvolvedores que
utilizam o Zend Framework acham que estes padrões são igualmente importantes para
que seu estilo de codificação permaneça consistente com todo o código do Framework.
Vale também notar que é necessário esforço significativo para especificar padrões de
codificação por completo.
Por vezes, desenvolvedores consideram o estabelecimento de um padrão mais
importante do que o padrão sugere de verdade ao nível mais detalhado de design.
As instruções nos padrões de codificação do Zend Framework absorvem práticas que
funcionaram bem no projeto do Framework. Você pode alterar tais padrões ou
usá-los "as is" de acordo com os termos de nossa licença.
Os tópicos abordados nos padrões de codificação do Zend Framework incluem:
Formatação de arquivos PHPConvenções de nomenclaturaEstilo de codificaçãoDocumentação em linha de códigoObjetivos
Padrões de codificação são importantes em qualquer projeto de desenvolvimento, mas
são particularmente importantes quando muitos desenvolvedores estão trabalhando no
mesmo projeto. Eles ajudam a garantir que o código possua alta qualidade, poucos
bugs e possam ser facilmente mantidos.
Formatação de Arquivos PHPGeral
Para arquivos que contenham somente código PHP, a tag de
fechamento ("?>") nunca é permitida. Ela não é exigida pelo PHP e
omiti-la previne a injeção acidental de espaços em branco desnecessários na
resposta.
Importante: A inclusão de dados binários arbitrários, como
permitido pela função __HALT_COMPILER(), é proibida a
partir de arquivos PHP no projeto Zend Framework ou de
arquivos derivados deles. O uso deste recurso é permitido somente para alguns
scripts de instalação.
IndentaçãoA indentação deve consistir de 4 espaços. Tabulações não são permitidas.Comprimento máximo de linha
O comprimento desejável das linhas é 80 caracteres. Isto significa que
desenvolvedores do Zend Framework devem se esforçar para manter cada linha de seus
códigos com menos que 80 caracteres onde possível e prático. Entretanto, linhas
maiores são aceitáveis em algumas circunstâncias. O comprimento máximo de qualquer
linha de código PHP é 120 caracteres.
Quebra de linha
Quebras de linha seguem a convenção de arquivos de texto Unix. As linhas devem
terminar com um único caractere de quebra -- linefeed (LF). Caracteres de quebra são
representados como ordinal 10 ou hexadecimal 0x0A.
Nota: Não use retornos -- carriage returns (CR) -- como é a convenção em arquivos
dos sistemas Apple (0x0D) ou a combinação de retorno e quebra
(CRLF), como é o padrão dos sistemas Windows (0x0D, 0x0A).
Convenções de NomenclaturaClasses
O Zend Framework utiliza um padrão de nomes de classes de forma que os nomes das
classes mapeiam diretamente os diretórios onde estão armazenadas. O diretório raiz
da biblioteca padrão do Zend Framework é o diretório "Zend/" e o diretório raiz da
biblioteca de extras é "ZendX/". Todas as classes do Zend Framework são armazenadas
hierarquicamente sob tais diretórios.
Nomes de classes devem conter somente caracteres alfanuméricos. Números são
permitidos em nomes de classes mas são desencorajados na maioria dos casos.
Underscores são permitidos somente no lugar de separador de diretórios. O arquivo
"Zend/Db/Table.php", por exemplo, deve mapear a classe de nome
"Zend_Db_Table".
Se um nome de classe é composto de mais de uma palavra, a primeira letra de cada
nova palavra deve ser maiúscula. Letras maiúsculas em sequência não são permitidas.
A classe "Zend_PDF", por exemplo, não é permitida, enquanto
"Zend_Pdf" é.
Estas convenções definem um mecanismo de pseudonamespace para o Framework. O Zend
Framework irá adotar o recurso de namespace do PHP assim que ele
se tornar disponível e prático para nossos desenvolvedores os utilizarem em suas
aplicações.
Exemplos desta convenção de nomenclatura podem ser vistos em nomes de classes nas
bibliotecas padrão e de extras.
Importante: Códigos que devem ser disponibilizados junto às
bibliotecas do Zend Framework mas não são parte das bibliotecas padrão ou de
extras (por exemplo, código de aplicação ou bibliotecas que não são distribuídas
pela Zend) nunca devem iniciar com "Zend_" ou "ZendX_".
Classes abstratas
Em geral, classes abstratas seguem as mesmas convenções de classes, com uma
regra adicional: nomes de classes abstratas devem terminar com o termo "Abstract",
que não pode ser precedido por um underscore. Por exemplo,
Zend_Controller_Plugin_Abstract é considerado um nome
inválido, mas Zend_Controller_PluginAbstract ou
Zend_Controller_Plugin_PluginAbstract seriam nomes válidos.
Esta convenção de codificação é nova na versão 1.9.0 do Zend Framework. Classes
de datas anteriores a esta versão podem não seguir esta regra mas serão
renomeadas no futuro a fim de obedecê-la.
A razão de tal mudança é o uso de namespace. Como pretendemos que o Zend
Framework 2.0 utilize PHP 5.3, utilizaremos namespaces. A
maneira mais fácil de automatizar a conversão para namespaces é simplemente
converter underscores para o separador de namespace -- mas sob as antigas
convenções de nomenclatura isto deixa o nome da classe como somente "Abstract"
ou "Interface" -- as quais são palavras-chave reservadas em
PHP. Se prefixarmos o nome do (sub)componente ao nome da
classe, podemos evitar tais problemas.
Para ilustrar a situação, considere converter a classe
Zend_Controller_Request_Abstract para utilizar
namespaces:
Claramente isto não irá funcionar. Sob as novas convenções de nomenclatura,
entretanto, isso se tornaria:
Ainda retemos a semântica e a separação de namespace enquanto omitimos os
problemas com palavras-chave; ao mesmo tempo, a classe abstrata é melhor
descrita.
Interfaces
Em geral, interfaces seguem as mesmas convenções de classes, com uma
regra adicional: nomes de interface podem opcionalmente terminar com o termo
"Interface", que não pode ser precedido por um underscore. Por exemplo,
Zend_Controller_Plugin_Interface é considerado um nome
inválido, mas Zend_Controller_PluginInterface ou
Zend_Controller_Plugin_PluginInterface seriam nomes válidos.
Embora esta regra não seja obrigatória, ela é fortemente recomendada, já que provê
uma boa pista visual aos desenvolvedores sobre quais arquivos contém interfaces em
vez de classes.
Esta convenção de nomenclatura é nova na versão 1.9.0 do Zend Framework. Classes
de datas anteriores a esta versão podem não seguir esta regra, mas serão
renomeadas no futuro a fim de obedecê-la. Veja a seção
anterior para informações sobre a razão da mudança.
Nomes de arquivos
Para todos os outros arquivos, somente caracteres alfanuméricos, underscores e
hifens são permitidos. Espaços são estritamente proibidos.
Qualquer arquivo que contenha código PHP deve terminar com a
extensão ".php", com a notável exceção de scripts de view. Os
exemplos a seguir mostram nomes de arquivo aceitáveis para classes do Zend
Framework:
Nomes de arquivos devem mapear nomes de classes, como descrito acima.
Funções e métodos
Nomes de funções devem conter somente caracteres alfanuméricos, não sendo
underscores permitidos. Números são permitidos mas desencorajados na maioria dos
casos.
Nomes de funções devem sempre começar com letra minúscula e, quando consistir de
mais de uma palavra, a primeira letra de cada palavra deve ser maiúscula. Esta
formatação é comumente chamada de "camelCase".
A utilização de verbos é geralmente encorajada, devendo os nomes de funções ser tão
verbais quanto prático a fim de descrever de forma clara seu propósito e
comportamento.
Estes são exemplos de nomes aceitáveis de funções:
Para programação orientada a objetos, acessores de variáveis estáticas ou de
instância devem sempre ser prefixados com "get" ou "set". Ao implementar padrões de
design (“design patterns”), como o singleton ou o factory, o nome do método deve
conter o nome do padrão onde prático a fim de descrever claramente seu
comportamento.
Para métodos de objetos que são declarados com o modificador "private" ou
"protected", o primeiro caractere do nome do método deve ser um underscore. Esta é a
única aplicação aceitável de um underscore em um nome de método. Métodos declarados
como "public" nunca devem conter um underscore.
Funções em escopo global (também chamadas de "funções flutuantes") são permitidas
mas desencorajadas na maioria dos casos. Considere encapsular estas funções em uma
classe estática.
Variáveis
Nomes de variáveis devem conter somente caracteres alfanuméricos, não sendo
underscores permitidos. Números são permitidos mas são desencorajados na maioria dos
casos.
Para variáveis de instância declaradas com o modificador "private" ou "protected", o
primeiro caractere do nome da variável deve ser um underscore. Esta é a única
aplicação aceitável de um underscore em nome de variável. Variáveis-membras
declaradas com "public" nunca devem começar com um underscore.
Assim como nomes de funções (veja seção 3.3), nomes de variáveis devem sempre
começar com uma letra minúscula e seguir a convenção "camelCase".
A utilização de verbos é encorajada, ou seja, variáveis devem sempre ser tão verbais
quanto prático para descrever os dados que o desenvolvedor pretende armazenar nelas.
Nomes concisos de variáveis como "$i" e "$n"
são desencorajados para todos os contextos de laço, exceto os menores. Se um loop
contém mais de 20 linhas de código então as variáveis de índice devem ter nomes mais
descritivos.
Constantes
Constantes devem conter tanto caracteres alfanuméricos quanto underscores. Números
são permitidos.
Todas as letras usadas em um nome de constante devem ser maiúsculas, enquanto todas
as palavras devem ser separadas por underscores.
Por exemplo, EMBED_SUPPRESS_EMBED_EXCEPTION é permitido
enquanto EMBED_SUPPRESSEMBEDEXCEPTION não.
Constantes devem ser definidas como membras de classe com o modificador "const".
Definir constantes em escopo global com a função "define" é permitido mas fortemente
desencorajado.
Estilo de CodificaçãoDemarcação de código PHP
Código PHP deve sempre ser delimitado pelas tags na forma
completa, padrão do PHP:
]]>
Tags reduzidas nunca não permitidas. Para arquivos que contenham somente código
PHP, a tag de fechamento deve sempre ser omitida (veja a seção Geral).
StringsStrings literais
Quando uma string é literal (não contém substituição de variáveis), o apóstrofo
ou "aspa simples" deve sempre ser utilizado para demarcar a string:
Strings literais contendo apóstrofos
Quando uma string literal em si contém apóstrofos, é permitido demarcar a string
com aspas ou "aspas duplas". Isto é especialmente útil para sentenças
SQL:
Esta sintaxe é preferível a escapar os apóstrofos uma vez que é muito mais
legível.
Substituição de variáveis
A substituição de variáveis é permitida utilizando qualquer uma destas formas:
Por consistência, esta forma não é permitida:
Concatenação de strings
Strings devem ser concatenadas utilizando o operador ".". Um espaço deve sempre
ser adicionado antes e depois do operador "." para melhorar a legibilidade:
Ao concatenar strings com o operador "." encoraja-se quebrar a expressão em
múltiplas linhas para facilitar a leitura. Nestes casos, cada linha sucessiva
deve ser indentada com espaços em branco de forma que o operador "." fique
alinhado com o operador "=":
ArraysArrays numericamente indexadosNúmeros negativos não são permitidos como índices.
Um array indexado deve iniciar com um número não-negativo. Entretanto, índices
iniciados em números diferentes de 0 são desencorajados.
Ao declarar arrays indexados com a função Array, um espaço deve ser
adicionado após cada vírgula delimitadora para aumentar a legibilidade:
É permitido declarar arrays indexados em várias linhas utilizando o construtor
"array". Neste caso, cada linha sucessiva deve ser indentada com espaços de
forma que o começo de cada linha fique alinhado:
Alternativamente, o item inicial do array pode começar na linha seguinte. Neste
caso, ele deve ser indentado em um nível a mais que a linha que contém a
declaração do array e todas as linhas sucessivas devem ter a mesma indentação. O
parêntese de fechamento deve estar em uma linha a parte no mesmo nível de
indentação da linha que contém a declaração do array:
Ao usar esta última declaração, encorajamos utilizar uma vírgula após o último
item do array. Isto minimiza o impacto de adicionar novos itens em linhas
sucessivas e ajuda a garantir que nenhum erro ocorra devido à ausência de uma
vírgula.
Arrays associativos
Ao declarar arrays associativos com o construtor Array, encoraja-se
quebrar a expressão em várias linhas. Neste caso, cada linha sucessiva deve ser
indentada com espaços em branco de forma que as chaves e os valores fiquem
alinhados:
'firstValue',
'secondKey' => 'secondValue');
]]>
Alternativamente, o item inicial do array pode começar na linha seguinte. Neste
caso, ele deve ser indentado a um nível a mais que a linha contendo a declaração
do array e todas as linhas sucessivas devem ter a mesma indentação. O parêntese
de fechamento deve estar em uma linha própria, no mesmo nível de indentação da
linha que contém a declaração do array. Para legibilidade, os vários operadores
de atribuição "=>" devem ser espaçados de forma a ficarem alinhados.
'firstValue',
'secondKey' => 'secondValue',
);
]]>
Ao utilizar esta última declaração, encorajamos utilizar uma vírgula após o
último item do array; isto minimiza o impacto de adicionar novos itens em linhas
sucessivas e ajuda a garantir que nenhum erro ocorra devido à ausência de uma
vírgula.
ClassesDeclaração de classe
Classes devem ser nomeadas de acordo com a convenção de nomenclatura do Zend
Framework.
A chave deve ser sempre escrita na linha abaixo do nome da classe.
Toda classe deve ter um bloco de documentação em conformidade ao padrão do
PHPDocumentor.
Todo código em uma classe deve ser indentado com quatro espaços.
Apenas uma única classe é permitida em cada arquivo PHP.
A inserção de código adicional em arquivos de classe é permitida, mas
desencorajada. Em tais arquivos, duas linhas em branco devem separar a classe de
qualquer código PHP no arquivo.
A seguir, um exemplo de declaração de classe aceitável:
Classes que estendem outras classes ou que implementam interfaces devem declarar
suas dependências na mesma linha, quando possível.
Se estas operações fizerem com que o comprimento da linha exceda o comprimento
máximo, quebre a linha antes das palavras-chave "extends" e/ou
"implements", e indente tais linhas em mais um nível.
Se a classe implementa múltiplas interfaces e a declaração excede o comprimento
máximo da linha, quebre após cada interface separada por vírgula e indente os
nomes das interfaces de forma a ficarem alinhados.
Variáveis membras de classes
Variáveis-membras devem ser nomeadas de acordo com as convenções de nomenclatura
de variáveis do Zend Framework.
Quaisquer variáveis declaradas em uma classe devem ser listadas no topo da
classe, acima da declaração de quaisquer métodos.
O construtor var não é permitido. Variáveis-membras devem
sempre declarar sua visibilidade usando um dos modificadores
private, protected ou
public. Dar acesso direto a variáveis-membras declarando-as
como públicas é permitido mas desencorajado. Em vez disso, utilize métodos
acessores (set e get).
Funções e métodosDeclaração de funções e métodos
Funções devem ser nomeadas de acordo com as convenções de nomenclatura do Zend
Framework.
Métodos dentro de classes devem sempre declarar sua visibilidade usando um dos
modificadores private, protected ou
public.
Assim como ocorre com classes, a chave deve sempre ser escrita na linha abaixo
do nome da função. Espaços entre o nome da função e o parêntese de abertura para
os argumentos não são permitidos.
Funções em escopo global são fortemente desencorajadas.
A seguir, um exemplo de declaração aceitável de função em uma classe:
Quando a lista de argumentos exceder o comprimento
máximo de linha você pode introduzir quebras de linha. Argumentos
adicionais à função/método devem ser identados um nível a mais que o da
declaração da função/método. Uma quebra de linha deve ser colocada antes do
parêntese de fechamento de argumentos, que deve então ser colocado na mesma
linha da chave de abertura da função/método com uma espaço separando os dois, e
no mesmo nível de identação da declaração da função/método. A seguir, um exemplo
de tal situação:
O único mecanismo de passagem de parâmetro permitido em uma declaração de
método é a passagem por referência.
Passagem por referência em tempo de chamada é estritamente proibido.
O valor de retorno não deve ser cercado por parênteses. Isto pode embaraçar a
legibilidade, além de quebrar o código caso um método seja modificado
posteriormente para retornar por referência.
bar);
}
/**
* CERTO
*/
public function bar()
{
return $this->bar;
}
}
]]>Uso de funções e métodos
Argumentos de funções devem ser separados por um único espaço após a vírgula
delimitadora. A seguir, um exemplo de chamada aceitável de função que utiliza
três argumentos:
Passagem por referência em tempo de chamada é estritamente proibido. Veja na
seção de declaração de funções a maneira apropriada de passar argumentos de
função por referência.
Ao passar arrays como argumentos para uma função, a chamada da função pode
incluir a indicação "array" e pode ser quebrada em múltiplas linhas para
aumentar a legibilidade. Em tais casos, as instruções para a escrita de arrays
ainda se aplicam:
Expressões de controleIf/Else/Elseif
Expressões de controle baseadas nos construtores if e
elseif devem ter um único espaço antes do parêntese de
abertura do condicional e um único espaço depois do parêntese de fechamento.
Dentro das expressões condicionais entre os parênteses, os operadores devem ser
separados por espaços para maior legibilidade. Parênteses aninhados são
encorajados a fim de melhorar o agrupamento lógico de expressões condicionais
maiores.
A chave de abertura deve ser escrita na mesma linha da expressão condicional,
enquanto a chave de fechamento deve sempre ser escrita na sua própria linha.
Qualquer conteúdo dentro das chaves deve ser indentado utilizando quatro
espaços.
Se a expressão condicional fizer com que a linha exceda o comprimento
máximo e possuir várias cláusulas você pode quebrar a condicional em
várias linhas. Em tais casos, quebre a linha antes de um operador lógico e
indente a linha de forma a ficar alinhada abaixo do primeiro caractere da
cláusula condicional. O parêntese de fechamento no condicional será então
colocado em uma linha junto à chave de abertura com um espaço separando os dois,
em um nível de indentação equivalente ao da expressão de controle de abertura.
A intenção deste último formato de declaração é prevenir problemas ao adicionar
ou remover cláusulas da condicional durante revisões posteriores.
Para expressões "if" que incluem "elseif" ou "else", as convenções de formatação
são similares às do construtor "if". Os exemplos a seguir demonstram a
formatação apropriada para expressões "if" com construtores "else" e/ou
"elseif":
O PHP permite que expressões sejam escritas sem chaves em
algumas circunstâncias. Este padrão de codificação, no entando, não faz
diferenciação alguma -- todas expressões "if", "elseif" ou "else" devem utilizar
chaves.
Switch
Expressões de controle escritas com a expressão "switch" devem ter um único
espaço antes do parêntese de abertura da expressão condicional e após o
parêntese de fechamento.
Todo o conteúdo dentro da expressão "switch" deve ser indentado utilizando
quatro espaços e o conteúdo abaixo de cada expressão "case" deve ser indentado
utilizando quatro espaços adicionais.
O construtor default nunca deve ser omitido de uma
expressão switch.
Em alguns casos é útil escrever uma expressão case que
recai sobre a próxima omitindo um break ou
return. Para diferenciar tais casos de bugs, qualquer
expressão case onde o break ou o
return sejam omitidos devem conter um comentário
indicando que a quebra foi intencionalmente omitida.
Documentação em linha de códigoFormato de documentação
Todos blocos de documentação ("docblocks") devem ser compatíveis com o formato
phpDocumentor. Descrever o formato phpDocumentor está além do escopo deste
documento. Para mais informações, visite: http://phpdoc.org/
Todo arquivo de classe deve conter um docblock em nível de arquivo no topo de
cada arquivo e um docblock em nível de classe imediatamente acima da classe.
Exemplos de tais docblocks podem ser vistos abaixo.
Arquivos
Todo arquivo que contém código PHP deve ter um docblock no
topo do arquivo contendo no mínimo estas tags do phpDocumentor:
A anotação @category deve ter o valor "Zend".
A anotação @package deve ser utilizada e deve ser
equivalente ao nome do componente da classe contida no arquivo. Tipicamente, o
nome do componente possuirá apenas dois segmentos, o prefixo "Zend" e o nome do
componente.
A anotação @subpackage é opcional. Caso informada, deve ser
o nome do subcomponente menos o prefixo da classe. No exemplo acima, assume-se
que a classe no arquivo ou é "Zend_Magic_Wand" ou utiliza
tal nome de classe como parte de seu prefixo.
Classes
Toda classe deve ter um docblock que contenha no mínimo estas tags do
phpDocumentor:
A anotação @category deve ter o valor "Zend".
A anotação @package deve ser informada e deve ser
equivalente ao componente a que a classe pertence; tipicamente, terá apenas dois
segmentos: o prefixo "Zend" e o nome do componente.
A anotação @subpackage é opcional. Caso informada, deve ser
o nome do subcomponente menos o prefixo da classe. No exemplo acima, assume-se
que a classe descrita ou é "Zend_Magic_Wand" ou utiliza
este nome como parte do seu prefixo.
Funções
Toda função, incluindo métodos de objetos, deve possuir um docblock que contenha
no mínimo:
Uma descrição da funçãoTodos os argumentosTodos os possíveis valores de retorno
Não é necessário utilizar a tag "@access" já que o nível de acesso é conhecido
através do modificador "public", "private" ou "protected" utilizado na
declaração.
Se uma função ou método pode disparar uma exceção, utilize @throws para todas as
classes de exceção: