Newsgroup: it.comp.www.php
Titolo: Come 'programmare facile'

Ciao,
stavo cercando di chiarimi le idee sul mare di CMS, Framework,
librerie, classi e quant'altro.
Sto cercando qualcosa che sia facilmente includibile ed utilizzabile
nei miei progetti web (dei CMS tendenzialmente) che mi permetta di
velocizzare i tempi di sviluppo.
Alcuni casi in cui mi sarebbe utile del codice già pronto sarebbe:
- Mostrare il risultato di una query in formato tabellare (con CSS,
paginazione e magari anche ordinamento in base al campo)
- Creare form per l'inserimento, aggiornamento e cancellazione dati
abbastanza semplici (anagrafiche, oppure elenchi)
- Gestione dei diritti e degli accessi [meno importante]
- Gestione di moduli e template (ma credetemi so ben poco su come
funzionino e su cosa siano in PHP)
- Gestione del multilingua
- Parsing o modifiche delle stringhe [meno importante]
Un CMS già pronto non mi piace. La struttura vorrei impostarla io ma
con l'ausilio di molte routine classiche già pronte da utilizzare e
non dover riscrivere ogni volta.
Sto facendo un CMS con Backoffice e non capisco di cosa ho bisogno.
Vengo da ASP ma pare che su PHP ci siano infiniti progetti in più da
sfruttare... solo che non so se appunto mi serve un framework, un CMS
(noo! ^_^), delle classi o cos'altro.
E soprattutto quale fa per me.
Quindi chiedo a voi opinioni, suggerimenti, critiche.
Grazie :-)

 dover riscrivere ogni volta.
Allora ti serve un framework

 velocizzare i tempi di sviluppo.
Dai una occhiata a questi framework:
http://codeigniter.com/
http://cakephp.org/
http://www.symfony-project.org/
Personalmente mi trovo molto bene con CakePHP. Se decidi per questo
framework, ti consiglio il libro Beginning CakePHP (ISBN:
978-1-4302-0977-5)
-- 
Vuoi distribuire il tuo sito web su CD/DVD?
Prova 
http://www.dwebpro.com/
Vuoi diventare un esperto analista PHP/MySQL?
Vieni a fare uno stage con noi: 
http://www.creativepark.it/stage/

 Quindi chiedo a voi opinioni, suggerimenti, critiche.
Per quello che chiedi ti serve un framework.
Per capire *quale* framework, questo dipende dai gusti e dalle
necessità. Credo che il piu' potente e completo in giro sia Zend, ma ce
ne sono altri piu' leggeri che spesso fanno tutto quello che mediamente
serve ad una utenza media (es: codeigniter, che io uso spesso).
Provane qualcuno e decidi.

 Allora ti serve un framework
E, giusto per chiarire la mia ignoranza, che differenza c'è tra un
framework e un semplice insieme di classi, di classi per varie
eventualità?


Non capisco come sapere se però fanno quello di cui ho bisogno.
Non lo voglio per cose gigantesche ma per:
- Evitare di scrivere sempre le stesse select, stampate sempre in
tabelle simili, con le stesse paginazioni, con form di modifica dove
cambiano solo i nomi dei campi. Insomma non ri-scrivere troppo
codice.
- Gestire il template del mio portale in modo da poter spostare e
posizionare (e aggiungere!) elementi un pò ovunque. So che si usano i
moduli ma non so di preciso che cosa siano.
- Gestire le traduzioni (se fosse facile e versatile)
- Gestire l'accesso ed eventuali diritti
Chiedo in pratica un pò di procedure già fatte (stampare tabelle,
paginazioni, etc) e un pò di strutturazione preimpostata (ma è meno
indispensabile).
Non credo mi serva qualcosa di complesso; e magari Zend è anche troppo
grosso e ampio, no? Installarlo e usarlo diventerebbe forse uno
svantaggio anzichè una comodità (visto che dovrei usarlo 'qua e là').
Come mi ci oriento?

 necessità.
Mi chiedo anche se secondo voi è meglio che supporti PHP5 o no.
Io per adesso programmo col 4 ed uso php da pochi mesi.
Non conosco le peculiarità del 5 e se il passaggio comporterebbe
grossi cambiamenti di codice o di utilizzo.
Mi stavo buttando su CodeIgniter e vedo che è in PHP4...

 Io per adesso programmo col 4 ed uso php da pochi mesi.
