Come visualizzare gli statement SQL in MySQL

Se vogliamo sapere ad esempio cosa succede sul database di Joomla quando creiamo un nuovo utente o un nuovo articolo, il miglior modo per capirlo senza addentrarsi nel codice PHP è quello di attivare il log degli statement di MySQL.

Per fare ciò bisogna analizzare e manipolare il valore delle variabili general_loggeneral_log_file e log_ouput.

Per visualizzarne il valore, basta eseguire i seguenti statement in una console SQL come quella di phpMyAdmin:

SHOW GLOBAL VARIABLES LIKE 'general_log'
SHOW GLOBAL VARIABLES LIKE 'general_log_file'
SHOW GLOBAL VARIABLES LIKE 'log_output'

Ottenendo come rispettivi output:

Variable_name value
general_log OFF
general_log_file C:ProgramDataMySQLMySQL Server 5.5DataLorenzo-GI.log
log_output FILE

A questo punto, dopo aver capito su che file verrà scritto l’output, lo possiamo attivare eseguendo lo statement:

SET GLOBAL general_log = 'ON'

Subito dopo aver attivato il log effettuiamo la nostra operazione (creare un utente, cancellare un articolo, ecc.) terminata la quale lo disattiviamo eseguendo lo statement:

SET GLOBAL general_log = 'OFF'

Aprendo il file di log con un editor di testo potremo vedere la sequenza di statement che sono stati eseguiti sul database per portare a compimento l’azione di interesse.

CodeIgniter vs Yii framework vs CakePHP vs Zend framework vs Symfony vs Kohana vs Akelos vs DooPHP: Quale framework PHP scelgo?

La risposta sintetica è: nessuno, sono tutti la stessa minestra!

Tutti i framework elencati cercano di distinguersi uno dall’altro, ma in realtà sono uno la copia dell’altro. Basta guardare le caratteristiche riportate sui loro siti o la tabella comparativa di wikipedia.

CodeIgniter Yii framework CakePHP Zend framework Symfony Kohana Akelos DooPHP

Riassumendo hanno tutti le solite caratteristiche:

  • paradigma ad oggetti
  • design pattern MVC (Model View Controller)
  • utilizzano sistemi di Object-relational mapping (ORM)
  • Supporto all’i18n (ovvero multilingua)

e le solite non-caratteristiche:

  • facile da usare
  • veloce/performante
  • flessibile
  • stabile, affidabile
  • sicuro
  • interoperabile
  • supportato dalla comunità
  • ben documentato
  • ecc.

Se però analizziamo le caratteristiche pubblicizzate abbiamo quanto segue:

Paradigma ad oggetti OOP

La sezione di wikipedia è più che esplicativa: http://en.wikipedia.org/wiki/Object-oriented_programming#Criticism

Design pattern MVC

Di per sè l’idea è buona, ma unito alla OOP ha l’effetto di aumentare la complessità con una scarsità di benefici.

Il flusso logico dell’applicazione è sparpagliato in tanti file e utilizzando OOP tipicamente è nascosto dall’ereditarietà tra classi. Invece di leggere il flusso logico di un listato di codice in sequenza bisogna continuamente saltare da un file all’altro. Il risultato è che per aggiungere una funzionalità o modificare un programma che segue questo pattern tipicamente è di più il tempo che si passa a capire come innestarsi nella logica che si vuole modificare rispetto al tempo speso nell’operare la modifica.

Generic Framework build with MVC Pattern + OOP Paradigm

Object-relational mapping (ORM)

Anche in questo caso l’ORM è di fatto un tentativo di soluzione ai problemi introdotti dalla OOP nell’interazione con un DB.

Sicuri contro attacchi SQL Injection e XSS

La tipica frase che si legge è: utilizza il nostro framework e in automatico la tua web application sarà sicura.

Di fatto però questa frase comunica allo sviluppatore un falso senso di sicurezza perché lascia intendere che ci penserà il framework a rendere sicura la web app, ma in realtà ciò non è possibile. Per sua natura stessa infatti la sicurezza è un tema pervasivo di tutta la progettazione, lo sviluppo e il deploy di un applicazione e pertanto le minacce legate alla sicurezza devono essere chiare allo sviluppatore (non si può nascondere la testa sotto la sabbia).

