Composer,  PHP,  Programação

Criando um pacote composer – packagist

Uma das grandes revoluções no mundo PHP foi a criação do gerenciamento de pacotes/dependências composer, funcionando tanto para ambientes windows quanto linux, ele facilita e muito a vida de nós programadores.

Como o foco desse tutorial é a criação de um pacote, não focarei na instalação do composer, nem em sua configuração, que podem ser encontradas facilmente no site

Vamos lá.

Imagine uma situação, você tem diversos projetos, onde será necessário ler uma string, e ver se existe algum JSON no meio dela, e parsear esses dados. Claro que você poderia criar um simples função para isso, e importar para seus outros projetos. Mas que tal dividir ela com a comunidade, além de facilitar sua extensão em outros projetos existentes e futuros ? Para isso criaremos esse pacote.

Passos iniciais
Agora que já definimos nosso escopo, vamos as configurações inicias. Criei 1 folder no seu document root (no meu caso /var/www/html ). Esse folder não será importante no upload do pacote não. Por convencão (e para facilitar o PS4), colocaremos nossos arquivos dentro do pasta src.

Feito isso, acesse o folder, e digite composer init. Dessa forma iremos criar, de forma interativa, o arquivo composer.json.

composer init
view raw composer init hosted with ❤ by GitHub

Serão feitas algumas perguntas, a saber

PerguntaValores
Package name (/) [samhk222/src]:O composer trabalha com a notação vendor/pacote igual você já deve ter visto dentro das suas pastas /vendor. Geralmente o nome é seunick-ou-empresa/nome-do-pacote
DescriptionO que o seu pacote fará
Author [Samuel Aiala Ferreira , n to skip]:Uma dica, o que vem em amarelo é o valor default, caso esteja correto basta apertar enter
Minimum Stability []:
dev (Coloque dev)
Package Type (e.g. library, project, metapackage, composer-plugin) []:library
LicenseAperte enter, ou escolha sua licença, ela não fará diferença agora
Would you like to define your dependencies (require) interactively [yes]? no
Would you like to define your dev dependencies (require-dev) interactivelyno
Do you confirm generation [yes]? yesyes ou enter para criar o package.json

ao final dos perguntas, ele exibirá o composer.json e perguntará se está OK, basta digitar yes (ou apertar enter)

Iremos fazer umas pequenas modificações no arquivo composer.json, para incluir o require o autoload, ficando dessa forma

{
"name": "samhk222/json-string-parser",
"description": "Parseia as informações de uma string, retornando em forma de array, os jsons que foram encontrados nela",
"type": "library",
"authors": [
{
"name": "Samuel Aiala Ferreira",
"email": "samuca@samuca.com"
}
],
"minimum-stability": "dev",
"require": {
"php": ">=5.3.0"
},
"autoload": {
"psr-4": {
"samhk222\\": "src/"
}
}
}

Vamos as explicações.

  • require php >= 5.3.0 – Versão mínima do php requerida para rodar o script
  • “samhk222\\”: “src/” – Significa para fazer o autoload, usando o PSR-4, dos namespaces samhk222 que estão dentro da pasta src

Para testar se está tudo correto, digite composer install na linha de comando,

Dessa forma ele irá criar a pasta vendor (que não deve ir para o git) e o arquivo composer.lock (que deve SIM ir para o git, pois ele garante que toda a equipe de desenvolvimento esteja usando os mesmo pacotes).

Agora vamos criar o programa, para esse esqueleto fazer realmente alguma coisa. Crie o arquivo dentro da pasta /src/Parser.php

<?PHP
# Lembra quando fizemos o autoload dentro do composer.json, para os namespaces samhk222 dentro da pasta src ?
# precisamos declará-lo agora, senão não sera feito o autload dessa classe
namespace samhk222;
class Parser
{
public $hasJSON = false; #Indica se a string tem algum json
public $hasFaltyJSON = false; # Indica se tem json, mas com erro
public $matches = []; # Retorna os matches do json caso encontrados
public function parseString($text)
{
$pattern = '/\{(?:[^{}]|(?R))*\}/x ';
preg_match_all($pattern, $text, $matches);
if (count($matches[0])>0){
$this->hasJSON = true;
foreach ($matches[0] as $key => $value) {
$decoded = json_decode($value);
if (json_last_error() !== JSON_ERROR_NONE) {
$this->hasFaltyJSON = true;
} else {
$this->matches[] = $decoded;
}
}
}
return ;
}
}
view raw Parser.php hosted with ❤ by GitHub

