portaldacalheta.pt
  • Principal
  • Mundo
  • Europa
  • Ciência De Dados E Bancos De Dados
  • Gerenciamento De Projetos
Tecnologia

Código PHP com erros: os 10 erros mais comuns que os desenvolvedores de PHP cometem



PHP torna relativamente fácil construir um sistema baseado na web, o que é um dos motivos de sua popularidade. Mas apesar de sua facilidade de uso, PHP evoluiu para uma linguagem bastante sofisticada com muitas estruturas, nuances e sutilezas que podem incomodar os desenvolvedores, levando a horas de depuração complicada. Este artigo destaca dez dos erros mais comuns que Desenvolvedores PHP precisa ter cuidado.

Erro comum nº 1: deixar referências de array pendentes após foreach rotações

Não sabe como usar loops foreach em PHP? Usando referências em foreach os loops podem ser úteis se você quiser operar em cada elemento do array sobre o qual está iterando. Por exemplo:



$arr = array(1, 2, 3, 4); foreach ($arr as &$value) { $value = $value * 2; } // $arr is now array(2, 4, 6, 8)

O problema é que, se você não tomar cuidado, isso também pode ter alguns efeitos colaterais e consequências indesejáveis. Especificamente, no exemplo acima, depois que o código é executado, $value permanecerá no escopo e conterá uma referência ao último elemento na matriz. Operações subsequentes envolvendo $value poderia, portanto, involuntariamente acabar modificando o último elemento na matriz.



A principal coisa a lembrar é que foreach não cria um escopo. Portanto, $value no exemplo acima é um referência dentro do escopo superior do script. Em cada iteração foreach define a referência para apontar para o próximo elemento de $array. Após a conclusão do loop, portanto, $value ainda aponta para o último elemento de $array e permanece no escopo.



Aqui está um exemplo do tipo de bug evasivo e confuso que isso pode causar:

$array = [1, 2, 3]; echo implode(',', $array), ' '; foreach ($array as &$value) {} // by reference echo implode(',', $array), ' '; foreach ($array as $value) {} // by value (i.e., copy) echo implode(',', $array), ' ';

O código acima irá gerar o seguinte:



1,2,3 1,2,3 1,2,2

Não, isso não é um erro de digitação. O último valor na última linha é de fato 2, não 3.

Por quê?



Depois de passar pelo primeiro foreach loop, $array permanece inalterado, mas, conforme explicado acima, $value é deixado como uma referência pendente para o último elemento em $array (uma vez que foreach loop acessado $value por referência )

Como resultado, quando passamos pelo segundo foreach loop, “coisas estranhas” parecem acontecer. Especificamente, uma vez que $value agora está sendo acessado por valor (ou seja, por cópia de ), foreach cópias cada sequencial $array elemento em $value em cada etapa do loop. Como resultado, aqui está o que acontece durante cada etapa do segundo foreach ciclo:



  • Passe 1: Cópias $array[0] (ou seja, “1”) em $value (que é uma referência a $array[2]), então $array[2] agora é igual a 1. Portanto, $array agora contém [1, 2, 1].
  • Passe 2: Cópias $array[1] (ou seja, “2”) em $value (que é uma referência a $array[2]), então $array[2] agora é igual a 2. Portanto $array agora contém [1, 2, 2].
  • Passe 3: Cópias $array[2] (que agora é igual a “2”) em $value (que é uma referência a $array[2]), então $array[2] ainda é igual a 2. Portanto, $array agora contém [1, 2, 2].

Para ainda obter o benefício de usar referências em foreach loops sem correr o risco desses tipos de problemas, chame unset() na variável, imediatamente após foreach loop, para remover a referência; por exemplo.:

$arr = array(1, 2, 3, 4); foreach ($arr as &$value) { $value = $value * 2; } unset($value); // $value no longer references $arr[3]

Erro comum nº 2: mal-entendido isset() comportamento