Per di più la maggior parte dei framework sopra esposti non forniscono funzionalità realmente utili come l’escaping di HTML, Javascript ecc.

Conclusione

Il difetto dei web framework è che sono troppo generici, perché vogliono consentire lo sviluppo di qualsiasi applicazione web, ma così facendo aggiungono uno strato di complessità fornendo in cambio funzionalità per lo più generiche.

Nel caso specifico del php inoltre già il linguaggio è pensato per il WEB e di conseguenza già il linguaggio ha tutto quello che serve per lo sviluppo di applicazioni WEB generiche.

Il risultato netto per utilizzare i framework sopra esposti è dover imparare oltre ad un linguaggio di programmazione come il PHP, un paradigma di programmazione OOP, un design pattern MVC e un framework che di fatto non aggiunge nulla, ma aumenta la complessità con tutto quello che ne deriva:

  • programmi più buggati
  • produttività rallentata

Soluzione

L’unica soluzione è non usare un framework generico, ma utilizzarne uno specifico per il tipo di applicazione che si vuole creare.

Noi di Garda Informatica abbiamo creato un nostro framework, specifico per lo sviluppo di applicazioni gestionali web based. La specificità del framework è la chiave per ottenere uno strumento efficiente ed efficace.

Script PHP per l’importazione/esportazione dati del proprio database

bees

Un tipo di soluzione che i nostri clienti ci chiedono spesso è quella di script per l’importazione/esportazione dati da e verso un database.

Lo scenario tipico è quello di un database, magari di un gestionale proprietario closed source, dal quale vanno estratti dei dati oppure sul quale vanno aggiornati dei dati con quelli provenienti da una fonte esterna come per esempio un foglio excel o un altro database.

In questo caso l’esigenza è quella di avere una procedura da lanciare per effettuare questo aggiornamento sia da interfaccia web sia come lavoro schedulabile es.: una volta ogni notte.

Non tutti sanno che il PHP, oltre ad essere il linguaggio web per eccellenza, può essere utilizzato anche per sviluppare script da lanciare a riga di comando.

Naturalmente se il nostro script viene lanciato dal web dovrà produrre un certo output (es. l’html di avanzamento), se invece viene lanciato da riga di comando ne dovrà produrre di diverso tipo (es. semplici righe di testo).

Il modo per capire in quale dei due casi ci troviamo è quello di interrogare la costante predefinita PHP_SAPI la quale contiene la stessa stringa ritornata dalla funzione php_sapi_name.

Se cioè la costante PHP_SAPI è uguale a cli significa che il nostro codice sta girando da command line, in tutti gli altri casi significa che sta girando via web.

Quindi, per esempio, la nostra funzione di output avrà una struttura simile alla seguente:

function output($msg) {
    if (PHP_SAPI === 'cli') {
        echo '<div>' . htmlentities($msg) . '</div>';
    } else {
        error_log($msg);
    }
}

Un altro accorgimento da tenere presente quando si vuole sviluppare un command line script è quello di impostare correttamente il path per le inclusioni dal momento che lo script può essere lanciato in modo assoluto o relativamente alla directory in cui è contenuto.

Il path cioè va impostato come segue nel file di avvio dello script e appena prima che vengano fatte le inclusioni di altri PHP:

define('BASE_PATH', dirname(__FILE__));
set_include_path(get_include_path() . PATH_SEPARATOR . BASE_PATH);

require_once 'lib/my_lib.php';
...

Se ci dimentichiamo di fare ciò non sarà possibile lanciare lo script con path assoluto come nell’esempio seguente:

root@myserver:~> php /var/www/vhosts/miosito.it/scripts/mioscript.php

Infine, trattandosi di uno script che potenzialmente può impiegare diverso tempo per completare il suo lavoro e consumare più memoria di quella che generalmente basta per una pagina web, è bene togliere il limite sul tempo di esecuzione e aumentare la memoria a disposizione:

<?php
/* lo script non ha limiti di tempo per completare la sua esecuzione */
set_time_limit(0);
/* lo script avrà a disposizione fino a 128 MiB */
ini_set('memory_limit', '128M');

Quanto vale il software?

chess_board1

Alle volte può capitare che il Cliente, una volta visto il preventivo per il software che ha richiesto, ritenga che la cifra sia alta.

Questo reazione però è guidata fondamentalmente dalla sola visione di quanto costerà il software e non di quanto vale.

Già, perché il software ha un valore intrinseco che va oltre il solo costo per produrlo.

Per capire quanto vale il software bisogna fare due conti e rispondere a queste domande:

  • l’utilizzo di questo software nella mia azienda quanto tempo mi farà risparmiare all’anno?
  • l’utilizzo di questo software quanto mi farà guadagnare all’anno?
  • l’utilizzo di questo software quanto mi farà crescere?

Per fare un esempio, se consideriamo un costo orario per dipendente di 15 euro, è sufficiente che un software faccia risparmiare 20 minuti al giorno a un dipendente per avere un risparmio di quasi 2000 euro/anno.

Tempo che potrà essere impiegato in altre attività determinando di fatto una crescita dell’azienda.

Se invece si tratta di un nuovo servizio a pagamento che l’azienda offre ai suoi clienti, per fare un esempio, con un ricavo di 9.90 euro/mese per cliente, già con 50 clienti l’azienda guadagnerà 6000 euro/anno.

Problematiche ricorrenti nello sviluppo di webapp 3/3: date

Dopo aver analizzato la gestione dell’escaping e dell’encoding vediamo la gestione delle date.

Se la nostra webapp è raggiungibile da Internet significa che può essere utilizzata da luoghi con fusi orari differenti da quello in cui risiede il nostro server. Inoltre il server può risiedere fisicamente in un paese con il fuso orario o timezone diverso dal nostro.

Per poter gestire correttamente questo scenario bisogna fare delle scelte consapevoli a livello di applicazione.

Una scelta potrebbe essere quella di impostare come timezone dell’applicazione e del database l’UTC: questo ci dà un punto di riferimento fisso nel tempo per la nostra webapp indipendentemente da dove si trova il server ospitante (hosting). In più, grazie a questa scelta, se sviluppiamo in PHP non dovremo preoccuparci della differenza tra date e gmdate poiché sarà del tutto indifferente.

In PHP per utilizzare questo timezone dovremo utilizzare la funzione date_default_timezone_set come nel modo seguente:

date_default_timezone_set('UTC');

Per quanto riguarda invece il database MySQL subito dopo la connessione si potrà eseguire lo statement SQL:

SET time_zone = '+00:00';

A questo punto non resta che ragionare sui casi che si possono presentare quando un utente indica una data/ora e come gestirli rispetto alla scrittura su DB, alla successiva lettura e alla presentazione lato utente.

I casi possibili da gestire sono 2:

  • Caso 1: l’utente esprime una data/ora in modo assoluto o comunque non rispetto al proprio timezone es. “Arriverò da voi il 10 agosto 2012 alle 8:40”;
  • Caso 2: l’utente esprime una data/ora rispetto al proprio fuso orario es. “Passate a ritirare il pacco il 3 settembre alle 9:10”;

Scrittura su DB:

  • Caso 1: la data va salvata così com’è su database (e quindi la si considera espressa rispetto al timezone del server, cioè UTC);
  • Caso 2: la data va convertita dal timezone dell’utente al timezone del server (UTC) in fase di salvataggio.

Lettura da DB e presentazione:

  • Caso 1: la data va letta e inviata all’utente così com’è, senza conversioni;
  • Caso 2: la data va letta e convertita nel timezone dell’utente prima di inviargliela.

In ogni caso, internamente, la logica del programma ragionerà su date e ore in UTC, l’eventuale conversione da e verso il timezone dell’utente avverrà subito dopo aver ricevuto il dato in input e subito prima di inviare il dato in output.