Nossa lib está pronta (apesar de não termos utilizado ela ainda). Então vamos publicá-la. Para isso é necessário ter uma conta no github, e uma no packagist

Após criar um repositório no git, digite os comandos abaixo, no root do projeto.

echo "# Primeira lib enviada ao packagist" >> README.md
echo "/vendor" >> .gitignore
git init
git add .
git commit -m "Primeiro commit"
git remote add origin https://github.com/samhk222/json-string-parser.git
# O comando abaixo é opcional, mas ele salva suas credenciais do git para nao ter que digitar toda hora
git config credentials.helper store
git push -u origin master
# O Packagist ira nos solicitar que criemos uma tag, para nao precisarmos instalar do branch de dev, entao crie ela de uma vez
git tag -a 0.0.2 -m "Criando a primeira versão do nosso aplicativo"
git push origin --tags
view raw gistfile1.txt hosted with ❤ by GitHub



Vamos agora ao packagist. Depois de criar sua conta, vá em submit (menu superior) e cole a url do seu repo e clique em check. Caso tudo dê certo, ele irá exibir seu vendor name, e o nome do seu pacote, e basta concluir o formulário.

Dessa forma agora basta testar nosso recém enviado pacote. Faça o seguinte, crie uma pasta no seu /www por exemplo /www/teste-json-string-parser e digite o comando para instalar o pacote (sendo 0.0.2 a tag que você criou).

Você verá que o composer instalou nosso componente, gerou o autoload.php, o composer.json e o composer.lock.

Para utilizar o pacote, crie 1 arquivo index.php dentro da raiz da pasta, e cole os comandos abaixo.

<?PHP
require('vendor/autoload.php'); # Todas as paginas que desejar usar a lib, inclua essa linha
use samhk222\Parser; # Importe nosso parser
$parser = new Parser();
$string_com_json = 'Olá, seja bem vindo ao nosso site, as opções de menu são {"menu": {"header": "SVG Viewer", "items": [{"id": "Open"}, {"id": "OpenNew", "label": "Open New"}, null, {"id": "ZoomIn", "label": "Zoom In"}, {"id": "ZoomOut", "label": "Zoom Out"}, {"id": "OriginalView", "label": "Original View"}, null, {"id": "Quality"}, {"id": "Pause"}, {"id": "Mute"}, null, {"id": "Find", "label": "Find..."}, {"id": "FindAgain", "label": "Find Again"}, {"id": "Copy"}, {"id": "CopyAgain", "label": "Copy Again"}, {"id": "CopySVG", "label": "Copy SVG"}, {"id": "ViewSVG", "label": "View SVG"}, {"id": "ViewSource", "label": "View Source"}, {"id": "SaveAs", "label": "Save As"}, null, {"id": "Help"}, {"id": "About", "label": "About Adobe CVG Viewer..."} ] }} por favor escolha uma para continuarmos, vamos inserir outro json, para termos {"segundo":"parametro"} e porque não um terceiro json {"chave":"valor"} depois dessa string toda, mas esse ultimo aqui tem erro, porque {"chave":sem aspas}não tem aspas';
$string_sem_json = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
echo "\n<pre>";
$parser->parseString($string_com_json);
echo sprintf("Tem algum json ? %s\n", $parser->hasJSON ? "Sim" : "Não");
echo sprintf("Tem erro em algum json ? %s\n", $parser->hasFaltyJSON ? "Sim" : "Não");
if ($parser->hasJSON) {
echo sprintf("JSONs válidos encontrados (Total: %s) \n%s\n", count($parser->matches), print_r($parser->matches,true));
}
echo "\n</pre>";
view raw index.php hosted with ❤ by GitHub

E quando rodamos no browser, temos a saída da lib

Próximos passos
– É possível criar 1 hook no git para atualizar o packagist todas as vezes que nosso pacote for atualizado (commit), e isso ficará para um próximo tutorial.


Notice: ob_end_flush(): failed to send buffer of zlib output compression (0) in /home/samu/public_html/blog/wp-includes/functions.php on line 5277