Deve _obbligatoriamente_ supportare PHP5!
	Francesco

 eventualità?
Un framework e` un insieme di classi ben integrate tra di loro, in modo 
che una classe che ha bisogno di una funzione gia` implementata da 
un'altra non la reimplementa, ma usa quella classe.
Bye.

 fosse facile e versatile) - Gestire l'accesso ed eventuali diritti
Mi pare di capire che il grosso ti serve a livello di generazione di 
codice HTML, piu` che di infrastruttura di progetto.
Probabilmente le classi di PEAR dedicare all'HTML ti sono piu` utili di un 
framework completo.
Anche se io ti consiglio comunque di vedere come funziona un framework, e 
magari di iniziare a usarne uno.
Per rispondere anche all'altra domanda: PHP4 e` morto ad agosto del 2008. 
Non va piu` usato. Passa immediatamente al 5.
Bye.

 Bye.
Ciao :-)

 conto che fin'ora ho sempre programmato ben poco a oggetti)
Di evitare register_globals, safe_mode e poche altre cose.
In pratica cose che gia` erano deprecate in PHP4.
Per il resto e` compatibile quasi al 100% con PHP4. La "magagna" (il 
miglioramento, a dire il vero) piu` grossa, se programmavi a oggetti, e` 
il cambiamento dei parametri delle funzioni, che ora vengono passati per 
riferimento e non per copia quando sono oggetti.
Bye.

 riferimento e non per copia quando sono oggetti.
Vabbè tanto dovrò imparare in futuro... e così 'a senso' sembra una
'cosa buona' :-)

 Mai usato register_globals e safe_mode non so neanche cosa sia ^_^
La bastardata di register_globals e` che spesso veniva abilitato di 
default, quindi magari non ti accorgi che lo usi.
Prova a modificare php.ini, a cercarlo e a metterlo a Off e vedi se i tuoi 
script funzionano ancora.
 
Bye.

 default, quindi magari non ti accorgi che lo usi.
