MySQL Update Join para Alterar Múltiplas Linhas de uma só vez

// explicit inner join
UPDATE product AS p
INNER JOIN product_price AS pp ON (pp.product_id = p.product_id)
SET pp.old_price = p.current_price,
    p.current_price = pp.base_price * 0.8
WHERE p.created_at < '2021-01-01';

// implicit inner join
UPDATE product AS p, product_price AS pp
SET pp.old_price = p.current_price,
    p.current_price = pp.base_price * 0.8
WHERE pp.product_id = p.product_id
p.created_at < '2021-01-01';

// explicit left join, only left side is updatable
UPDATE product AS p
LEFT JOIN product_price AS pp ON (pp.product_id = p.product_id)
SET p.deleted = 1
WHERE p.created_at < '2021-01-01';

Toda vez que eu estudo um banco de dados novo uma das coisas que sempre busco em todos eles é entender como escrever a sintaxe de um update em massa apenas relacionando tabelas sem a necessidade de laços for ou foreach bastante comuns em Stored Procedures. Esta preferência é porque a performance de uma instrução SQL é amplamente superior a execução de um laço de programação.

Eu peguei esta mania por que quando iniciei na linguagem SQL com banco de dados Informix, este banco de dados possuía uma sintaxe fora de serie para fazer update com dados entre tabelas. A sintaxe era bastante comum e intuitiva que permitia a alteração de diversas colunas e diversas linhas num mesmo comando.

Como o pessoal da MySQL AB também era fora de série eles implementaram uma funcionalidade chamada de Cross Table Update, que nada mais é que um update que permite join com outras tabelas. Resumindo, esta funcionalidade do MySQL preenche com perfeição o comportamento que eu conseguia executar com o Informix.

Outra forma de se fazer update em massa é utilizando-se sub-selects, porém as instruções do update com join são infinitamente mais simples de serem escritas e também a performance com o update join é bem melhor.

E para que não finquem dúvidas sobre a autoria deste recurso, esta funcionalidade foi disponibilizada desde a versão 4.0 do MySQL.

Uma salva de palma pra eles… genial!

PHP Flex Search Encontrando Registros Por Múltiplos Argumentos Numa só Tacada

$inputTextString = 'cano pvc 3mm rosca azul tigre pc';
$baseQuery = 'SELECT * FROM product WHERE 1=1 %s';

$flexQuery = ' %1$s (product.code LIKE \'%%%2$s%%\' OR product.long_desc LIKE \'%%%2$s%%\' OR product.short_desc LIKE \'%%%2$s%%\' OR product.brand LIKE \'%%%2$s%%\' OR product.measure_unit LIKE \'%%%2$s%%\')';
            
$flexWhere = '';
$flexArgs = explode(' ',$inputTextString);
foreach($flexArgs as $flexArg) {
  $flexAnd = empty($flexWhere) ? 'AND(' : 'AND';
  $flexWhere .= vsprintf($flexQuery,[$flexAnd, $flexArg]); 
}

$flexWhere .= empty($flexWhere) ? '' : ')';
$flexSearch = sprintf($baseQuery, $flexWhere);

$conn = mysqli_connect('localhost', 'username', 'password', 'database');
$result = mysqli_query($conn, $flexSearch);

Sabe quando você vai àquele material de construção e o vendedor não consegue achar o produto que você pediu dentro do sistema de vendas? Pois é, que falta de sorte né!

No meu caso eu acho que dei bastante sorte quando iniciei na programação WEB no início dos anos 2000… trabalhando com sistemas eCommerce uma das jóias do nosso aplicativo PHP era a busca de produtos simplesmente informando todas as características para pesquisa num único campo string.

Todas as informações como partes do nome, marca, modelo, dimensões, unidade de medida eram informados num único campo TYPE TEXT simplesmente separando as partes por espaço em branco, o separador universal mais rápido de ser digitado.

Como a técnica não tinha sido nomeada até então eu acabei dando o nome de FLEX SEARCH por que é exatamente isto que este conceito de busca faz, flexibiliza a pesquisa de registros para o operador.. o desenvolvedor que se vire pra fazer o código funcionar.

