• ModSenior

    [GUIDA] CodeIgniter

    Cos'è CodeIgniter
    CodeIgniter è un framework php che utilizza il pattern MVC.

    Maggiori informazioni sul pattern MVCle trovi qui (All'interno di questa guida viene data per scontata la conoscenza teorica del pattern MVC):
    http://www.giorgiotave.it/forum/scripting-e-risorse-utili/189022-guida-pattern-mvc.html

    Perchè scegliere CodeIgniter
    Esistono moltissimi framework, tra i più famosi abbiamo indubbiamente: Zend Framework, Symfony e CakePHP.
    CodeIgniter a differenza dei framework appena citati è indubbiamente più leggero e consente di ottenere performance molto superiori, al costo di avere però un framework più semplificato e con delle librerie che in altri framework troviamo già a nostra disposizione, e qui invece no(Molte sono comunque disponibili nella rete, ma non sono ufficiali).

    Come framework è quello che, a mio avviso, si riesce a capire in tempi veramente minimi. Questo anche grazie ad un ottima documentazione ed alla presenza di video tutorial(In inglese) che ti spiegano come iniziare ad utilizzarlo.

    È il miglior framework?
    Il migliore in assoluto non credo esista, dipende cosa devi fare, e anche da quanto tempo lo utilizzi.
    Se sei indeciso tra CodeIgniter ed un altro framework, la cosa migliore è iniziare ad utilizzarli entrambi e vedere con quale si hanno meno problemi.

    Dove posso scaricarlo
    È possibile scaricare CodeIgniter daqui:
    ellislab.com/codeigniter

    Iniziamo ad indicare come funziona
    CodeIgniter contiene 2 directory principali ed un file index.php.
    Appena scaricato CodeIgniter troviamo anche il file relativo alla licenza e la documentazione(Reperibile anche sul sito online).

    Iniziamo col dire che tutte lerichieste da parte dell'utente vengono fatte al file index.php,avremo quindi url del tipo index.php/registrati
    Sarà ovviamente possibile utilizzareil mod rewrite per elimianre la parte index.php e rendere gli url piùuser-friendly
    Le 2 directory sono invece applicatione system.

    System
    Qui si trovano i file di CodeIgniter che si occupano di far funzionare il tutto correttamente, di norma non vanno modificati.
    Se vogliamo riscrivere una parte di CodeIgniter, perchè di base non si adatta alle nostre esigenze è possibile farlo estendendo le classi utilizzate da CodeIgniter senza modificare i file presenti in system (Spiegherò più avanti come fare).

    Application
    Questa cartella è la nostra area di sviluppo, che contiene al suo interno varie cartelle, sembrano tante a prima vista ma non preoccupatevi le analizzeremo con un esempio pratico.
    In config troviamo i file relativi allaconfigurazione di CodeIgniter, quelli che interessano a noi per ilmomento sono 2: config.php e database.php

    In database.php dobbiamo impostare iparametri di connessione al nostro database.
    In config.php troviamo le impostazionidella nostra applicazione, basta leggere i commenti per capire qualicampi modificare e come modificarli, trattiamo brevemente i piùimportanti:

    base_url Deve contente un url del tipohttp://www.sito.ext/ ATTENZIONE: Lo slash finale deve essere presente
    index_page Se impostato vuoto otteniamourl del tipo sito.ext/controller/method invece disito.ext/index.php/controller/method
    encryption_key Prima o poi torneràutile utilizzare il crypt per cui è meglio inserire la chiave sin dasubito, per evitare di dimenticarlo
    Nella parte relativa alla sessioneconsiglio di abilitare il crypt dei cookie per ragioni di sicurezza.

    Routing
    Il routing di CodeIgniter funziona nel seguente modo quando l'utente va all'url sito.ext/saluta/amichevolmente/pippo Verrà eseguito il metodo amichevolmente del controller saluta, e gli verrà passato come parametro pippo.

    ***** PARTE 1 - La nostra primaapplicazione *****
    Controller
    I controller vanno creati in/application/controllers ed il nome del file deve essere uguale al nome della classe al suo interno.
    Creiamo il file saluta.php ed al suo interno mettiamo:

    [php]
    <?php if ( ! defined('BASEPATH'))exit('No direct script access allowed');

    class Saluta extends CI_Controller
    {
    public function amichevolmente($a =false)
    {
    $data = array();
    $data['saluta_a'] = $a;

        $this->load->view('saluta_amichevolmente',$data);
    }
    

    }
    [/php]

    Il controller si limita a prendere ininput un parametro ($a) e lo inserisce in un array che passeremo alview.
    NOTA: Nel nome del file view non vàscritto .php

    Il View
    I file views vanno inseriti in/application/views/ nel nostro caso creiamo il file saluta_amichevolmente.php ed al suo interno scriviamo:
    [php]
    <?php
    echo 'Ciao '.$saluta_a;
    [/php]

    In questa maniera andando all'indirizzo:
    sito.ext/saluta/amichevolmente/pippo
    Visualizzeremo:
    Ciao pippo

    Il view ottiene dal controller esclusivamente il contenuto dell'array $data, tutte le altre variabili presenti nel controller non sono presenti nel view.

    Vantaggi di questo approccio
    Questo approccio ci consente di sapere subito in quale parte di codice intervenire quando vogliamo fare una modifica, e consente inoltre a più persone di lavorare contemporaneamente, ad esempio una persona può scrivere il controller ed un'altra può creare il view.

    Il model
    L'esempio appena fatto è molto banale,ma è fondamentale capire i compiti del view e del controller.
    A questi 2 componenti si aggiunge il model, che viene utilizzato dal controller per utilizzare una base di dati (Un database).
    Dobbiamo quindi pensare che c'è una divisione dei compiti tra questi 3 componenti, con il controller che riceve i dati di input, in base ad essi effettua le chiamate al model, ed infine richiama il view per mostrare i dati di output.
    CodeIgniter contiene un layer di astrazione del database, e supporta si la tradizionale struttura dove possiamo scrivere la nostra query, sia il pattern Active Record.
    Io preferisco utilizzare la maniera tradizionale, e per una guida penso sia anche più utile trattare da questo punto di vista.

    Creiamo ora il nostro primo model, chechiameremo blog_model. Per fare ciò creiamo il file blog_model.phpin /application/models/ e scriviamo:
    [php]
    class Blog_model extends CI_Model {

    function __construct()
    {
        parent::__construct();
    }
    
    function getUtenti()
    {
        $query =$this->db->query("SELECT * FROM utenti");
        if($query->num_rows == 0)
        return false;
       return $query->result();
    }
    

    }
    [/php]

    La tabella utenti possiamo crearla con questa query:

    
    CREATE TABLE IF NOT EXISTS `utenti` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `nome_utente` varchar(50) CHARACTERSET latin1 NOT NULL,
      `password` varchar(32) CHARACTER SETlatin1 NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8AUTO_INCREMENT=1 ;
    
    

    Supponiamo di voler salutare tutti gliutenti presenti in tabella, modifichiamo il controller che avevamo precedentemente creato saluta.php in questo modo:
    [php]
    <?php if ( ! defined('BASEPATH'))exit('No direct script access allowed');

    class Saluta extends CI_Controller
    {
    public function amichevolmente($a =false)
    {
    $data = array();
    $data['saluta_a'] = $a;

        $this->load->view('saluta_amichevolmente',$data);
    }
    public function tutti()
    {
        $data = array();
        $this->load->model('blog_model');
        $data['saluta_a'] =$this->blog_model->getUtenti();
        
        $this->load->view('saluta_amichevolmente_tutti',$data);
    }
    

    }
    [/php]

    Per caricare il model che abbiamoscritto è necessario scrivere:
    $this->load->model('blog_model');

    Una volta fatto ciò, potremoutilizzarlo dal controller facendo $this->blog_model

    Creiamo adesso il nostro view:saluta_amichevolmente_tutti.php scrivendo:
    [php]
    <?php
    if($saluta_a)
    {
    foreach($saluta_a AS $a)
    {
    echo 'Ciao '.$a->nome_utente.'<br/>';
    }
    }
    else
    {
    echo 'Non c'è nessuno da salutare:(';
    }
    [/php]
    Nel model avevo messo che restituisce false nel caso in cui la tabella è vuota, per cui aggiungiamo un if per verificare se la tabella era vuota o meno. Nel caso non fosse vuota, scorriamo l'array e salutiamo singolarmente tutti.

    NOTA: $query->result restituisce unarray di oggetti, sono disponibili altri metodi per restituire irecord sotto forma di array.

    ***** PARTE 2 - Model nel dettaglio *****
    Abbiamo fatto una breve panoramica di come creare la nostra prima applicazione con CodeIgniter.
    Vediamo ora di costruire un model più completo, utilizzando sempre la tecnica tradizionale per costruire le nostre query.
    Apriamo il nostro file blog_model.php e scriviamo:
    [php]
    class Blog_model extends CI_Model {

    function __construct()
    {
        parent::__construct();
    }
    
    function getUtenti()
    {
        $query =$this->db->query("SELECT * FROM utenti");
        if($query->num_rows == 0)
        return false;
       return $query->result();
    }
    function getUtente($id)
    {
        $query =$this->db->query("SELECT * FROM utenti WHERE id = $idLIMIT 1");
        if($query->num_rows == 0)
        return false;
       return $query->row();
    }
    

    }
    [/php]
    Abbiamo creato il metodo getUtente che permette di ottenere i dati relativi all'utente avente un determinato id. Da notare che invece di utilizzare $query->result() abbiamo utilizzato $query->row()
    Questo perchè $query->result()restituisce un array, e viene utilizzato quando la query restituisce più record, ma nel caso del singolo utente in cui sappiamo che restituisce un unico record possiamo utilizzare $query->row() che ci restituisce l'oggetto direttamente invece di avere un array di un elemento.

    Un controller può utilizzare quanti models vuole senza limitazioni di alcun genere, e solamente il models dovrebbe comunicare con il database. Si possono effettuare query anche nel controller o nel view, ma è altamente sconsigliato in quanto si perdono tutti i benefici di un pattern MVC, e non avrebbe senso utilizzarlo.
    Per effettuare l'escape dei caratteri per le query ed evitare SQL INJECTION è possibile utilizzare$this->db->escape(), nel nostro model l'ho omesso in quanto trattando un ID che dovrebbe essere numerico, si presuppone che il controller lo abbia adeguatamente controllato prima di spedirlo al model. In campi di tipo stringa invece bisogna utilizzare$this->db->escape() per evitare problemi.

    ***** PARTE 3 - Gli Helper *****
    È possibile caricare uno degli helper che CodeIgniter ci mette a disposizione inserendo nel controller:$this->load->helper('nome_helper'); ad esempio possiamo fare:

    $this->load->helper('url');

    Ed avere cosi a disposizione numerose funzioni per semplificarci la vita (Un elenco completo delle funzioni di questo helper è disponibile qui: ellislab.com/codeigniter/user-guide/helpers/url_helper.html)
    Se vogliamo ad esempio creare un collegamento nel view invece di fare: <a href="http://example.com">Click Here</a>
    Possiamo fare:
    anchor('http://example.com', 'ClickHere')

    Il vatanggio degli helper è quello chese vuoi modificare tutti i tag a del sito per aggiungere qualcosa,invece di modificare ogni singolo tag puoi intervenire modificando lafunzione.
    Poichè gli helper sono molto semplici da utilizzare non mi dilungo oltre nelle spiegazioni, basta far riferimento alla documentazione per vedere quali CodeIgniter ci mette a disposizione.
    Possiamo crearne anche altri aggiuntivi, in /application/helpers/ gli helper devono avere un nome del tipo thedarkita_helper.php, ed al suo interno possiamo inserire la nostra funzione:
    [php]
    function helper_di_prova()
    {
    echo 'Io sono un helper di prova';
    }
    [/php]
    Basterà carica dal controller con:
    $this->load->helper('thedarkita');

    Per poterla utilizzare dove si vuole richiamandola con helper_di_prova()

    ***** PARTE 4 *****
    Prossimamente disponibile...

    Aggiungerò altre cose nella guida,modificando questo post pian piano, visto che è un argomento moltolungo da trattare. Ho cercato di spiegare le cose più basilari, inmaniera più breve possibile e senza dilungarmi molto sulle possibilipersonazzazioni che CodeIgniter ci consente.
    Se avete dubbi o domande, potete rispondere a questa discussione. E se preferite che aggiungiamo anche una guida più pratica con un esempio, possiamo decidere insieme cosa realizzare.


  • User Newbie

    ciao mi farebbe piacere mi se puoi darmi una mano con un progetto che sto cercando di ultimare fatto da un azienda e scritto tutto con
    [h=2]CodeIgniterti sarei davvero grato ho provato ad aggiungerti su skype o nel caso dammi indicazioni tu

    grazie ancora

    claudio


  • User Attivo

    Ciao Dark!

    Mi sto cimentando su CodeIgniter, me lo hanno consigliato più persone e con questo secondo tutorial in Italiano che trovo o ci provo adesso o mai più.

    Le prime domande:

    1. Alla pagina di download fanno scegliere tra la versione stable (attualmente 2.2.1) e quella in sviluppo attivo (attualmente 3.0 RC2).
      Hai idea se cambia molto o hai suggerimenti su quale scegliere?
      Dovrebbe servire per un sito definibile come "CMS" con iscrizione utenti e varie funzioni che dovrei completare entro dicembre.

    2. Su $this->db->escape().
      Si utilizza inserendo tra le parentesi la variabile da verificare ( tipo $this->db->escape($username) ) ?
      Se si, è possibile anche con unico comando fare l'escape di più variabili ($this->db->escape($username, $valore1, $valore2)) ?

    Inoltre, per quanto riguarda $_GET e $_POST, è valido:
    $username = (isset($_POST['username'])) ? trim($_POST['username']) : '';
    if (!get_magic_quotes_gpc()) { $username = addslashes($username); }
    $this->db->escape($username);

    O l'uso di $this->db->escape($username) permette di ignorare il controllo magic_quotes_gpc?

    Ottima guida come sempre, con l'altro sull'area privata ho iniziato con PHP, con questa ho le idee molto più chiare su CI e MVC. 😄


  • ModSenior

    Ciao,
    ti rispondo per punti:

    1. Puoi già utilizzare la versione 3.0 che ha solo problemi minori, ed è ormai questione di poco tempo per la stable.

    2. Devi utilizzarlo nella query, ogni valore che passi per fare ad esempio:

    WHERE nome = $username
    

    Deve essere cosi:

    WHERE nome = **$this->db->escape(**$username)
    

    NOTA: Non è necessario che metti tu manualmente gli apici, la funzione di occupa anche di questo aspetto oltre che dal garantirti la protezione da SQL INJECTION, per cui non sono necessarie operazioni con addslashes e simili.
    Fermo restando che se utilizzi l'ORM di codeigniter, invece di fare manualmente le query, non è necessario occuparsi di questo aspetto, in quanto viene già eseguito automaticamente.


  • User Attivo
    1. Perfetto, inizio direttamente con la documentazione della 3 allora, sperando che entro dicembre ci sia la stable.
    2. Ok, quindi quello basta per evitare gli altri controlli (a parte quelli specifici).

    Onestamente mi sfugge il suggerimento sull'ORM. Ho provato a fare una ricerca ma sembra un qualcosa da aggiungere e ci sarebbe più scelta (datamapper, doctrine, gas, ecc..). Però dal tuo consiglio sembrava un qualcosa di già incluso nel pacchetto di CI.

    Grazie!


  • ModSenior

  • User Attivo

    Nel settaggio dell'encryption key, come deve essere la chiave nel file config?
    Va bene una di quelle proposte in questo sito: randomkeygen.com
    Dove è indicato CodeIgniter Encryption Keys (Can be used for any other 256-bit key requirement)
    ?

    Impostata la chiave, CI procede in automatico a criptare cookie e sessioni?

    Grazie!


  • ModSenior

    Per fare il crypt delle sessioni, devi impostare il valore nel file di configurazione. Mentre i normali cookie, sono comunque non codificati.


  • User Attivo

    L'unica che non capisco è l'uso degli helper. Non si possono fare le stesse operazioni anche all'interno delle classi, evitando gli helper?


  • ModSenior

    Un helper puoi utilizzarlo anche in una view, in maniera diretta ad esempio. Poi è normale che volendo si possa fare anche utilizzando una classe/libreria, ma dal punto di vista logico sono per usi diversi


  • User Attivo

    Chiarissimo,

    Grazie!


  • User Attivo

    E' normale che un template a se stante si vede correttamente, mentre se messo in una view mi esce fuori con margini in alto e in basso?
    Sapete dirmi come posso risolverlo?

    Grazie!