Sulla 4 son sicuro che era disabilitata :-)
Ho un problema però.
Ho scaricato PHP 5.2, l'ho scompattato e sostituito alla C:\php\, ho
creato il php.ini (dal reccomended), copiato libmysql.dll in system e
system32, cambiato httpd.conf sostituendo il modulo con quello di
PHP5. (ho praticamente effettuato le operazioni che nella guida di
HTML.it sono evidenziate in rosso, cioè per PHP5)
Riavviato Apache ma non funziona più nulla.
Ho un portale che deve restare in PHP 4 e uno nuovo che oramai
continuerò sviluppando in PHP 5.
Come posso mantenerli entrambi? :-(
Credevo fosse facile il passaggio ma non mi riesce.

 Credevo fosse facile il passaggio ma non mi riesce.
Usa un S.O. piu` semplice: Linux. ;)
Bye.

 Bye.
Ciao :-)

 diverse?
Vanno in conflitto perche` usano gli stessi simboli di linking con apache. 
E` come se definissi due funzioni con lo stesso nome.
 
Bye.

Ho rifatto tutto da capo e adesso funziona PHP 5! :D
Gli script sembrano andare una meraviglia!!
Ora provo ad aggiungere Zend che sembra quello con più 'credito',
essendo dello stesso team di PHP.
Metto anche PEAR (ho visto che è già incluso O_o), che forse a questo
punto è quello che mi può fornire più funzionalità 'varie'.
E poi dovrò affrontare anche l'argomento dei gestori di template tipo
Smarty.
Diamine quant'è vasto PHP :-P

 E` come se definissi due funzioni con lo stesso nome.
Concettualmente è fattibile. A proposito! L'overloading delle funzioni
è stato aggiunto con PHP5 oppure non si possono dichiarare ancora
funzioni con lo stesso nome?

 assegnandogli un paio di CSS e gestendo in automatico la paginazione?
Esiste esiste, io ho fatto una classe molto semplice che data una query 
sql ti genera una tabella con il risultato della query.
Non implemente il paginatore, se hai voglia di migliorare i sorgenti 
aggiungendo anche quella funzione ben venga.
Ti copio incollo l'intero codice delle due classi, non e' lunghissimo.
La classe base e' pagina.php che serve per generare codice html, la 
classe table query fa le pagine con il risultato della query.
Classe TableQuery
**************************************************************************
<?php
require_once('pagina.php');
class tableQuery extends pagina
   {
   /**
    * connessione al db
    */	
	private $conn;
	/**
	 * query da eseguire
	 */	 	
   private $sql;
   /**
    * aggiungere colonne di ins/mod/del ?
    */	
   private $addCol;
   /**
    * indirizzo per link inserisci/modifica/cancella
    */	
   private $link;
   /**
    * campo chiave primaria per link inserisci/modifica/cancella
    */	
   private $pk;
   public $borderTable;
   public $tableWidth;
   public $cellspacing;
   public $cellpadding;
   public $tableTitle;
   public $msg_prima;
   public $msg_dopo;
   function __construct($sql,$conn)
     {
     $this->sql  = $sql;
     if (get_resource_type($conn) != 'pgsql link')
        die('Risorsa non valida. Specificare una risorsa di tipo pgsql 
link');
     $this->conn = $conn;
     // setto parametri di default della tabella
     $this->borderTable  = 1;
     $this->tableWidth   = '';
     $this->cellpadding  = 4;
     $this->cellspacing  = 4;
     $this->tableAlign   = 'left';
     $this->addCol       = FALSE;
     $this->msg_prima    = FALSE;
     $this->msg_dopo     = FALSE;
     }
   private function getTable()
     {
     $tab = '<div class="table_query">'."\n";
     $result = pg_query($this->conn,$this->sql);
     if ($result)
       {
       $tab .= '<table cellpadding="'.$this->cellpadding.'" 
cellspacing="'.$this->cellspacing.'" border="'.$this->borderTable.'" 
width="'.$this->tableWidth.'">';
       if ( $this->addCol )
         $tab .= '<caption><strong><a href="'.$this->link.'">Inserisci 
riga</a></strong></caption>'."\n";
       // stampo riga di intestazione con i nomi dei campi
       $tab .= '<tr>'."\n";
       for ($i=0; $i<pg_num_fields($result); $i++ )
         $tab .= ' <th>'.strtoupper(pg_field_name($result,$i)).'</th>'."\n";
       if ( $this->addCol )
         $tab .= '<th>MOD</th><th>DEL</th>';
       $tab .= '</tr>'."\n";
       // memorizzo i dati in un array associativo
       while ($row = pg_fetch_assoc($result))
         {
         ($i++%2) ? $class='rd' : $class='rp';
         $tab .= ' <tr class="'.$class.'">'."\n";
         // stampo le celle del risultato
         foreach ($row as $data)
           $tab .= ' <td>'.$data.'</td>'."\n";
         if ( $this->addCol )
           $tab .= $this->getLink($row);
         $tab .= '</tr>'."\n";
         }
       $tab .= '</table>';
       }
     $tab .= '</div>' . "\n";
     $this->table = $tab;
     }
   private function getLink($row)
     {
     $col = ' <td><a 
href="'.$this->link.'?act=mod&amp;'.$this->pk.'='.$row[$this->pk].'">Mod</a></td>'."\n";
     $col .= ' <td><a 
href="'.$this->link.'?act=del&amp;'.$this->pk.'='.$row[$this->pk].'">Del</a></td>'."\n";
     return $col;
     }
   public function insModDel($link, $pk)
     {
     $this->addCol = TRUE;
     $this->link = $link;
     $this->pk   = $pk;
     }
   public function print_htlm($title)
     {
     $this->title = $title;
     $this->_apri_html();
     if ($this->msg_prima)
       $this->html .= $this->msg_prima;
     $this->getTable();
     if ($this->msg_dopo)
       $this->html .= $this->msg_dopo;
     $this->html .= $this->table;
     $this->_chiudi_html();
     echo $this->html;
     }
   public function msg_prima($testo)
     {
     $this->msg_prima = $testo;
     }
   public function msg_dopo($testo)
     {
     $this->msg_dopo = $testo;
     }
   }
?>
Per utilizzare la classe
$sql = 'select * from studenti';
$p = new tableQuery($sql,$connessione);
$p->print_htlm('Titolo della pagina');
Classe pagina
*********************************************************************
<?php
class pagina
{
	/**
	 * DTD della pagina, i valori validi sono transitional, frame, default
	 */
	private $dtd;
   /**
   * Testo del body
   */
	protected $body;
	/**
	 * Codice html della pagina
	 */
	private $html;
   /**
   * Foglio di stile da utilizzare come file esterno
   */
	private $css_file;
	/**
	 * Javascript da includere come file esterno
	 */
	private $js_file;
	/**
	 * Css inline
	 */
	private $css_inline;
	/**
	 * Javascript inline
	 */
	private $js_inline;
	/**
	 * Elementi aggiuntivi di head
	 */
	private $head;
         /**
         * Titolo della pagina
         */
	private $title;
	/**
	 * Costruttore, richiede il titolo da dare alla pagina
	 *
	 * @param string $titolo
	 */
	function __construct($titolo,$dtd='strict')
	{
		$this->title = $titolo;
		$this->dtd   = $dtd;
	}
	/**
	 * Setta l'html della pagina, richiede il DTD da utilizzare
	 *
	 * @param string $dtd
	 */
	protected function _apri_html()
	{
		switch ($this->dtd)
		{
			case 'transitional':
				$this->html = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 
Transitional//EN" "
http://www.w3.org/TR/html4/loose.dtd
">';
				break;
			case 'frame':
				$this->html = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 
Frameset//EN" "
http://www.w3.org/TR/HTML4.01/frameset.dtd
">';
				break;
			default:
				$this->html = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
"
http://www.w3.org/TR/html4/strict.dtd
">';
				break;
		}
		$this->html .= "\n" . '<html>';
		$this->html .= "\n" . ' <head>';
		$this->html .= "\n" . '  <meta http-equiv="Content-Type" 
content="text/html; charset=iso-8859-15">';
		$this->html .= "\n" . '  <meta http-equiv="Content-Type" 
content="text/html; charset=iso-8859-15">';
		$this->html .= "\n" . '  <meta name="GENERATOR" 
content="ClassePagina_v1">';
		$this->html .= "\n" . '  <meta name="AUTHOR" content="Mauro Rainis">';
   	        $this->html .= "\n" . '  <title>' . $this->title . '</title>';
		if ( isset($this->css_file) )
		  $this->html .= "\n  " . $this->css_file;
		if ( isset($this->js_file) )
		  $this->html .= "\n  " . $this->css_file;
		if ( isset($this->head) )
		  $this->html .= "\n  " . $this->head;
 
		$this->html .= "\n" . ' </head>';
		$this->html .= "\n" . '<body>';
		//$this->html .= "\n";
	}
 
	/**
	 * Chide body e html della pagina
	 *
	 */
	protected function _chiudi_html($html='')
	{
		if ($html)
		  $this->html .= "\n" . $html;
		$this->html .= "\n" . '</body>';
		$this->html .= "\n" . '</html>';
	}
	/**
	 * Aggiunge un riferimento ad un css esterno
	 *
	 * @param string $css nome del file da includere
	 */
	public function includeCss($css)
	{
		$this->css_file .= '<link rel="stylesheet" type="text/css" 
href="'.$css.'">'."\n  ";
	}
 
	/**
	 * Aggiunge un css inline
	 *
	 * @param string $css testo del css da includere
	 */
	public function addCss($css)
	{
		$this->css_inline .= '  <style type="text/css">'."\n";
		$this->css_inline .= '  '.$css."\n";
		$this->css_inline .= '  </style>'."\n";
   }
 
         /**
	 * Aggiunge un riferimento ad un javascript esterno
	 *
	 * @param string $js nome del file da includere
	 */
	public function includeJs($js)
	{
		$this->js_file .= '<script type="text/javascript" 
src="'.$js.'"></script>'."\n  ";
	}
	/**
	 * Aggiunge un js inline
	 *
	 * @param string $css testo del js da includere
	 */
	public function addJs($js)
	{
		$this->js_inline .= '  <script type="text/javascript">'."\n";
		$this->js_inline .= '  '.$js."\n";
		$this->js_inline .= '  </script>'."\n";
         }
 
	/**
	 * Aggiunge elementi di head
	 *
	 * @param string $head testo da aggiungere a head
	 */
	public function addHead($head)
	{
		$this->head .= $head."\n";
         }
	/**
	 * Aggiunge contenuti al body della pagina
	 *
	 * @param string $txt
	 */
	public function addBody($txt)
	{
		$this->body .= $txt."\n";
	}
	/**
	 * Aggiunge un paragrafo al body della pagina
	 *
	 * @param string $txt
	 */
	public function addP($txt)
	{
		$this->body .= '<p>'.$txt."</p>\n";
	}
	/**
	 * Aggiunge un div al body della pagina
	 *
	 * @param string $txt
	 */
	public function addDiv($txt)
	{
		$this->body .= '<div>'.$txt."</div>\n";
	}
 
	/**
	 * Fa echo della pagina completa
	 *
	 */
	public function printPage()
	{
		echo $this->getPage();
	}
 
	/**
	 * Ritorna la pagina completa
	 *
	 * @return string
	 */
	public function getPage()
	{
		$this->_apri_html();
		$this->html .= $this->css_inline;
		$this->html .= $this->js_inline;
		$this->html .= $this->body;
		$this->_chiudi_html();
		return $this->html;
	}
}
/*
// Codice per testare la classe
  // $p = new pagina('Pagina web','transitional');
  $p = new pagina('Pagina web');
  $p->includeCss('pippo1.css');
  $p->includeCss('pippo2.css');
  $p->addCss('div{border: 1px solid red;}');
  $p->includeJs('javascript_file1.css');
  $p->includeJs('javascript_file2.css');
  $p->addJs('function prova(){alert(prova);}');
  $p->addBody('Ciao mondo<br>');
  $p->addBody('<div>Altra riga di body </div>');
  $p->printPage();
*/
?>

  $p = new pagina('Pagina web');
Carino, semplice e utile!
Anch'io, mentre sviluppavo più siti, mi sono costruito un mio 
"framework" (compresa la funzione di cui parla Pictor che, data una sql, 
mostra la tabella con la paginazione), anche perché mi dava fastidio 
fisicamente avere lo stesso codice in più moduli. Purtroppo non l'ho 
implementato con le classi e il codice andrebbe sicuramente rivisto per 
renderlo più generico e magari con ajax...
Certo che se non lo si fa di lavoro diventa improbo star dietro a tutte 
queste cose.
-- 
Jax

 queste cose.
E' vero ... questa classe l'ho sistemata per un corso di applicazioni 
web che tengo in Universita' .... prima non c'era un bit di commenti :-)
Prossimamente la migliorero' ulteriormente e magari la posto su qualche 
sito.
ciao
Mauro

 
Con pear ho creato una classe che data una query sql mi resituisce o un 
dbgrid con impaginazione e ordinamento colonne oppure l'output su excel.
Se ti interessa il codice, posso postarlo.
	Francesco

 Se ti interessa il codice, posso postarlo.
Come hai gestito la formattazione dei campi? Io ci ho pensato su, ho 
provato a basarmi sul tipo di campo mysql, ma alla fine ho optato per 
crearmi una mia "anagrafica campi", dove definisco un tipo più specifico 
di quello in mysql, in modo da avere un output html che sia significativo...
Faccio un esempio tipico, un campo id_qualcosa che si collega con l'id 
di una tabella. Non puoi certo mostrare l'id nudo e crudo...
Il modo più ovvio di gestire questa cosa è fare direttamente nell'sql la 
join alla tabella mediante l'id, ma in questo modo risulta difficile 
(anzi, impossibile) generalizzare la query.
Allora, nella mia anagrafica campi, mi sono definito quel campo come 
tipo personalizzato = "id", e in un altro campo generico "param" = nome 
della tabella dove reperire la descrizione.
Esempio: quando trovo una colonna che si chiama id_pippo, controllo il 
tipo, vedo che è "id", quindi so che devo andare a prendere il campo 
"descrizione" della tabella "pippo", e mostro quello al posto del valore 
del campo nella <table>.
Considerate che mi baso sulla stessa anagrafica campi per sapere che 
tipo di input generare (text, select, checkbox...); è stato un po' 
complicato gestire le varie eccezioni che mi si presentavano di caso in 
caso, però per ora funziona bene.
E' un modo troppo cervellotico secondo voi? Come avete affrontato la 
problematica?
-- 
Jax

 
Dipende da caso a caso. Nel mio esempio avevo la necessità, data una 
query di mostrare il risultato in una tabella con paging e ordinamento 
ed esportare anche il risultato su excel e, questa scelta, mi sembrava 
la via più breve!
	Francesco

 con lo stesso nome?
Cosa intendi per overloading? ;)
In una classe puoi definire un metodo con lo stesso nome di uno della 
classe padre, e lo sovrascrivi (e puoi richiamare quello del genitore con 
parent::nomemetodo())
Non puoi sovrascrivere una funzione nello scope globale con un'altra con 
lo stesso nome (ti da` un fatal error l'interprete)
Se intendi il polimorfismo, non ha senso in PHP, visto che "non ci sono i 
tipi".
Bye.

 con lo stesso nome?
Cosa intendi per overloading? ;)


 tipi".
No intendevo proprio sovrascrivere una funzione globale come può
essere (esempio a caso) str_len(), facendo
function str_len() {
 ////
}
Anche se cercavo addirittura un modo per definire la funzione in modo
che sfruttasse quella definita da PHP ma apportandone modifiche.
Una cosa tipo
function str_len($str) {
    return str_len( trim($str) );   // E qua usa quella standard
}
Insomma: fantascienza! ^_^

 Insomma: fantascienza! ^_^
Più che altro un modo ottimo per indurre al suicidio chi dovrà mantenere 
il codice in futuro... te stesso incluso :)
Le funzioni standard *devono* comportarsi tutte nello stesso modo, pensa 
che casino se ognuno se le personalizzasse...
-- 
Jax

Vi prendo spunto, grazie :-)
Se aggiungo qualcosa lo posto.

Certo che può interessarmi :-)
Sicuramente sarà utile a molti!

 problematica?
E' cervellotica perchè non sarà mai versatilissima.
Ma d'altronde non mi viene in mente niente di meglio.
Magari farei una cosa più 'carina' (imho) tipo, nella query, cambiare
il nome dei campi in base a cosa sono e aggiungendo un prefisso.
Per esempio una query come:
SELECT Nome, Cognome, Attivo FROM Utenti WHERE .....
potrebbe diventare
SELECT txt_Nome, txt_ Cognome, bol_Attivo FROM Utenti WHERE .....
La funzione/classe va a parsare il nome del campo e si imposta secondo
il prefisso (un txt mostrerà un "input text", un bol mostrerà "Sì/No"
in base al suo valore).
E' come basarsi sui tipi degli attributi ma con più versatilità, visto
che i prefissi li decidiamo noi e possiamo crearci più varianti (come
txtPWD per le password, txtHID per degli "input hidden").
Un pò come hai fatto tu, mi pare di aver capito.
Di meglio non mi viene in mente.

 SELECT txt_Nome, txt_ Cognome, bol_Attivo FROM Utenti WHERE .....
Avevo fatto così anch'io all'inizio (agendo non sulle singole query ma 
direttamente sui nomi dei campi).
Poi ho cominciato ad avere a che fare con troppe variabili da gestire su 
un nome di campo e ho preferito adottare la tabella dei campi 
(indubbiamente più lenta).
Per esempio la tabella collegata ad un campo id, il fatto che quel campo 
sia obbligatorio e/o protetto in una maschera di inserimento, 
l'intestazione della sua colonna in una tabella, la lunghezza di una 
eventuale edit su quel campo...
Facendo così ho anche, in qualche modo, astratto le informazioni dal 
tipo di database: se un domani volessi passare a Postgre, per esempio, 
non sarei legato a funzioni del tipo mysql_field_type, che magari in 
postgre non ci sono (ok, in questo caso c'è :)) o che ritornano 
risultati diversi da quelli che ti aspettavi.
-- 
Jax