Apesar do nome, isset() não só retorna falso se um item não existe, mas também retorna false para null valores .



Esse comportamento é mais problemático do que pode parecer à primeira vista e é uma fonte comum de problemas.

Considere o seguinte:



$data = fetchRecordFromStorage($storage, $identifier); if (!isset($data['keyShouldBeSet']) { // do something here if 'keyShouldBeSet' is not set }

O autor deste código provavelmente queria verificar se keyShouldBeSet foi definido em $data. Mas, conforme discutido, isset($data['keyShouldBeSet']) vai Além disso retorna falso se $data['keyShouldBeSet'] foi definido, mas foi definido como null. Portanto, a lógica acima é falha.

Aqui está outro exemplo:

if ($_POST['active']) { $postData = extractSomething($_POST); } // ... if (!isset($postData)) { echo 'post not active'; }

O código acima assume que if $_POST['active'] retorna true, então postData será necessariamente definido e, portanto, isset($postData) retornará true. Por outro lado, o código acima assume que o só maneira que isset($postData) retornará false é se $_POST['active'] devolvido false também.

Não.

Conforme explicado, isset($postData) também retornará false if $postData foi definido como null. Portanto é possível para isset($postData) para retornar false mesmo se $_POST['active'] retornado true. Então, novamente, a lógica acima é falha.

E, a propósito, como um ponto lateral, se a intenção no código acima realmente era verificar novamente se $_POST['active'] retornou verdadeiro, contando com isset() pois esta foi uma má decisão de codificação em qualquer caso. Em vez disso, teria sido melhor apenas verificar novamente $_POST['active']; ou seja:

if ($_POST['active']) { $postData = extractSomething($_POST); } // ... if ($_POST['active']) { echo 'post not active'; }

Para casos, porém, onde é importante verificar se uma variável foi realmente definida (ou seja, para distinguir entre uma variável que não foi definida e uma variável que foi definida como null), o array_key_exists() método é uma solução muito mais robusta.

Por exemplo, poderíamos reescrever o primeiro dos dois exemplos acima da seguinte maneira:

melhor lugar para aprender c
$data = fetchRecordFromStorage($storage, $identifier); if (! array_key_exists('keyShouldBeSet', $data)) { // do this if 'keyShouldBeSet' isn't set }

Além disso, combinando array_key_exists() com get_defined_vars() , podemos verificar com segurança se uma variável dentro do escopo atual foi definida ou não:

if (array_key_exists('varShouldBeSet', get_defined_vars())) { // variable $varShouldBeSet exists in current scope }

Erro comum nº 3: confusão sobre retornar por referência vs. por valor

Considere este snippet de código:

class Config { private $values = []; public function getValues() { return $this->values; } } $config = new Config(); $config->getValues()['test'] = 'test'; echo $config->getValues()['test'];

Se você executar o código acima, obterá o seguinte:

PHP Notice: Undefined index: test in /path/to/my/script.php on line 21

O que está errado?

O problema é que o código acima confunde o retorno de arrays por referência com o retorno de arrays por valor. A menos que você diga explicitamente ao PHP para retornar um array por referência (ou seja, usando &), o PHP irá, por padrão, retornar o array “por valor”. Isso significa que um cópia de do array será retornado e, portanto, a função chamada e o chamador não estarão acessando a mesma instância do array.

Portanto, a chamada acima para getValues() retorna um cópia de do $values array em vez de uma referência a ele. Com isso em mente, vamos revisitar as duas linhas principais do exemplo acima:

// getValues() returns a COPY of the $values array, so this adds a 'test' element // to a COPY of the $values array, but not to the $values array itself. $config->getValues()['test'] = 'test'; // getValues() again returns ANOTHER COPY of the $values array, and THIS copy doesn't // contain a 'test' element (which is why we get the 'undefined index' message). echo $config->getValues()['test'];

Uma possível correção seria salvar a primeira cópia do arquivo $values array retornado por getValues() e operar nessa cópia posteriormente; por exemplo.:

$vals = $config->getValues(); $vals['test'] = 'test'; echo $vals['test'];

Esse código funcionará bem (ou seja, ele produzirá test sem gerar nenhuma mensagem de 'índice indefinido'), mas dependendo do que você está tentando realizar, essa abordagem pode ou não ser adequada. Em particular, o código acima não modificará o original $values array. Então, se você Faz deseja que suas modificações (como adicionar um elemento de 'teste') afetem a matriz original, em vez disso, você precisará modificar o getValues() função para retornar um referência para o $values próprio array. Isso é feito adicionando um & antes do nome da função, indicando que deve retornar uma referência; ou seja:

class Config { private $values = []; // return a REFERENCE to the actual $values array public function &getValues() { return $this->values; } } $config = new Config(); $config->getValues()['test'] = 'test'; echo $config->getValues()['test'];

A saída disso será test, conforme esperado.

Mas para tornar as coisas mais confusas, considere, em vez disso, o seguinte snippet de código:

class Config { private $values; // using ArrayObject rather than array public function __construct() { $this->values = new ArrayObject(); } public function getValues() { return $this->values; } } $config = new Config(); $config->getValues()['test'] = 'test'; echo $config->getValues()['test'];

Se você adivinhou que isso resultaria no mesmo erro de “índice indefinido” que nosso anterior array exemplo, você estava errado. De fato, isto o código funcionará bem. A razão é que, ao contrário dos arrays, PHP sempre passa objetos por referência . (ArrayObject é um objeto SPL, que imita totalmente o uso de matrizes, mas funciona como um objeto.)

Como esses exemplos demonstram, nem sempre é totalmente óbvio no PHP se você está lidando com uma cópia ou uma referência. Portanto, é essencial entender esses comportamentos padrão (ou seja, variáveis ​​e arrays são passados ​​por valor; objetos são passados ​​por referência) e também verificar cuidadosamente a documentação da API para a função que você está chamando para ver se ela está retornando um valor, um cópia de uma matriz, uma referência a uma matriz ou uma referência a um objeto.

Dito isso, é importante observar que a prática de retornar uma referência a uma matriz ou a um ArrayObject geralmente é algo que deve ser evitado, pois fornece ao chamador a capacidade de modificar os dados privados da instância. Isso “vai na cara” do encapsulamento. Em vez disso, é melhor usar o estilo antigo 'getters' e 'setters', por exemplo:

class Config { private $values = []; public function setValue($key, $value) { $this->values[$key] = $value; } public function getValue($key) { return $this->values[$key]; } } $config = new Config(); $config->setValue('testKey', 'testValue'); echo $config->getValue('testKey'); // echos 'testValue'

Essa abordagem dá ao chamador a capacidade de definir ou obter qualquer valor na matriz sem fornecer acesso público ao $values próprio array.

Erro comum nº 4: realizar consultas em um loop

Não é incomum encontrar algo assim se o seu PHP não estiver funcionando:

$models = []; foreach ($inputValues as $inputValue) { $models[] = $valueRepository->findByValue($inputValue); }

Embora possa não haver absolutamente nada de errado aqui, mas se você seguir a lógica do código, poderá descobrir que a aparência inocente chama acima para $valueRepository->findByValue() no final das contas resulta em algum tipo de consulta, como:

$result = $connection->query('SELECT `x`,`y` FROM `values` WHERE `value`=' . $inputValue);

Como resultado, cada iteração do loop acima resultaria em uma consulta separada ao banco de dados. Portanto, se, por exemplo, você forneceu uma matriz de 1.000 valores para o loop, ele geraria 1.000 consultas separadas para o recurso! Se tal script for chamado em vários threads, ele pode potencialmente levar o sistema a uma paralisação.

Portanto, é crucial reconhecer quando as consultas estão sendo feitas por seu código e, sempre que possível, reunir os valores e, em seguida, executar uma consulta para buscar todos os resultados.

Um exemplo de um lugar bastante comum para encontrar consultas sendo feitas de forma ineficiente (ou seja, em um loop) é quando um formulário é postado com uma lista de valores (IDs, por exemplo). Em seguida, para recuperar os dados de registro completos de cada um dos IDs, o código percorrerá a matriz e fará uma consulta SQL separada para cada ID. Isso geralmente será algo assim:

$data = []; foreach ($ids as $id) { $result = $connection->query('SELECT `x`, `y` FROM `values` WHERE `id` = ' . $id); $data[] = $result->fetch_row(); }

Mas a mesma coisa pode ser realizada com muito mais eficiência em um solteiro Consulta SQL da seguinte forma:

$data = []; if (count($ids)) { $result = $connection->query('SELECT `x`, `y` FROM `values` WHERE `id` IN (' . implode(',', $ids)); while ($row = $result->fetch_row()) { $data[] = $row; } }

Portanto, é crucial reconhecer quando as consultas estão sendo feitas, direta ou indiretamente, por seu código. Sempre que possível, reúna os valores e execute uma consulta para buscar todos os resultados. Ainda assim, deve-se ter cuidado lá também, o que nos leva ao nosso próximo erro comum de PHP ...

Erro comum nº 5: headfakes e ineficiências no uso de memória

Embora buscar muitos registros de uma vez seja definitivamente mais eficiente do que executar uma única consulta para cada linha a ser buscada, tal abordagem pode potencialmente levar a uma condição de “falta de memória” em libmysqlclient ao usar PHP’s mysql extensão.

Para demonstrar, vamos dar uma olhada em uma caixa de teste com recursos limitados (512 MB de RAM), MySQL e php-cli.

Vamos inicializar uma tabela de banco de dados como esta:

// connect to mysql $connection = new mysqli('localhost', 'username', 'password', 'database'); // create table of 400 columns $query = 'CREATE TABLE `test`(`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT'; for ($col = 0; $col query($query); // write 2 million rows for ($row = 0; $row <2000000; $row++) { $query = 'INSERT INTO `test` VALUES ($row'; for ($col = 0; $col query($query); }

OK, agora vamos verificar o uso de recursos:

como criar um plano de contas
// connect to mysql $connection = new mysqli('localhost', 'username', 'password', 'database'); echo 'Before: ' . memory_get_peak_usage() . ' '; $res = $connection->query('SELECT `x`,`y` FROM `test` LIMIT 1'); echo 'Limit 1: ' . memory_get_peak_usage() . ' '; $res = $connection->query('SELECT `x`,`y` FROM `test` LIMIT 10000'); echo 'Limit 10000: ' . memory_get_peak_usage() . ' ';

Resultado:

Before: 224704 Limit 1: 224704 Limit 10000: 224704

Legal. Parece que a consulta é gerenciada com segurança internamente em termos de recursos.

Só para ter certeza, vamos aumentar o limite mais uma vez e defini-lo para 100.000. Opa. Quando fazemos isso, obtemos:

PHP Warning: mysqli::query(): (HY000/2013): Lost connection to MySQL server during query in /root/test.php on line 11

O que aconteceu?

O problema aqui é a maneira como o PHP mysql módulo funciona. Na verdade, é apenas um proxy para libmysqlclient, que faz o trabalho sujo. Quando uma parte dos dados é selecionada, ela vai diretamente para a memória. Como essa memória não é gerenciada pelo gerente do PHP, memory_get_peak_usage() não mostrará nenhum aumento na utilização de recursos conforme aumentamos o limite em nossa consulta. Isso leva a problemas como o demonstrado acima, em que somos levados à complacência pensando que nosso gerenciamento de memória está bem. Mas, na realidade, nosso gerenciamento de memória apresenta falhas graves e podemos ter problemas como o mostrado acima.

Você pode pelo menos evitar o headfake acima (embora ele não melhore por si só a utilização da memória) usando mysqlnd módulo. mysqlnd é compilado como uma extensão PHP nativa e faz usar o gerenciador de memória do PHP.

Portanto, se executarmos o teste acima usando mysqlnd em vez de mysql, temos uma imagem muito mais realista de nossa utilização de memória:

Before: 232048 Limit 1: 324952 Limit 10000: 32572912

E é ainda pior do que isso, aliás. De acordo com a documentação do PHP, mysql usa o dobro de recursos do que mysqlnd para armazenar dados, então o script original usando mysql realmente usou ainda mais memória do que mostrado aqui (aproximadamente o dobro).

Para evitar tais problemas, considere limitar o tamanho de suas consultas e usar um loop com pequeno número de iterações; por exemplo.:

$totalNumberToFetch = 10000; $portionSize = 100; for ($i = 0; $i query( 'SELECT `x`,`y` FROM `test` LIMIT $limitFrom, $portionSize'); }

Quando consideramos este erro do PHP e erro # 4 acima, percebemos que há um equilíbrio saudável que seu código idealmente precisa atingir entre, por um lado, ter suas consultas muito granulares e repetitivas e ter cada uma de suas consultas individuais muito grande. Como acontece com a maioria das coisas na vida, é necessário equilíbrio; ambos os extremos não são bons e podem causar problemas com o PHP não funcionando corretamente.

Erro comum nº 6: Ignorar problemas Unicode / UTF-8

Em certo sentido, isso é realmente mais um problema no PHP em si do que algo que você enfrentaria ao depurar o PHP, mas nunca foi abordado de forma adequada. O núcleo do PHP 6 deveria ter reconhecimento de Unicode, mas isso foi colocado em espera quando o desenvolvimento do PHP 6 foi suspenso em 2010.

Mas isso de forma alguma isenta o desenvolvedor de manuseando corretamente UTF-8 e evitando a suposição errônea de que todas as strings serão necessariamente “ASCII simples e antigas”. Código que falha em lidar adequadamente com strings não ASCII é notório por apresentar gnarly heisenbugs em seu código. Mesmo simples strlen($_POST['name']) ligações poderiam causar problemas se alguém com um sobrenome como “Schrödinger” tentasse se inscrever em seu sistema.

Aqui está uma pequena lista de verificação para evitar esses problemas em seu código:

  • Se você não sabe muito sobre Unicode e UTF-8, deve pelo menos aprender o básico. Este é um ótimo manual Aqui .
  • Certifique-se de sempre usar o mb_* funções em vez das funções de string antigas (certifique-se de que a extensão “multibyte” esteja incluída em sua construção PHP).
  • Certifique-se de que seu banco de dados e tabelas estejam configurados para usar Unicode (muitas compilações do MySQL ainda usam latin1 por padrão).
  • Lembre-se de que json_encode() converte símbolos não ASCII (por exemplo, “Schrödinger” torna-se “Schr u00f6dinger”), mas serialize() faz não .
  • Certifique-se de que seus arquivos de código PHP também sejam codificados em UTF-8 para evitar colisões ao concatenar strings com constantes de string codificadas ou configuradas.

Um recurso particularmente valioso a esse respeito é o UTF-8 Primer para PHP e MySQL postagem por Francisco claria neste blog.

Erro comum nº 7: presumindo $_POST sempre conterá seus dados POST

Apesar do nome, o $_POST array nem sempre conterá seus dados POST e pode ser facilmente encontrado vazio. Para entender isso, vamos dar uma olhada em um exemplo. Suponha que fazemos uma solicitação de servidor com um jQuery.ajax() ligue da seguinte forma:

// js $.ajax({ url: 'http://my.site/some/path', method: 'post', data: JSON.stringify({a: 'a', b: 'b'}), contentType: 'application/json' });

(A propósito, observe o contentType: 'application/json' aqui. Enviamos dados como JSON, que é bastante popular para APIs. É o padrão, por exemplo, para postar no AngularJS $http serviço .)

No lado do servidor de nosso exemplo, simplesmente despejamos o $_POST array:

// php var_dump($_POST);

Surpreendentemente, o resultado será:

array(0) { }

Por quê? O que aconteceu com nossa string JSON {a: 'a', b: 'b'}?

A resposta é que O PHP só analisa uma carga útil POST automaticamente quando ele tem um tipo de conteúdo de application/x-www-form-urlencoded ou multipart/form-data. As razões para isso são históricas - esses dois tipos de conteúdo eram essencialmente os únicos usados ​​anos atrás quando o PHP $_POST foi implementado. Assim, com qualquer outro tipo de conteúdo (mesmo aqueles que são bastante populares hoje, como application/json), o PHP não carrega automaticamente a carga útil do POST.

Desde $_POST é uma superglobal, se substituirmos uma vez (de preferência no início do nosso script), o valor modificado (ou seja, incluindo a carga útil do POST) será referenciável em todo o nosso código. Isso é importante porque $_POST é comumente usado por estruturas de PHP e quase todos os scripts personalizados para extrair e transformar dados de solicitação.

Portanto, por exemplo, ao processar uma carga útil POST com um tipo de conteúdo de application/json, precisamos analisar manualmente o conteúdo da solicitação (ou seja, decodificar os dados JSON) e substituir o $_POST variável, da seguinte forma:

// php $_POST = json_decode(file_get_contents('php://input'), true);

Então, quando despejamos o $_POST array, vemos que inclui corretamente a carga útil do POST; por exemplo.:

array(2) { ['a']=> string(1) 'a' ['b']=> string(1) 'b' }

Erro comum nº 8: pensar que o PHP suporta um tipo de dados de caractere

Veja este exemplo de código e tente adivinhar o que será impresso:

for ($c = 'a'; $c <= 'z'; $c++) { echo $c . ' '; }

Se você respondeu de 'a' a 'z', pode se surpreender ao saber que estava errado.

Sim, vai imprimir de 'a' a 'z', mas depois Além disso imprima de 'aa' a 'yz'. Vamos ver por quê.

No PHP não há char tipo de dados; apenas string está disponível. Com isso em mente, incrementando o string z em PHP produz aa:

php> $c = 'z'; echo ++$c . ' '; aa

No entanto, para confundir ainda mais as coisas, aa é lexicograficamente Menos do que z:

php> var_export((boolean)('aa' <'z')) . ' '; true

É por isso que o código de amostra apresentado acima imprime as letras a a z, mas então Além disso impressões aa por meio de yz. Ele para quando atinge za, que é o primeiro valor que encontra que é 'maior que' z:

php> var_export((boolean)('za' <'z')) . ' '; false

Sendo esse o caso, aqui está uma maneira de devidamente percorrer os valores ‘a’ a ‘z’ em PHP:

for ($i = ord('a'); $i <= ord('z'); $i++) { echo chr($i) . ' '; }

Ou alternativamente:

$letters = range('a', 'z'); for ($i = 0; $i

Erro comum nº 9: Ignorar os padrões de codificação

Embora ignorar os padrões de codificação não leve diretamente à necessidade de depurar o código PHP, ainda é provavelmente uma das coisas mais importantes para discutir aqui.

Ignorar os padrões de codificação pode causar uma série de problemas em um projeto. Na melhor das hipóteses, resulta em um código inconsistente (já que cada desenvolvedor está “fazendo suas próprias coisas”). Mas, na pior das hipóteses, ele produz código PHP que não funciona ou pode ser difícil (às vezes quase impossível) de navegar, tornando-o extremamente difícil de depurar, aprimorar e manter. E isso significa produtividade reduzida para sua equipe, incluindo muito esforço desperdiçado (ou pelo menos desnecessário).

Felizmente para desenvolvedores de PHP, existe a recomendação de padrões PHP (PSR), composta pelos cinco padrões a seguir:

  • PSR-0 : Padrão de carregamento automático
  • PSR-1 : Padrão Básico de Codificação
  • PSR-2 : Guia de estilo de codificação
  • PSR-3 : Interface do Logger
  • PSR-4 : Autoloader

O PSR foi originalmente criado com base em informações de mantenedores das plataformas mais reconhecidas do mercado. Zend, Drupal, Symfony, Joomla e outras contribuíram para esses padrões e agora os estão seguindo. Até o PEAR, que tentou ser um padrão durante anos antes disso, agora participa do PSR.

Em certo sentido, quase não importa qual é o seu padrão de codificação, contanto que você concorde com um padrão e o cumpra, mas seguir o PSR geralmente é uma boa ideia, a menos que você tenha algum motivo convincente em seu projeto para fazer o contrário . Mais e mais equipes e projetos estão se adaptando ao PSR. Tt é definitivamente reconhecido neste ponto como 'o' padrão pela maioria dos desenvolvedores de PHP, então usá-lo ajudará a garantir que os novos desenvolvedores estejam familiarizados e confortáveis ​​com seu padrão de codificação quando se juntarem à sua equipe.

Erro comum nº 10: Uso incorreto empty()

Alguns desenvolvedores de PHP gostam de usar empty() para verificações booleanas de quase tudo. Existem casos, porém, em que isso pode levar à confusão.

Primeiro, vamos voltar aos arrays e ArrayObject instâncias (que imitam arrays). Dada sua similaridade, é fácil supor que matrizes e ArrayObject as instâncias se comportarão de forma idêntica. Isso prova, no entanto, ser uma suposição perigosa. Por exemplo, no PHP 5.0:

// PHP 5.0 or later: $array = []; var_dump(empty($array)); // outputs bool(true) $array = new ArrayObject(); var_dump(empty($array)); // outputs bool(false) // why don't these both produce the same output?

E para piorar ainda mais as coisas, os resultados teriam sido diferentes antes do PHP 5.0:

// Prior to PHP 5.0: $array = []; var_dump(empty($array)); // outputs bool(false) $array = new ArrayObject(); var_dump(empty($array)); // outputs bool(false)

Infelizmente, essa abordagem é bastante popular. Por exemplo, esta é a maneira ZendDbTableGateway do Zend Framework 2 retorna dados ao chamar current() em TableGateway::select() resultado como o doc sugere. O desenvolvedor pode facilmente se tornar vítima desse erro com esses dados.

Para evitar esses problemas, a melhor abordagem para verificar se há estruturas de matriz vazias é usar count():

// Note that this work in ALL versions of PHP (both pre and post 5.0): $array = []; var_dump(count($array)); // outputs int(0) $array = new ArrayObject(); var_dump(count($array)); // outputs int(0)

E, aliás, uma vez que o PHP lança 0 para false, count() também pode ser usado em if () condições para verificar se há matrizes vazias. Também é importante notar que, em PHP, count() é a complexidade constante (O(1) operação) em matrizes, o que torna ainda mais claro que é a escolha certa.

Outro exemplo quando empty() pode ser perigoso quando combinada com a função de classe mágica __get(). Vamos definir duas classes e ter um test propriedade em ambos.

Primeiro, vamos definir um Regular classe que inclui test como uma propriedade normal:

class Regular { public $test = 'value'; }

Então, vamos definir um Magic classe que usa a magia __get() operador para acessar seu test propriedade:

class Magic { private $values = ['test' => 'value']; public function __get($key) { if (isset($this->values[$key])) { return $this->values[$key]; } } }

OK, agora vamos ver o que acontece quando tentamos acessar o test propriedade de cada uma dessas classes:

$regular = new Regular(); var_dump($regular->test); // outputs string(4) 'value' $magic = new Magic(); var_dump($magic->test); // outputs string(4) 'value'

Tudo bem até agora.

Mas agora vamos ver o que acontece quando chamamos empty() em cada um destes:

var_dump(empty($regular->test)); // outputs bool(false) var_dump(empty($magic->test)); // outputs bool(true)

Ugh. Portanto, se confiarmos em empty(), podemos ser enganados e acreditar que test propriedade de $magic está vazio, enquanto na realidade está definido como 'value'.

Infelizmente, se uma classe usa a magia __get() função para recuperar o valor de uma propriedade, não há maneira infalível de verificar se o valor da propriedade está vazio ou não. Fora do escopo da classe, você só pode realmente verificar se um null valor será retornado, e isso não significa necessariamente que a chave correspondente não esteja definida, pois na verdade poderia têm estado conjunto para null.

inteligência de negócios vs inteligência artificial

Em contraste, se tentarmos fazer referência a uma propriedade não existente de um Regular instância de classe, obteremos um aviso semelhante ao seguinte:

Notice: Undefined property: Regular::$nonExistantTest in /path/to/test.php on line 10 Call Stack: 0.0012 234704 1. {main}() /path/to/test.php:0

Portanto, o ponto principal aqui é que empty() método deve ser usado com cuidado, pois pode levar a resultados confusos - ou mesmo potencialmente enganosos - se não for cuidadoso.

Embrulhar

A facilidade de uso do PHP pode acalmar os desenvolvedores com uma falsa sensação de conforto, deixando-os vulneráveis ​​a longas depurações de PHP devido a algumas das nuances e idiossincrasias da linguagem. Isso pode resultar no não funcionamento do PHP e em problemas como os descritos aqui.

A linguagem PHP evoluiu significativamente ao longo de seus 20 anos de história. Familiarizar-se com suas sutilezas é um esforço que vale a pena, pois ajudará a garantir que o software que você produz é mais escalável, robusto e sustentável.

Os passeios de barco de lava no Havaí continuam após explosões e ferimentos

Mundo

Os passeios de barco de lava no Havaí continuam após explosões e ferimentos
Por que os investidores estão escolhendo modelos de patrocinadores independentes versus fundos PE tradicionais

Por que os investidores estão escolhendo modelos de patrocinadores independentes versus fundos PE tradicionais

Investidores E Financiamento

Publicações Populares
A lista abrangente de conferências Agile
A lista abrangente de conferências Agile
Na noite antes da inauguração, Biden lidera luto pelas vítimas do vírus
Na noite antes da inauguração, Biden lidera luto pelas vítimas do vírus
Documentação do Algoritmo Ruby com AsciiDoc e Knitr
Documentação do Algoritmo Ruby com AsciiDoc e Knitr
Especialista em comunicação
Especialista em comunicação
Um guia de campo para DesignOps
Um guia de campo para DesignOps
 
Página inicial Smart IoT: domesticando a Internet das coisas
Página inicial Smart IoT: domesticando a Internet das coisas
Quanto tempo sua startup pode sobreviver sem um CFO em tempo integral?
Quanto tempo sua startup pode sobreviver sem um CFO em tempo integral?
Um Mergulho Profundo na Aprendizagem por Reforço
Um Mergulho Profundo na Aprendizagem por Reforço
As mulheres deverão usar o hijab, mas não a burca, disse o porta-voz do Talibã
As mulheres deverão usar o hijab, mas não a burca, disse o porta-voz do Talibã
Spring Security com JWT para REST API
Spring Security com JWT para REST API
Publicações Populares
  • como fazer teste de usuário
  • como avaliar uma empresa de biotecnologia
  • qual algoritmo o bitcoin usa
  • análise de sentimento de python de dados do Twitter
  • documento de especificação para desenvolvimento de software
Categorias
  • Mundo
  • Europa
  • Ciência De Dados E Bancos De Dados
  • Gerenciamento De Projetos
  • © 2022 | Todos Os Direitos Reservados

    portaldacalheta.pt