Progetto Step by Step CodeIgniter – I Controller
In questo passaggio del tutorial a CodeIgniter vediamo finalmente l’elemento del framework che si occupa della logica dell’applicazione, e cioè il controller. Come vedremo questo elemento è quello che viene eseguito direttamente dall’utente ed è ciò che mette in comunicazione i dati (e cioè i modelli) con l’output (le viste).
CodeIgniter infatti, tramite la classe Routing, si occupa di leggere l’URL digitato e indirizzare all’apposito controller il metodo da eseguire. Ad esempio, digitando l’indirizzo http://www.dominio.com/index.php/nome_controller/nome_metodo/ CodeIgniter andrà a richiamare il controller nome_controller ed eseguirà il metodo nome_metodo. Se invece viene omesso nome_metodo verrà richiamato il metodo di default chiamato index.
Dal punto di vista del codice, un controller non è altro che una classe PHP che eredita dalla classe nativa Controller. Pertanto la sintassi base sarà:
class Mia_classe extends Controller {
function Mia_classe() { //questo è il costruttore
parent::Controller(); //richiamo il costruttore della classe “Controller”
}
function index() {
//funzione richiamata di default
}
function mia_funzione() {
//metodo personalizzato
}
}
i controller vanno di norma salvati nella cartella /system/application/controllers, mentre il nome del file dovrà coincidere col nome della classe, quindi nell’esempio precedente questo dovrà chiamarsi mia_classe.php – Notare l’eliminazione delle maiuscole richiesta dal framework.
Tornando alla nostra applicazione, dato che abbiamo tre entità in gioco avremo bisogno di tre file separati. Ciò non è la regola, in quanto i controller vanno intesi più che altro come azioni da compiere. Nel nostro caso però, dato che andremo ad operare ogni volta su un elemento preciso in maniera abbastanza indipendente, ho preferito separarli in tre controller distinti anziché uno unico.
Partiamo dal controller delle tipologie (che sarà analogo a quello degli stati).
Prendendo come spunto il modello qui sopra, il nostro controller per gli stati sarà del tipo:
class Statuses extends Controller {
function Statuses() {
parent::Controller();
$this->load->model(‘status_model’);
}
function index() {
//funzione richiamata di default
}
}
Come vedete nel costruttore Statuses() vado a caricare il modello status_model che mi servirà all’interno del controller.
Ora andiamo a popolare il metodo index() che ci servirà per la lista completa degli stati. Per farlo aggiungiamo:
$data[‘statuses’] = $this->status_model->get(); $this->load->view(‘list_statuses’, $data);
La prima riga si occupa di eseguire il metodo get del modello status_model e a salvarne l’output nell’array $data. Nella seconda riga invece andiamo a caricare la vista list_statuses passando i dati da visualizzare. CodeIgniter andrà a cercare la vista list_statuses.php all’interno della cartella /system/application/views. Vedremo in seguito come realizzare la vista, ma per quanto riguarda il Controller abbiamo già ottenuto quello che ci serve.
I prossimi metodi che ci servono sono quelli per interagire col sito. Infatti abbiamo previsto la possibilità di aggiungere, modificare o rimuovere stati direttamente dal sito senza dover accedere al database.
Presupponiamo già di avere un form che invii tramite post i campi necessari (andremo a realizzarlo in una delle viste). Il nostro metodo che chiameremo add() sarà:
function add() {
if ($this->input->post(‘submit’) {
//ho fatto il submit...
$insert[‘name’] = $this->input->post(‘name’);
$this->status_model->add($insert);
return $this->index();
} else {
//non ho fatto il submit quindi mostro il form...
$this->load->view(‘add_status’);
}
}
Innanzitutto vedo se ho già fatto il submit o se invece devo mostrare il form per l’inserimento. Nel primo caso leggo i dati tramite $this->input->post('nome') che è il metodo offerto dalla libreria Input di C.I. per leggere i dati in POST, richiamo il metodo add() del modello per seguire l’inserimento. Una volta concluso mostro la lista degli articoli richiamando il metodo di default $this->index()
La funzione edit() è molto simile, con la differenza che dovendo modificare un preciso stato dovrò specificarlo tramite id. Per farlo basta passare quest’ultimo come parametro al nostro metodo. Nel browser ciò è possibile nella forma: http://www.dominio.com/index.php/mio_controller/metodo/parametro1/parametro2/ etc…
Il metodo diventa quindi:
function edit($id) {
if ($this->input->post(‘submit’) {
//ho fatto il submit...
$insert[‘name’] = $this->input->post(‘name’);
$this->status_model->edit($insert, $id);
return $this->index();
} else {
//non ho fatto il submit quindi mostro il form...
$data[‘status’] = $this->status_model->get_single($id);
$this->load->view(‘add_status’, $data);
}
}
Come vedete l’unica differenza rispetto all’inserimento sta che nel metodo edit() del modello devo passare anche l’id dell’elemento da modificare. Devo inoltre pre-popolare il form con i valori già esistenti. Posso farlo tramite il metodo get_single($id) del nostro modello, che ci permette di leggere un singolo stato e passarne i dati alla vista.
L’ultimo metodo è quello destinato alla cancellazione di uno stato, ed è molto semplice:
function delete($id) {
$this->status_model->delete($id);
return $this->index();
}
Come avrete sicuramente visto non viene effettuato nessun controllo sulla validità dei dati. Questo però sarà facilmente integrabile in un secondo momento tramite ulteriori controlli e la libreria Validation presente in CodeIgniter.
Il controller Types sarà identico a quanto appena visto, con l’unica differenza di nomenclatura tra stati e tipi. Basterà quindi fare copia-incolla dei files e modificare quanto serve.
Anche il controller relativo agli items sarà molto simile, con la differenza che avremo più campi da gestire (non solo il nome) e avremo bisogno di tutti e tre i modelli. Il controller completo è il seguente:
class Items extends Controller {
function Items() {
parent::Controller();
$this->load->model('item_model');
$this->load->model('type_model');
$this->load->model('status_model');
}
function index() {
//lista degli elementi nel database
$data['items'] = $this->item_model->get();
$this->load->view('list_items', $data);
}
function add() {
if ($this->input->post('submit')) {
$insert['name'] = $this->input->post('name');
$insert['code'] = $this->input->post('code');
$insert['description'] = $this->input->post('description');
$insert['position'] = $this->input->post('position');
$insert['type_id'] = $this->input->post('type_id');
$insert['status_id'] = $this->input->post('status_id');
$insert['about_the_status'] = $this->input->post('about_the_status');
$this->item_model->add($insert);
return $this->index(); //torno all'indice...
} else {
$data['types'] = $this->type_model->get();
$data['statuses'] = $this->status_model->get();
$this->load->view('add_item', $data);
}
}
function edit($id) {
if ($this->input->post('submit')) {
$insert['name'] = $this->input->post('name');
$insert['code'] = $this->input->post('code');
$insert['description'] = $this->input->post('description');
$insert['position'] = $this->input->post('position');
$insert['type_id'] = $this->input->post('type_id');
$insert['status_id'] = $this->input->post('status_id');
$insert['about_the_status'] = $this->input->post('about_the_status');
$this->item_model->edit($insert, $id);
return $this->index(); //torno all'indice...
} else {
$data['item'] = $this->item_model->get_single($id);
$data['types'] = $this->type_model->get();
$data['statuses'] = $this->status_model->get();
$this->load->view('edit_item', $data);
}
}
function delete($id) {
$this->item_model->delete($id);
return $this->index();
}
}
Anche se più lungo, il concetto è il medesimo dei precedenti. Vorrei soffermarmi semplicemente sulle istruzioni
$data[‘types’] = $this->type_model->get(); $data[‘statuses’] = $this->status_model->get();
presenti sia nel metodo per l’inserimento che per quello per la cancellazione. In pratica andiamo a prepararci in due array l’elenco degli stati e delle tipologie disponibili nel nostro database. Questo ci serve per realizzare delle comode dropdown nei form per i riferimenti esterni. Quando vedremo in dettaglio le viste capiremo meglio come andremo a utilizzarlo.
Nella prossima puntata vedremo in dettaglio le viste, completando il primo step e potendo far funzionare una prima basilare applicazione. In seguito, come già accennato, vedremo come gestire la validazione dei dati.
Puntate precedenti:
Comments(5)
Ho seguito con attenzione le varie fasi di creazione della tua applicazione che ho usato come modello per estrarre i dati da un database esistente ho parecchie difficoltà però quando cerco di paginare i dati con la classe pagination. Mi spiego meglio, se unisco cun una join 2 o 3 tablelle non so come fare per limitare i risultati a 10 items per pagina
questo è il model
db->select(’materiali.*, misure.name as misura’);
$this->db->from(’materiali’);
$this->db->join(’misure’, ‘materiali.misura_id = misure.id’);
$this->db->order_by(”denominazione”, “desc”);
$query = $this->db->get();
return $query->result_array();
}
function get_single($id) {
$this->db->select(’materiali.*, misure.name as misura’);
$this->db->from(’materiali’);
$this->db->join(’misure’, ‘materiali.misura_id = misure.id’);
$this->db->where(’materiali.id’, $id);
$query = $this->db->get();
return $query->row_array();
}
function add($materiale) {
return $this->db->insert(’materiali’, $materiale);
}
function delete($id) {
$this->db->where(’id’, $id);
return $this->db->delete(’materiali’);
}
function edit($materiale, $id) {
$this->db->where(’id’, $id);
return $this->db->update(’materiali’, $materiale);
}
}
?>
e questo il controller
load->model(’materiale_model’);
$this->load->model(’misura_model’);
$this->load->library(’validation’);
$this->load->helper(’date’);
$this->load->library(’pagination’);;
}
function index() {
//lista degli elementi nel database
$config['base_url'] = base_url().’index.php/materiali/index’;
$config['total_rows'] = $this->db->count_all(’materiali’);
$config['per_page'] = ‘10′;
$config['uri_segment'] = 3;
$config['full_tag_open'] = ”;
$config['full_tag_close'] = ”;
$this->pagination->initialize($config);
$data['materiali'] = $this->materiale_model->get();
$this->load->view(’list_materiali’, $data);
}
function add() {
/*
preparo i parametri di configurazione per
la classe “validation”
*/
$fields['nuc'] = ‘NUC’;
$fields['denominazione'] = ‘Denominazione’;
$fields['misura_id'] = ‘Un Mis’;
$fields['consistenza'] = ‘Consistenza’;
$fields['prezzo'] = ‘Prezzo’;
$fields['note'] = ‘Note’;
$rules['nuc'] = ‘required’;
$rules['denominazione'] = ‘required’;
$rules['misura_id'] = ‘required|number’;
$rules['consistenza'] = ‘required’;
$rules['prezzo'] = ‘required|number’;
$rules['note'] = ‘required’;
$this->validation->set_rules($rules);
$this->validation->set_fields($fields);
if ($this->input->post(’submit’) && $this->validation->run()) {
/*
ho fatto il post e ho passato la validazione
quindi salvo nel db i dati
*/
$insert['nuc'] = $this->input->post(’nuc’);
$insert['denominazione'] = $this->input->post(’denominazione’);
$insert['misura_id'] = $this->input->post(’misura_id’);
$insert['consistenza'] = $this->input->post(’consistenza’);
$insert['prezzo'] = $this->input->post(’prezzo’);
$insert['note'] = $this->input->post(’note’);
$this->materiale_model->add($insert);
return $this->index(); //torno all’indice…
} else {
/*
non ho fatto il post oppure
non ho passato la validazione
quindi mostro il form…
*/
$data['misure'] = $this->misura_model->get();
$this->load->view(’add_materiale’, $data);
}
}
function edit($id = false) {
if (!$id) {
/*
se non ho l’id non posso modificare nulla,
quindi torno all’elenco
*/
return $this->index();
}
/*
preparo i parametri di configurazione per
la classe “validation”
*/
$fields['nuc'] = ‘NUC’;
$fields['denominazione'] = ‘Denominazione’;
$fields['misura_id'] = ‘Un Mis’;
$fields['consistenza'] = ‘Consistenza’;
$fields['prezzo'] = ‘Prezzo’;
$fields['note'] = ‘Note’;
$rules['nuc'] = ‘required’;
$rules['denominazione'] = ‘required’;
$rules['misura_id'] = ‘required|number’;
$rules['consistenza'] = ‘required|number’;
$rules['prezzo'] = ‘required’;
$rules['note'] = ‘required’;
$this->validation->set_rules($rules);
$this->validation->set_fields($fields);
if ($this->input->post(’submit’) && $this->validation->run()) {
/*
ho fatto il post e ho passato la validazione
quindi salvo nel db i dati
*/
$insert['nuc'] = $this->input->post(’nuc’);
$insert['denominazione'] = $this->input->post(’denominazione’);
$insert['misura_id'] = $this->input->post(’misura_id’);
$insert['consistenza'] = $this->input->post(’consistenza’);
$insert['prezzo'] = $this->input->post(’prezzo’);
$insert['note'] = $this->input->post(’note’);
$this->materiale_model->edit($insert, $id);
return $this->index(); //torno all’indice…
} else {
/*
non ho fatto il post oppure
non ho passato la validazione
quindi mostro il form…
*/
$data['id'] = $id;
$data['materiale'] = $this->materiale_model->get_single($id);
$data['misure'] = $this->misura_model->get();
$this->load->view(’edit_materiale’, $data);
}
}
function delete($id) {
$this->materiale_model->delete($id);
return $this->index();
}
}
?>
Ciao!
Innanzitutto bisogna modificare il modello in modo da ricevere i parametri della paginazione. La libreria infatti si occupa di generare l’html necessario ma non modifica l’interazione col database.
Bisogna quindi introdurre nel metodo get() del modello la riga $this->db->limit($perpage, $from);.
In questo modo possiamo specificare quante righe prelevare e da che record partire:
function get($perpage = 0, $from = 0) {
…vecchio metodo get…
$this->db->limit($perpate, $from);
…get e return…
}
nel modello invece quando andremo a chiamare la funzione basterà passare i dati della paginazione (risultati per pagina e segmento dell’URI contenente il record da cui partire):
$this->materiali_model->get($config['per_page'], $this->uri->segment(3));
così dovrebbe funzionare.
Ciao Cesco…
Come faccio a controllare che una query sia valida?
cioè, se eseguo una query con where e questa non è soddisfatta il result mi da undefined, come posso controllare e assegnare un valore?
Grazie
Ciao franz,
Per controllare i risultati puoi usare il metodo num_rows(). Ad es:
$query = $this->db->get(’tabella’);
if ( ! $query->num_rows() ) {
return ‘mio valore di default’;
} else {
//return $query->result_array();
}
Grazie risolto!
Posso chiederti un’altra cosa riguardo le sessioni?
Dovrei tradurre questo codice:
$userid = $row['id'];
session_start();
$_SESSION['id'] = session_id();
$_SESSION['userid'] = $userid;
In pratica quando effettuo il login setto la variabile $_SESSION['userid'] con l’id della tabella.
Al momento del logout, session_unset();
Spero di essermi spiegato