Observe no código que a busca é flexibilizada ao máximo, pois tentamos encontrar os fragmentos de pesquisa informados não somente na descrição do produto, mas também em outros campos na tabela, e esta busca é feita de forma não obstrutiva, ou seja, a busca tentar encontrar os fragmentos onde for possível mas não requer obrigatoriedade de existência em todos os pontos.

Se você imprimir o conteúdo em $flexSearch você vai encontrar uma query como o SELECT logo abaixo. Então basta simplesmente executar a instrução SQL para obter os registros desejados.

SELECT * FROM product WHERE 1=1  AND( (product.code LIKE '%cano%' OR product.long_desc LIKE '%cano%' OR product.short_desc LIKE '%cano%' OR product.brand LIKE '%cano%' OR product.measure_unit LIKE '%cano%') AND (product.code LIKE '%pvc%' OR product.long_desc LIKE '%pvc%' OR product.short_desc LIKE '%pvc%' OR product.brand LIKE '%pvc%' OR product.measure_unit LIKE '%pvc%') AND (product.code LIKE '%3mm%' OR product.long_desc LIKE '%3mm%' OR product.short_desc LIKE '%3mm%' OR product.brand LIKE '%3mm%' OR product.measure_unit LIKE '%3mm%') AND (product.code LIKE '%rosca%' OR product.long_desc LIKE '%rosca%' OR product.short_desc LIKE '%rosca%' OR product.brand LIKE '%rosca%' OR product.measure_unit LIKE '%rosca%') AND (product.code LIKE '%azul%' OR product.long_desc LIKE '%azul%' OR product.short_desc LIKE '%azul%' OR product.brand LIKE '%azul%' OR product.measure_unit LIKE '%azul%') AND (product.code LIKE '%tigre%' OR product.long_desc LIKE '%tigre%' OR product.short_desc LIKE '%tigre%' OR product.brand LIKE '%tigre%' OR product.measure_unit LIKE '%tigre%') AND (product.code LIKE '%pc%' OR product.long_desc LIKE '%pc%' OR product.short_desc LIKE '%pc%' OR product.brand LIKE '%pc%' OR product.measure_unit LIKE '%pc%'))

Resumindo, a busca só vai falhar se algum fragmento de pesquisa informado não existir em nenhuma das fontes possíveis. O PHP ajuda muito na construção de queries dinâmicas, e este SQL é bastante padrão ANSI e deveria rodar fácil em pelo menos uma dúzia de diferentes bancos de dados.

Da próxima vez que for ao comércio e se deparar com um vendedor em dificuldades, você vai lembrar… vai aí um Flex Search?!!!

SHELL Bash Remover Arquivos Selecionados com Find -exec

find folder -type f -name '*.txt' -exec rm {} +

Para quem tem de lidar com arquivos físicos em sua rotina diária eu tenho certeza de que em algum momento já precisou fazer um eliminação de determinados arquivos, arquivos estes misturados com outros milhares de arquivos, e ainda espalhados por diversos subdiretórios que você nem sequer pudesse imaginar onde estariam.

Bom, não é mais a minha rotina, mas um dia já precisei fazer este tipo de limpeza antes de entregar um deploy; Eu precisei limpar arquivos que não faziam parte do codebase do sistema, arquivos tipo teste e upload… daí bateu aquele frio na espinha!

Dei bastante sorte, numa rápida pesquisa um desses caras legais que ficam escrevendo dicas na internet escreveu um artigo que resolvia exatamente o meu problema. Então, explicando o comando acima:

O comando find vai buscar no diretório folder todos os elementos do tipo arquivo -type f cujo nome faça match com a extensão texto -name ‘*.txt’ e mais que isso, a busca na verdade vai ser processada de forma recursiva descendo até o último nível de diretório existente, já que um nível máximo -maxdepth não foi estipulado.

A remoção dos arquivos encontrados é processada com a opção de executar -exec um comando shell rm para remoção. O sinal de mais + ao final do comando é uma exigência da sintaxe para esta construção.

A mágica na verdade acontece nos brackets {} onde o mesmo é substituído por todas as ocorrências encontradas pelo comando find.

