PHP CLI + $_SESSION + $_GET + $_POST
Posted by Mathias Grimm on julho 13, 2008 in PHP
Opa!
Depois de algum tempo terminei o primeiro artigo que está de acordo com os objetivos do meu blog.
Não encontrei nenhum outro artigo com esse assunto por isso resolvi ajudar a comunidade com essa pequena contribuição. Acredito que esse artigo, isoladamente não faça tanto sentido, mas nos proximos artigos estarei utilizando ele como "CORE" da minha aplicação.
Este artigo mostra como utilizar (emular) $_GET,$_POST e $_SESSION via php cli (command line interface).
Para tal tive que serializar o get e o post e utilizar o cron do linux para limpar as sessões.
Muitos devem estar se perguntando pra que usar o php cli... posso adiantar que vou utilizar eles para
controlar separadamente cada requisição , permitir renice de processo por usuario, tendo em vista que
todas requisicoes rodam por padrão em um único daemon do apache, também pretendo utilizar o php cli para rotinas de agendamento (relatorios agendados serem enviados toda segunda feira, via email com pdf em anexo), para isso é necessário integração com o sistema operacional. Assim pretendo utilizar o php cli, para situações específicas.
O ambiente utilizado foi: Ubuntu linux 8,php5 e apache 2
O objetivo do artigo não é mostrar passo a passo a instalação de cada um dos elementos utilizados, mas sim demonstrar a funcionalidade, no entando estarei disposto a tentar resolver alguma dúvida que possa ocorrer.
Bom, vamos ao que interessa.
Pra começar:
Index.php
este arquivo serve como um "gateway" para aplicação toda.
Toda e qualquer requisição deve passar por ela para que as sessões,get e post funcionem corretamente.
Logo no inicio do script estou criando as variaveis get e post e as serializando, caso alguma delas não existam as defino com valor de um array vazio para manter compatibilidade. A terceira variavel $sid é criada para armazenar o id da sessão e logo mais vocês verão que esse id é utilizado para criar o arquivo
de sessão.
Agora vou explicar um pouco essa chamada ao sistema:
o comando system envia um comando diretamente para o sistema operacional, no caso o linux. Como podem ver o comando é php -f backindex.php, esse comando é para rodar o script backindex.php, tudo oq vier após isso será interpretado como argumento e armazenado na variavel global $argv. Por definição decidi que o primeiro argumento seria o $_POST, o segundo o $_GET e o terceiro o id da sessão, mas poderia ter sido utilizada em ordem diferente...
Para enviar o post e o get tive que serializar pois são arrays.
Segue abaixo o código da index.php
<?php ?>
Ok, vamos continuar...
backindex.php
Digamos que essa seria a index do seu sistema, o controller, ele que despacha todas requisições.
Ele controlará qual programa chamar e qual ação requisitar desse programa.
No meu exemplo utilizo apenas uma classe mas poriam ser utilizadas varias classes com um controlador um pouco mais incrementado.
O funcionamente do get e do post é simples, o que foi passado serialiado no index.php como argumento serializado é "des serializdo" aqui na backindex.php e tudo funciona corretamente...
Mas devemos dar uma atenção especial a sessão... ela precisa ser restaurada antes de qualquer processamento e salva após todos processamentos. Dessa forma garantimos um uso eficaz da sessão. Ou seja, armazenamos a sessão serializada dentro de um arquivo que tem o seu nome formado por aquele id passado la na index.php, então no incio de cada requisição abrimos o arquivo, "des serializamos" seu conteúdo, atribuimos esse conteúdo a variavel $_SESSION e no final da execuçao serializamos essa variavel e salvamos ela dentro do arquivo novamente. Acredito que essa seja a meneira com que o php trabalha com sessões no ambiente web.
Outro tratamento que tive que fazer é utilizar as funções register_shutdown_function e set_error_handler para garantir que a sessão seja salva mesmo que seja utilizado um die() , exit() ou aconteça algum erro no processamento do script. Essas funcoes definem qual função será chamada quando acontecer uma dessa coisas que citei acima (exit die etc...) e dentro dessas funções faço a chamada de salvamento da session.
Bom, até agora parece qua vai tudo bem, mas temos um problema... os arquivos de sessions precisam ser eliminados no tempo correto ou seu servidor terá milhares de arquivos depois de milhares de acessos... foi ai que utilizei um solução que também acredito que seja utilizana quando utilizamos sessões nativas... criei um agendamento de tarefa (cron) que é executado a cada 1 minuto e calcula o tempo das sessões que expiraram e as apaga.
Todas soluções que utilizei aqui não foram testadas em larga escala, mas acredito que devem funcionar normalmente, talvez algum ajuste seja necessário.
Voltando... as sessões são salvas (lembrando que são serializadas pois são um array) dentro da pasta .session (ponto session) dentro da sua aplicação mas também poderiam ficar numa pasta definida por você. As sessões são salvas com uma chamada ao sistema operacional, se você digitar no seu linux echo 1 > mathiasgrimm.com.br será gerado um arquivo mathiasgrimm.com.br com seu conteúdo igual a 1... utilizei essa lógica para gravar as sessões,
poderia ter sido utilizado um fwrite, file_put_contents e tal mas preferi utilizar uma chamada nativa do sistema operacioanl (sem motivos, na verdade soh pensei em fwrite e file_put_contents agora enquanto estava postando ehhe).
Dessa mesma forma recupero o conteudo do arquivo e "des serializo" seu conteudo.
Segue abaixo o código da backindex.php
<?php //safe session sleep on die,on exit or on E_ALL error //request emulation //session_id genereted by real session $GLOBALS['sid'] = $argv[3]; //wake up session //should to be before all processiong session_start_cli(); //controller include_once("TestClass.php"); $obTestClass1 = new TestClass(); $action = $_GET['a'] ? $_GET['a'] : 'sayHello'; $obTestClass1->$action(); //sleep session //should to be before all processiong session_write_close_cli(); /////////////////////////////////////// FUNCTIONS ///////////////////////////////////////// //emulation of session_write_close function session_write_close_cli() { $sid = $GLOBALS['sid']; $file = K_DIR_CLI_SESSION.$sid.".session"; //always overwrite the file } //emulation of session_start() function session_start_cli() { $sid = $GLOBALS['sid']; $file = K_DIR_CLI_SESSION.$sid.".session"; { } else { } } //grant session sleep on die,on exit or on E_ALL error function shutdown() { session_write_close_cli(); } //grant session sleep on die,on exit or on E_ALL error function error() { session_write_close_cli(); } ?>
Ok... vou explicar o arquvio session_expire.php que é o arquivo executado pelo cron (agendamento)
Esse script lê o nome dos arquivos que existem dentro da pasta de sessões, a mesma que você definiu na backindex.php e compara se a data de cada um deles é menor que a data atual menos o tempo de expirar a sessão...
ou seja se a data do arquivo for 01/01/2008 14:00:00 e a data atual for 01/01/2008 14:45:00 e o tempo da sessão expirar for de 15 minutos, sua sessão será removida..
agora vou mostrar o comando para você adicionar esse script ao cron
digite crontab -e e insira essa linha logo após a última linha:
0-59/1 * * * * php -f /var/www/cli/session/session_expire.php
pronto, isso fará com que seu script seja executado de 1 em 1 minuto.
Assumindo que seu script esteja dentro de /var/www/cli/session/
para verificar se seu scrip foi incluido no cron digite crontab -l
qualquer dúvida perguntem.
verifique se as sessões são criadas dentro de /var/www/cli/session/.session/ e se são apagadas após o tempo de inatividade sufuciente para que elas expirem.
para testar aqui em casa utilizei o tempo igual a 1 minuto.. o que facilita bastate... imagina ter de esperar os 180 minutos , que são definidos como padrão...
isso é outra coisa importante, o seu php-cli tem um php.ini e o seu php tem outro... não testei mas acho que os 2 poderiam utilizar o mesmo, bom , então caso esteja utilizando 2, como eu, lembre de editar o session.cache_expire no php.ini correto, o meu fica em /etc/php5/cli/php.ini
segue abaixo o código do session_expire.php
<?php //cron file - run every minute cleaning expired sessions $sessionPath = "/var/www/cli/session/.session/"; //sessions files $files = scandir($sessionPath); { //date on filetime (unix timestam) time //minutes //to seconds $expire *= 60; foreach($files as $file) { if($file == "." || $file == "..") continue; if($acttime < ($mknow-$expire)) { } } } ?>
Para finalizar vou mostrar o código da classe TesteClass que motrar um texto na tela e incrementa um valor em 2 variáveis na sessão, descomente a linha em que o die() está comentado, atulize o browser algumas vezes e depois comente a linha do die novamente... perceba que mesmo com o die() a sessao continua sendo salva... logicamente só a primeira variável...
segue abaixo o código da classe
<?php class TestClass { public function sayHello() { $this->renderPage(); $this->handleSession(); } public function testGet() { $html = " <h1 style='text-align:center;'>GET SAYS HELLO !!</h1> "; $html .= "<a href=?a=sayHello> Say Hello Again! </a>"; echo $html; } public function renderPage() { $html = " <h1 style='text-align:center;'>PHP COMMAND LINE INTERFACE SAYS HELLO !!</h1> "; $html .= "<a href=?a=testGet> TEST GET </a>"; echo $html; } //session manipulation protected function handleSession() { { $_SESSION['someVar']++; } else { $_SESSION['someVar']=1; echo " <h3> sua sessão expirou ou ainda não foi inicializada!</h3> "; } //die() { $_SESSION['someOtherVar']++; } else { $_SESSION['someOtherVar']=1; echo " <h3> sua sessão expirou ou ainda não foi inicializada!</h3> "; } } } ?>
Bom, acho que é isso.
Agradeço a todos que se interessaram no assunto, caso existam dúvidas, contribuições, críticas ou qualquer outra necessidade, é só entrar em contato comigo...
Para baixar todos os arquivos utilizados no artigo clique aqui
2 Comentários on PHP CLI + $_SESSION + $_GET + $_POST
By Carva on julho 14, 2008 at 6:29 pm
E ae mlk,
Mto massa sua ideia… Vou acompanhar seus artigos e dar uma estudada neles….
ta sumido mlk!!!
abraçao
By Feijão on julho 21, 2008 at 9:31 am
Mlq… sabe quando você se sente burro?…
Subscribe
Follow comments by subscribing to the PHP CLI + $_SESSION + $_GET + $_POST Comments RSS feed.