Pronto, sua remoção foi processada de forma limpa e segura!

Você poderia abusar ainda mais das opções de busca, no caso poderia informar as negativas, ou seja, apenas o conjunto de arquivos que não deseja remover.

find folder -type f '!' -name '*.css' '!' -name '*.js' '!' -name '*.php' -exec rm {} +

Segue abaixo uma sketch para montar um ambiente de testes para exercitar os comandos e poder remover os arquivos com segurança.

mkdir folder
mkdir folder/bkp

touch folder/one.txt
touch folder/two.txt
touch folder/three.csv
touch folder/four.txt

cp folder/*.* folder/bkp
touch folder/bkp/six.txt 

Aqui os comandos sem a remoção para você entender o comando find um pouco melhor. Tente variar as combinações de busca para ver o comportamento.

find folder -type f -name '*.txt'

find folder -type f '!' -name '*.css' '!' -name '*.js' '!' -name '*.php'

Agora você já sabe, ao invés de tentar aquele comando cujo nome não pode ser pronunciado (rm -r), agora você conhece uma opção muito mais segura. Se não for usá-la, é por sua conta e risco!

PHP Array Entenda como Obter Vantagens com as Funções Array Prontas

function bestProducts($products, $sales): array {
  $ySalesProducts = explode(' ', $sales);

  $yFiltered = array_filter(
    $ySalesProducts,
    function ($item) use ($products) {
      return in_array($item, $products, true);
    });
 
  $yCount = array_count_values($yFiltered);
  arsort($yCount);
  $ySlice = array_slice($yCount, 0, 2);
  [$first, $second] = array_values($ySlice);

  ($first === $second)
    ? ksort($ySlice)
    : null;

    return $ySlice;
}

$products = [ 'phone', 'mobile', 'game', 'headset', 'hdd', 'ssd' ];
$context = 'phone ssd headset ssd headset mobile headset phone game headset hdd ssd game ssd ssd headset game box box box box box box';

$result = bestProducts($products, $context);
var_dump($result);

Há algum tempo eu estava num desafio de codificação na Plataforma Hacker Rank e apareceu uma questão que usava muitos recursos de ARRAY… pensei comigo, tá no papo! Só que não…

Meu principal erro não foi subestimar o problema, mas sim subestimar a memorização das funções array e o porquê delas existirem. Como de costume, eu sempre recorro as documentações do PHP.net quando estou programando, só que durante uma maratona ou num desafio de programação ter estas funcionalidades prontamente memorizadas faz uma tremenda falta.

Churumelas postas, vamos ao enunciado do problema.

Dada uma lista de produtos ($products) previamente definida, contabilize a quantidade vendida de cada produto dada uma listagem de produtos vendidos ($context). Somente os produtos constantes na lista previamente definida devem ser contabilizados. Ao final selecione apenas os dois produtos mais vendidos, e caso haja um empate classifique os produtos em ordem alfabética. O retorno deve ser um array associativo produto x quantidade.

Observando o enunciado podemos perceber alguns recursos que serão necessários… explode para transformar a lista de produtos vendidos em array, array_filter para excluir quem não está na listagem de produtos pré-definidos, count para contar, sort para classificar, array_shift para pegar os produtos mais vendidos…

Podemos parar por aqui, boa parte destes recursos vão dar na trave, sabe por que? Porque provavelmente você não lembraria de cabeça a diferença entre sort, rsort, asort, arsort, ksort, krsort, usort, uasort, uksort… Talvez você também não lembre algumas funções prontas utilizam exclusivamente índices numéricos e/ou não preservam os índices originais associativos. Outra grande questão é a aplicação em arrays multi-níveis, uma coisa é trabalhar com array simples de um único nível e outra coisa processar array multi-nível em profundidade.

Assim, eu não vou tentar explicar o algoritmo do problema pra vocês; ele é muito simples depois de resolvido e pode facilmente ser entendido apenas você lendo o código. Conforme o enunciado também podemos perceber que os arrays aplicados são de nível simples onde as funções array prontas dão um show. Então eu vou explicar a seguir o que você deveria ter mente ou ter decorado sobre algumas funções array prontas, por que esse é o verdadeiro diferencial que você pode obter.

SORT – sort ordena um array pelo valor do elemento, mas ele despreza completamente os índices originais do array. Sort opera sobre o array original modificando-o completamente, assim bye bye array original depois do sort. Então sort não serve pra você se você precisa manter os índices associativos preservados depois da ordenação.

$y = (['fruit'=>'lemon','salad'=>'lettuce','protein'=>'eggs','carbohydrate'=>'pasta']);
sort($y);
print_r($y);
// [0] => eggs
// [1] => lemon
// [2] => lettuce
// [3] => pasta

RSORT – o mesmo que sort, só que ordena em ordem inversa. Repare que o R a frente de sort significa REVERSE. Lembre-se deste R a frente do sort, ele vai aparecer em outros comandos e terá a mesma semântica.

$y = ['fruit'=>'lemon','salad'=>'lettuce','protein'=>'eggs','carbohydrate'=>'pasta'];
rsort($y);
print_r($y);
// [0] => pasta
// [1] => lettuce
// [2] => lemon
// [3] => eggs

ASORT – o mesmo que sort, só que este aqui preserva os índices originais intactos. Repare que o A a frente de sort significa ASSOCIATIVE, indicando que o comando aplica-se a operações com arrays associativos. Os índices numéricos também serão preservados após a ordenação.

$y = (['fruit'=>'lemon',3=>'bread','salad'=>'lettuce',0=>'rice','protein'=>'eggs',1=>'beans','carbohydrate'=>'pasta']);
asort($y);
print_r($y);
// [1] => beans
// [3] => bread
// [protein] => eggs
// [fruit] => lemon
// [salad] => lettuce
// [carbohydrate] => pasta
// [0] => rice

ARSORT – o mesmo que asort só que a ordenação é feita em ordem inversa. Repare novamente o R antes do sort indica REVERSE ou seja, ordem inversa.

$y = (['fruit'=>'lemon',3=>'bread','salad'=>'lettuce',0=>'rice','protein'=>'eggs',1=>'beans','carbohydrate'=>'pasta']);
arsort($y);
print_r($y);
// [0] => rice
// [carbohydrate] => pasta
// [salad] => lettuce
// [fruit] => lemon
// [protein] => eggs
// [3] => bread
// [1] => beans

KSORT – ordena um array pelo índice e não pelo valor do elemento como faz o sort. Repare que K a frente do sort significa KEY. Aqui nos deparamos com uma primeira situação inusitada, como é comum termos índices mistos compostos por números e strings o tipo de ordenação padrão pode não atender as nossas expectativas. Para corrigir este comportamento basta ativar o segundo parâmetro informando SORT_STRING ou SORT_NATURAL, isso deve resolver a questão.

$y = ['fruit'=>'lemon',3=>'bread','salad'=>'lettuce',0=>'rice','protein'=>'eggs',1=>'beans','carbohydrate'=>'pasta'];
ksort($y);
print_r($y);
// [carbohydrate] => pasta
// [fruit] => lemon
// [salad] => lettuce
// [0] => rice
// [protein] => eggs
// [1] => beans
// [3] => bread

$y = ['fruit'=>'lemon',3=>'bread','salad'=>'lettuce',0=>'rice','protein'=>'eggs',1=>'beans','carbohydrate'=>'pasta'];
ksort($y, SORT_STRING);
print_r($y);
// [0] => rice
// [1] => beans
// [3] => bread
// [carbohydrate] => pasta
// [fruit] => lemon
// [protein] => eggs
// [salad] => lettuce

KRSORT – o mesmo que ksort só que ordenado em ordem inversa.

$y = ['fruit'=>'lemon',3=>'bread','salad'=>'lettuce',0=>'rice','protein'=>'eggs',1=>'beans','carbohydrate'=>'pasta'];
krsort($y, SORT_NATURAL);
print_r($y);
// [salad] => lettuce
// [protein] => eggs
// [fruit] => lemon
// [carbohydrate] => pasta
// [3] => bread
// [1] => beans
// [0] => rice

ARRAY_SLICE – esse aqui é animal, se você precisa quebrar um array em pedaços, sacar a ponta da frente ou até mesmo a ponta de trás do array, mas precisa que esta quebra preserve a combinação key => value do array original?! array_slice é a sua pedida.

$y = ['fruit'=>'lemon',3=>'bread','salad'=>'lettuce',0=>'rice','protein'=>'eggs',1=>'beans','carbohydrate'=>'pasta'];
krsort($y, SORT_STRING);
print_r($y);
// [salad] => lettuce
// [protein] => eggs
// [fruit] => lemon
// [carbohydrate] => pasta
// [3] => bread
// [1] => beans
// [0] => rice

$ys = array_slice($y, 0, 2);
print_r($ys);
// [salad] => lettuce
// [protein] => eggs

ARRAY_PUSHARRAY_POPARRAY_SHIFTARRAY_UNSHIFT – Lembre-se que estas funções não objetivam trabalhar com índices associativos então nenhuma destas funções servirão para o nosso caso. Todos esses quatro comandos operam em nível de elemento valor sem se importar com índices. A cada interação por estes comandos os índices do array são sistematicamente resequenciados.

$y = [];
array_push($y, 'first');
array_push($y, 'second');
array_push($y, 'third');
print_r($y);
// [0] => first
// [1] => second
// [2] => third
$ys = array_shift($y);
print_r($ys);
// first
array_unshift($y, 'zero');
print_r($y);
// [0] => zero
// [1] => second
// [2] => third
$yp = array_pop($y);
print_r($yp);
// third
print_r($y);
// [0] => zero
// [1] => second

ARRAY_COUNT_VALUES – fantástico recurso para contabilizar as ocorrências dos valores em um array. Pense no array de produtos vendidos, usando array_count_values teremos como retorno um array tendo os produtos como chave e as ocorrências de cada produto sumarizadas como valor.

$c = 'phone ssd headset ssd headset mobile headset phone game headset hdd ssd game ssd ssd headset game box box box box box box';
$y = explode(' ', $c);
print_r($y);
// [0] => phone              // [12] => game
// [1] => ssd                // [13] => ssd
// [2] => headset            // [14] => ssd
// [3] => ssd                // [15] => headset
// [4] => headset            // [16] => game   
// [5] => mobile             // [17] => box
// [6] => headset            // [18] => box
// [7] => phone              // [19] => box
// [8] => game               // [20] => box
// [9] => headset            // [21] => box
// [10] => hdd               // [22] => box
// [11] => ssd

$yc = array_count_values($y);
print_r($yc);
// [phone] => 2
// [ssd] => 5
// [headset] => 5
// [mobile] => 1
// [game] => 3
// [hdd] => 1
// [box] => 6

ARRAY_KEYS – retorna os índices de um array como um array de valores. Este novo array retornado será chaveado por índice numérico sequencial.

$y = ['phone'=>2,'ssd'=>5,'headset'=>5,'mobile'=>1,'game'=>3,'hdd'=>1,'box'=>6];
$yk = array_keys($y);
print_r($yk);
// [0] => phone
// [1] => ssd
// [2] => headset
// [3] => mobile
// [4] => game
// [5] => hdd
// [6] => box

ARRAY_VALUES – retorna os valores de um array como um array de valores desprezando os índices originais. O novo array será chaveado por índice numérico sequencial. O array_values trabalha apenas com um nível de array, assim arrays com multi-níveis contendo outros arrays ou objetos serão processados no seu primeiro nível, mas estes subarrays e objetos permanecerão intactos em sua estrutura.

$y = ['phone'=>2,'ssd'=>5,'headset'=>5,'mobile'=>1,'game'=>3,'hdd'=>1,'box'=>6,'sub'=> ['ps5'=>10]];
$yv = array_values($y);
print_r($yv);
// [0] => 2
// [1] => 5
// [2] => 5
// [3] => 1
// [4] => 3
// [5] => 1
// [6] => 6
// [7] => Array
// (
//   [ps5] => 10
// )

ARRAY_FLIP – inverte a posição de índices e valores, ou seja, os valores passam a ser índices e os índices passam a ser valores. Mas o array_flip trabalha somente com arrays simples com índices e valores do tipo string e/ou numérico. Caso seu array contenha um outro array ou um objeto o array flip vai emitir um warning mas ainda assim vai funcionar, porém os subarrays e objetos serão ignorados e não farão parte da nova array retornada.

$y = ['phone'=>2,'ssd'=>5,'headset'=>5,'mobile'=>1,'game'=>3,'hdd'=>1,'box'=>6,'sub'=> ['ps5'=>10]];
$yf = array_flip($y);
print_r($yf);
// [2] => phone
// [5] => headset
// [1] => hdd
// [3] => game
// [6] => box

ARRAY_SUM – sumariza ou contabiliza os elementos valores de um array desde que os valores possam ser convertidos para número. Repare que no exemplo o produto box que contém o valor 6txt será convertido para o número 6, pois este é o comportamento de conversão padrão esperado do PHP. Qualquer elemento que não possua um valor numérico, como subarray, objeto, ou texto, não será contabilizado. O retorno é um escalar com o total da somatória dos elementos numéricos.

$y = ['phone'=>'two','ssd'=>5,'headset'=>5,'mobile'=>1,'game'=>3,'hdd'=>1,'box'=>'6txt','sub'=> ['ps5'=>10]];
echo 'total: ' . array_sum($y);
// total: 21

ARRAY_FILTER – O famigerado array_filter é um dos seus maiores aliados. O simples fato de parsear um array com array_filter já elimina todos os elementos com valor null, sem necessidade de nenhuma função callback. Combinado com uma função callback então o poder de sanitização é exponencial. Mas lembre-se, array_filter não é multilevel e não serve para sanitização em profundidade.

$y = ['phone'=>'two','ssd'=>null,'headset'=>'','mobile'=>1,'game'=>3,'hdd'=>null,'box'=>6,'sub'=> ['ps5'=>10, 'ps3'=>null]];
$yt = array_filter($y);
print_r($yt);
// [phone] => two
// [mobile] => 1
// [game] => 3
// [box] => 6
// [sub] => Array
// (
//   [ps5] => 10
//   [ps3] =>
// )

$ytc = array_filter(
  $y,
  function($value) {
    return !empty($value);
  });
print_r($ytc);
// [phone] => two
// [mobile] => 1
// [game] => 3
// [box] => 6
// [sub] => Array
// (
//   [ps5] => 10
//   [ps3] =>
// )

ARRAY_REVERSE – e sempre teremos o simples reverse para inverter a ordem de um array. Quando você precisa transformar uma pilha LIFO and uma fila FIFO uma ordenação por sort não é seja desejada, então simplesmente aplica-se a inversão da ordem do array com o array_reverse.

$y = (['fruit'=>'lemon',3=>'bread','salad'=>'lettuce',0=>'rice','protein'=>'eggs',1=>'beans','carbohydrate'=>'pasta']);
$yr = array_reverse($y);
print_r($yr);
// [carbohydrate] => pasta
// [0] => beans
// [protein] => eggs
// [1] => rice
// [salad] => lettuce
// [2] => bread
// [fruit] => lemon

ARRAY_COLUMN – esta função é muito útil para manipular dados no formato tipo tabela composto por linhas e colunas. Assim, um array simples não vai funcionar com array_column por que ele precisa receber um array de arrays e é o segundo nível que deve conter os arrays associativos composto pelas colunas de cada linha. Até mesmo objetos são suportados pelo array_column.

Os índices do primeiro nível são irrelevantes para o processo, podem ser numéricos sequenciais ou associativos, eles serão desprezados de qualquer forma.

Além de buscar os valores da coluna desejada, o terceiro parâmetro ainda indica o nome de uma possível coluna na mesma linha cujo valor possa servir de índice para chavear o valor retornado. No mundo real uma chave única como ID seria o indicado. Lembrando que a coluna desejada não precisa existir em todas as linhas de qualquer linear, as linhas que não possuírem esta coluna serão desprezadas durante o processamento.

$y = [
['id'=>'0000','first'=>'Jonh','last'=>'Doe','email'=>'jonh.doe@email'],
['id'=>1000,'first'=>'Mary','last'=>'Loe','email'=>'mary.loe@email'],
['id'=>2000,'first'=>'Marilyn','last'=>'Moe','email'=>'marilyn.moe@email'],
'one' => ['id'=>1,'first'=>'Jonh','last'=>'Doe','eeeemail'=>'jonh.doe@email'],
'two' => ['id'=>2,'first'=>'Mary','last'=>'Loe','email'=>'mary.loe@email'],
'three' => ['id'=>3,'first'=>'Marilyn','last'=>'Moe','email'=>'marilyn.moe@email'],];
$yc = array_column($y,'email','id');
print_r($yc);
// [0000] => jonh.doe@email
// [1000] => mary.loe@email
// [2000] => marilyn.moe@email
// [2] => mary.loe@email
// [3] => marilyn.moe@email

ARRAY_MERGE – O array_merge é bastante controverso e as vezes não produz o resultado que você está querendo, mas ele funciona conforme foi projetado e as regras são bem claras.

O array_merge usa um array como base e um outro array adicional para ser mergido no array base. Caso um índice associativo no array adicional exista no array base o valor do array adicional será sobrescrito no array base. Caso o índice associativo no array adicional não exista no array base ele será adicionado no array base. Todos os índices numéricos no array adicional serão adicionados no array base com resequenciamento automático, ou seja, não importa se o índice numérico exista ou não no array base, ele será inserido independentemente de qualquer condição.

$ybase = ['fruit'=>'apple','drink'=>'water','snack'=>'chips',0=>'juice',1=>'banana'];
$yadd = ['fruit'=>'naranja','drink'=>'leche',0=>'manzana',1=>'pera'];
$yg = array_merge($ybase, $yadd);
print_r($yg);
// [fruit] => naranja
// [drink] => leche
// [snack] => chips
// [0] => juice
// [1] => banana
// [2] => manzana
// [3] => pera

ARRAY MERGE + SUGAR SYNTAX – Uma outra forma de você fazer um merge de arrays é utilizando o operador plus (+). Só que o comportamento desta sintaxe é um pouco diferente da função array_merge.

Considere o array base e o array adicional, com a sugar syntax os índices do array adicional que não existirem no array base serão adicionados no array base, e ponto final. Assim se o objetivo é simplesmente adicionar elementos omissos no array base a sugar syntax provê um resultado melhor.

$ybase = ['fruit'=>'apple','drink'=>'water','snack'=>'chips',0=>'juice',1=>'banana'];
$yadd = ['fruit'=>'naranja','drink'=>'leche',0=>'manzana',1=>'pera',3=>'frambuesa'];
$ysg = $ybase + $yadd;
print_r($ysg);
// [fruit] => apple
// [drink] => water
// [snack] => chips
// [0] => juice
// [1] => banana
// [3] => raspberry

ARRAY_REPLACE – Ao invés de array_merge ou merge sugar syntax considere utilizar array_replace para fazer o merge de arrays. Acontece que o array_replace no final das contas produz o resultado mais esperado na maioria das situações.

O array_replace faz o match entre array base e array adicional para qualquer tipo de índice, associativo e numérico. Os índices que fazem match serão sobrescritos na array base e os índices omissos serão adicionados no array base.

Simples, prático e objetivo!

$ybase = ['fruit'=>'apple','drink'=>'water','snack'=>'chips',0=>'juice',1=>'banana'];
$yadd = ['fruit'=>'naranja','drink'=>'leche',0=>'manzana',1=>'pera',3=>'frambuesa'];
$yr = array_replace($ybase, $yadd);
print_r($yr);
// [fruit] => naranja
// [drink] => leche
// [snack] => chips
// [0] => manzana
// [1] => pera
// [3] => frambuesa

Resumindo, as funções array prontas funcionam como uma caixa de ferramentas, se você não sabe como aplicá-las corretamente acabará usando somente o martelo e a talhadeira! Ou em último caso, só a MARRETA mesmo…