Newsgroup: it.comp.www.php
Titolo: Suggerimento su viste e controller

Ciao,
nel caso avessi un array da convertire in json, csv, xml ed html,
le procedure di conversione, è opportuno metterle nelle viste o
far spare fuori già l'output convertito dal controller?
Al momento il controller mi genera l'array ed in base a determinate
opzioni, deve ritornare al browser un output tra quelli di cui sopra.
Potrei uscire dal controller con un brutale "echo XML::fromArray($dati)"
per spar fuori direttamente l'xml, ma non mi sembra molto elegante.
pensavo quindi di passare l'array $dati direttamente alla vista corretta
(xml, json, ...) e di far convertire il tutto li dentro.
Che dite? Quale sarebbe la soluzione più pulita? Non sono troppo sicuro
che sia corretto mettere del codice che elabora un array dentro la vista
piuttosto che nel controller.
Tnx.

On 13 Lug, 21:26, Gandalf Corvotempesta

Da quel che ho capito io il controller deve richiedere i dati al
model, elaborarli, fare tutte le operazioni logiche, e passarle alla
vista che deve 'impaginarli' e 'stamnparli', quindi in teoria il tuo
controller dovrebbe solo verificare i dati e passarli alla vista in un
array, poi stà a lei metterli in json/xml/quello-che-ti-pare.
Così se un domani ti serve che li converta in html, ad esempio, sai
che dovrai agire sulla vista..
Ma aspettiamo che qualcuno con più esperienza ci delucidi ;)

 Ma aspettiamo che qualcuno con più esperienza ci delucidi ;)
Attendiamo pure.... :)

 fuori già l'output convertito dal controller?
Qui si scontrano diversi precetti di programmazione. :)
Io cerco di applicare sempre YAGNI e DRY, quindi in questo caso, visto 
che si tratta di una singola linea di codice per l'output di un singolo 
formato, la metterei nel controller (YAGNI). Il giorno in cui dovrai 
selezionare il formato di output, o quando ti servira` avere lo stesso 
output da diversi controller, la tiri fuori e la metti in n views che 
potresti anche riciclare per altri controller (DRY).
Bye.

 potresti anche riciclare per altri controller (DRY).
Uhm, forse mi sono espresso male.
Io ho X controller che estendono tutti un mio controller generico.
In base al content-type del tipo di richiesta che mi vien passato dal
client, devo rispondere in XML piuttosto che JSON, piuttosto che CSV etc.
Il codice che spara fuori l'output l'ho già fatto e sta dentro un
helper, quindi fuori sia dai controller che dalle viste.
Nel controller 'generico', quello che estende tutti gli altri, io
ho un bel "IF" che mi verifica:
if ( $contentType == 'XML' ) {
    View::load('xml', $arrDati);
else if ( $contentType == 'XML' ) {
    View::load('csv', $arrDati);
}
Questo è sostanzialmente il flusso del programma.
Ora, meglio mettere il codice che spara fuori l'xml dritto nel
controller, al posto di "View::load" oppure lascio le viste e
metto il codice dentro la vista corretta?
Quello che non mi è chiaro è se le viste devono obbligatoriamente
essere solo dei 'template' quindi con al massimo degli echo e dei
foreach, o se possono anche elaborare i dati preparandoli per l'output.
Se ad esempio mi arriva in input (nella vista) un array non conforme
alla tipologia di output di cui necessito, posso elaborarlo nella vista
(come ad esempio processarlo, cambiare alcuni valori, generare un nuovo
array, etc etc) o devo fare l'elaborazione nel controller e limitare
l'intervento della vista *al massimo* in qualcosa di questo tipo:
foreach ( $arrDati as $chiave => $valore ) {
    echo "<div>".$chiave."</div><div>".$valore."</div>";
}
Perchè, per come è strutturato il programma, e per espansioni future, mi
sarebbe più comodo passare tramite le viste, ma non vorrei denaturarne
lo scopo. Nel mio caso le viste sarebbero composte da poche righe di
php e ZERO di output (al massimo, giusto l'header XML nella vista XML,
ma nella vista JSON non avrò una singola riga di testo, solo codice php)
(no, non mischio codice php e html, sono dentro una vista ed un foreach
sarebbe impossibile da non usare mai)
-- 
Non tocca a noi dominare tutte le maree del mondo,
il nostro compito è di fare il possibile per la
salvezza degli anni nei quali viviamo,
sradicando il male dai campi che conosciamo.

 l'intervento della vista *al massimo* in qualcosa di questo tipo:
Il controller deve mediare tra i dati/model e la vista, quindi se dal 
model arrivano dati nel formato sbagliato, dovrebbe essere il controller 
a riadattarli per farli digerire alla view.
Oppure devi modificare il model per restituirli nel formato giusto o 
usare un adapter o un proxy che media tra la view e il model originale.
Dipende fondamentalmente da quanto controllo hai sul model. Se hai pieno 
controllo, modificalo per adattarsi al resto della tua architettura. Se 
ne hai poco (per esempio perche` i dati ti arrivano da un webservice su 
cui non hai controllo), usa un adapter/proxy che fa vedere alle tue view 
le tue API, e di nascosto converte i dati che provengono dal webservice.
Se il tuo model attuale e` un semplice array, puoi anche wrapparlo con 
una classe che implementi Iterable e ArrayAccess, e ammorbidire il 
passaggio da array a oggetti.
 
Bye.

 $this->view->process($arrDati);
Si, sostanzialmente funziona così la vista di Kohana.
Dal controller creo l'oggetto vista, gli setto le variabili
in maniera analoga al metodo che hai appena indicato poi
istruisco il controller di renderizzare il tutto.
in soldoni:
$view = new View::factory('xml');
$view->arrDati = $arrDati;
$view->render();
Il problema resta appunto $arrDati.
$arrDati è dinamico, e potrebbe essere (anzi, lo sarà) molto
corposo, quindi sarebbe impraticabile generare l'XML direttamente
da dentro il controller assegnando un risultato già finito.
O meglio, sarebbe un bagno di sangue.
Per questo pensavo di tenere il controller snello facendogli fare
quello per il quale è progettato: mediare tra Model e View.
I Model possono essere di due tipo:
1) output sparato fuori da un database e convertito in array
2) output sparato fuori da alcune API di alcuni webservice remoti e
convertiti sempre in Array.
In quest'ultimo caso, i webservice spesso mi ritornano un XML.
Il model prende l'XML, lo converte in array e lo spara al controller.
Questo passaggio serve per uniformare l'input che arriva al controller.
Così facendo, il controller riceve sempre e solo un array, la logica
di conversione viene fatta nel singolo model. Se un model riceve dati
'farlocchi', è quel model che li standardizza, evitando di ritrovarmi
con un controller di dimensioni assurde perchè deve gestire tutte le
combinazioni possibili. Se poi un giorno dovessi aggiungere un ulteriore
model, non dovrei far altro che lavorare su quello, senza metter mano al
controller per standardizzare i dati.
Pensavo di fare la stessa cosa con la view.
Il controller prende in carico un array, lo elabora quanto basta e spara
un array alla view, indipendentemente dal tipo di output.
Sarà poi la view XML a prendere l'array, elaborarlo e sistemarlo per
generare un XML corretto.
Idem per il json. La view del json prende l'array, lo elabora e lo spara
fuori in json.
Stessa cosa per il CSV.
Non mi sembra errato come discorso. Così facendo il controller sarà
sempre standard, lavorando sempre e solo con un array (o un oggetto,
devo vedere cosa è meglio nel mio caso), sarà compito dei model e delle
view uniformare i dati.


 fuori in json.
Vai liscio e tranquillo! ;)
Bye.

 Vai liscio e tranquillo! ;)
Ottimo.
Puoi quindi confermarmi che il metodo che ho implementato
non sia "strampalato" ma corretto dal punto di vista logico?

 "strampalato" ma corretto dal punto di vista logico?
Posso confermarti che l'avrei fatto anche io in quel modo, ma dirti che 
sia il metodo corretto no... :)
Bye.

 sia il metodo corretto no... :)
Be, l'importante è che tu l'avresti fatto così, almeno
la colpa è la tua :)
Scherzi a parte, non mi sai dire se è il metodo corretto perchè
non lo sai nemmeno te, oppure ci sono metodi migliori ma non
sapresti come applicarli al mio problema?
Insomma, non voglio fare una cosa sbagliata concettualmente,
potrei anche rivalutare tutta la progettazione....


 applicarli al mio problema?
La programmazione e` come le mutande, a ognuno le sue.
Anche il pattern MVC e` un pattern con delle linee guida, ma non e` un 
elenco di "il model fa a, b, c, d, e, f, g, ... il controller h, i, j, 
k... la view l, m, n, ..."
Ci sono diverse implementazioni del pattern anche nello stesso 
linguaggio, e non e` detto che una sia piu` corretta dell'altra. Finche` 
rispettano i principi di base vanno bene, e la tua architettura mi pare 
li rispetti. Per quello ti dicevo di andare tranquillo.
Poi, come nei database normalizzi fino alla 3nf ma poi denormalizzi per 
vari motivi (prestazioni, confusione negli schemi, ecc.), anche i pattern 
sono malleabili (cum grano salis), e ogni tanto puoi chiudere un occhio 
se li rispetti al 99% invece che al 100%.
Bye.

 li rispetti. Per quello ti dicevo di andare tranquillo.
Grazie.


Ok per il KISS, ma lo YAGNI mi spiegate cos'è? su wikipedia non ce n'è
traccia ;)
Cmq, da newbie quale sono, io la cosa la implementerei così:
1. Il controller carpisce gli input dall'utente, gli elabora, chiede
al model i dati neccesari
2. Li processa, fà tutti i suoi bei controlli, crea una struttura
funzionale (un array)
3. In base al content-type (che rimangono nell'ambito degli user
input), seleziona la view
4. Inizializza la view e gli passa li dati
5. alla vista non gli rimane che formattare i dati e creare l'output.
Se domani devi implementare l'esportazione in csv, crei un'altra vista
al quale arrivano i gli stessi dati delle altre, cambia solo l'output
che genera.
Oppure, volendo semplificare un pò le cose, il controller passa i dati
alla view e quella decide che output generare, ma lasciando la
validazione del content-type al controller, avendo nella vista un
metodo per ogni content-type supportato.
La mia idea andrebbe bene?


perchè sposti la business logic dal model al controller???
il pattern MVC indica che la business logic deve essere implementata nel 
model e non nel controller, quest'ultimo si deve preoccupare di prendere 
i dati dalla view e indirizzare al model (o più model) corretto e 
ritornare la view corretta. tutto il resto dovrebbe farlo il model 
magari più di uno ma sempre model è.
i dati, la loro elaborazione e i controlli sugli stessi appartengono 
alla logica dell'applicazione quindi al model.
è una domanda che pongo non solo a te ma anche agli altri che sembrano 
avvallare la tesi del controller che fa da business logic.
Ciao

 perchè sposti la business logic dal model al controller???
Perchè con l'MVC sono un newbie ;)
Apparte gli scherzi, io credevo che il model dovesse solo preoccuparsi
di recuperare i dati, dovunque essi siano.
Cioè:
$controller->dati = Model::pigliaDati($filtri_aggiuntivi)
il model, ad esempio, guarda se i dati richiesti sono in cache
(memcache, apc), o nel db (mysql, pgsql), li prende e li restituisce
al controller.
Poi, ad esempio, per il dicorso KISS, il controller passa al model
anche un paio di informazioni dell'utente autenticato (account,
gruppo, etc) così il model carica solo i dati al quale questo utente
può accedere.. ma anche qui, qualora i controlli sull'utente e su
quello a cui può accedere dovessero essere un pò complessi, io
tenderei a farli nel controller.
Ripeto, con l'mvc sono un newbie e sono qui per imparare, quindi se
sbaglio qualcosa ditelo pure ;)
E' che io il model lo vedo molto come 'qualcosa che si occupa solo di
recuperare i dati (db, memcache, file, etc...) ordinati dal controller
e restituirli al medesimo', il controller fà tutto il resto
(controlli, logica, etc), invoca la view e gli passa solo i dati
necessari per generare l'output.


pirla io che guardavo nel wiki italiano -.-


guarda anch'io sono newbie, nel senso che mi occupo di php come secondo 
lavoro e ho scelto ZF come framework, anch'io come te mettevo la 
business logic all'interno del controller e utilizzavo il model 
principalmente per reperire dati su db, le immagini e altri tipi di dati 
li implenetavo nel controller. poi mi sono trovato in situazioni che la 
logica dell'applicativo doveva cambiare o ampliarsi e mi sono reso conto 
che inserendo il tutto all'interno del controller, era poco manutenibile 
e le varie parti della logica dell'applicativo che dovevano rimanere 
separate erano spesso confuse e si andavano a mischiare.
un esempio è stato il controller sui metodi di pagamento, inizialmente 
prevedevo solo contanti e quindi la logica dell'applicativo(tutto su 
controller) andava bene (era accettabile), poi mi è stato richiesto di 
implementare gli altri metodi di pagamento (carta credito, bonifico, 
vaglia, ecc) che hanno logiche differente (dati diversi e controlli 
diversi) inserendo il tutto all'interno del controller ero costretto a 
fare una marea di "if" e "switch" e appena mettevo mani ad una parte del 
codice facilmente ne veniva influenzata un altra.
studiando attentamente il pattern MVC e cercando su internet articoli 
che mi facessero capire e approfondire mi sono reso conto che sbagliavo.
adesso il controller è rimasto uno (pagamenti) e a seconda del tipo di 
pagamento e dati inseriti richiamo i vari model che servono (esempio 
Carta di credito, model che controlla la vericità della carta di credito 
e preleva i dati necessari controllando che il cliente ha l'abilitazione 
a pagare con carta credito , model del pagamento CartaCredito che prende 
i dati del model precedente, passati dal controller , controlla un 
importo minimo e se passa, li invia ad un webservice ).
il controller a seconda della business logic invocata, richiama la view 
corretta.
questo approccio mi ha permesso di riutilizzare i model (quindi le varie 
modalità di pagamento) anche in altre parti dell'applicativo senza 
reinventare la ruota e senza ridondanza (un pagamento di carta di 
credito è quello, non varia è deve essere in UN SOLO PUNTO 
dell'applicazione), utilizzando il tuo approccio (il mio iniziale) se 
dovevo riutilizzare la logica dei pagamenti (come poi avvenuto 
"pagamento di vendita" e "pagamento di acquisto") e mettere tutta la 
logica all'interno del controller avrei dovuto fare due controller che 
praticamente facevano gli stessi controlli rischiando di sbagliare o 
gestire le due cose in maniera differente.
scusa se sono stato prolisso
mi farebbe piacere avere delle opinioni anche dagli altri pellizzari, 
gandalf & c. che sicuramente sono meno niewbie di me :)
Ciao

 gandalf & c. che sicuramente sono meno niewbie di me :)
A guarda, io sono un sistemista non un programmatore :)
Sto cercando di sviluppare un webservice REST ma non riesco
ad andare molto lontano, più che altro perchè non ho molta
familiarità con il paradigma MVC.
ad esempio, su Kohana, ho configurato il router per dirigere
le richieste al controller corretto e passare tutto il resto
della URI come parametro
Ad esempio:
/ciccio/ciao/mondo/come/va/
Controller = ciccio
/ciao/mondo/come/va/ sono invece i parametri che arrivano nel
controller.
Ho creato un controller di nome REST che mi prende i parametri
e me li esplode in un array in base allo slash '/'
A partire da questo controller ho esteso il controller "Ciccio"
che viene richiamato dal router.
Il router richiama una action di nome pari al metodo invocato.
ad esempio, se il metodo fosse GET, la action si chiamerebbe
Action_GET oppure Action_POST e così via.
Facendo così riesco a gestire i vari verbi (GET POST PUT DELETE)
Supponiamo che il "/ciao/mondo/come/va/" debba visualizzare il
contenuto di una directory di nome "mondo/come/va" perchè "/ciao/"
richiamato in GET significa elencare il contenuto della directory.
Te la logica che scansiona la directory, ne prende i file etc etc
la metteresti in un Model? Io al momento l'ho messa nel controller.
Nel caso la mettessi nel model, 
1) che nome gli daresti
2) come richiameresti il model? Gli passeresti tutta la stringa URI
passata come argomento magari nel __construct? 
In tal caso, il controller dovrebbe solo richiamare il model corretto,
prendere il suo output e passare l'output alla view? Ovvero, deve fare
esclusivamente da tramite tra model e view senza alcuna logica?
Ad esempio, dentro il controller:
$Model = new Model();
$outputModel = $Model->parse($_REQUEST);
$View = new View('XML');
$View->draw($outputModel);
Una roba del genere? Crea il model, gli passa i parametri, prende il
suo output, crea la View XML, gli passa i parametri e la View ritorna
l'output corretto?
E se avessi bisogno di richiamare più model? Li richiamo da dentro il
model stesso? O li richiamo dal controller?

 Ciao
Grazie mille, farò tesoro delle tue parole e (tempi permettendo)
proverò a fare anche il tuo metodo!

isValid() o qualcosa del genere.
Io valuto caso per caso.
Per le cose nuove (mai affrontate prima) di solito parto mettendo i check 
nel controller, poi provo a spostarli nel model verificando che non 
diventi troppo ingarbugliato il codice. Se il refactoring va liscio, li 
lascio li`. Se vedo che diventa incomprensibile il codice faccio revert e 
li lascio nel controller, in attesa che mi sia necessario astrarli.
Di solito quando mi e` necessario astrarli (perche` ho dati simili con 
due model diversi) riesco anche ad avere una visione piu` chiara del 
problema e lo affronto meglio.
Le cose si complicano un po' quando hai model che devono interagire tra 
loro. Per esempio un model che fornisce dati dal fs ma in base ai 
permessi dell'utente.
Qui o l'utente e` un oggetto globale e il model ne e` a conoscenza (e 
generi dipendenza stretta) o lo passi al model in qualche modo (e devi 
avere un'API stabile sull'oggetto utente).
Di solito, in questo caso, io accoppio strettamente il model FileSystem 
col model User, perche` il model User e` praticamente un singleton (c'e` 
solo un utente loggato per uno script PHP), quindi al model FileSystem 
non interessa lavorare con utenti di tipo diverso.
Ma anche qui esistono le eccezioni: potresti avere un utente locale, uno 
autenticato con OAuth, e uno con Facebook. A questo punto devi 
disaccoppiare e definire una API stabile tra i tre.
Ribadisco: valuto caso per caso, implemento il piu` semplice e quando 
serve faccio refactoring.
Bye.

 Poi chiede i dati al model e li passa alla (sua) view che li visualizza.
Uhm, quindi sostanzialmente il Controller è un grosso blocco di 
"if/else" e controlli di sicurezza.
Ad esempio, supponiamo di avere un guestbook semplice semplice.
Ho la mia form messa in una view.
ci sarà: <form action="/controller/azione/" method="POST">
i dati quindi vengono inviati ad una precisa azione del controller.
Il controller prende i dati, vede che si tratta di un guestbook,
verifica che siano corretti (cioè che non manchi l'indirizzo email di 
chi ha inviato il commento) e se tutto fila, richiama il model guestbook
dicendo di salvare.
$Model = new Model_Guestbook;
$Model->form = $_POST;
$Model->save();
Il model quindi prende i dati del post passati dal controller, li
elabora, crea le query e salva.
Prende l'output della query e lo spara indietro al controller.
Nel controller:
if ( $Model->output == 'ok' ) {
    $View = new View('Guestbook');
    $View->result = 'ok';
    $View->draw();
}
La view parte, vede che è settato "result" uguale ad OK e quindi
nasconde la form e mostra il messaggino "Grazie".
In pratica il controller fa da vigile urbano.
Smista i dati mettendo in comunicazione una determinata view con un
determinato model, in base alla action passata.
Però così facendo la logica sta nel controller, il model si occupa di
fare solo e soltanto da interfaccia da/verso il db.
E' il controller che smista e sistema ciò che non sarebbe compatibile
con il model/view di riferimento, come ad esempio rimbalzare eventuali
form senza email inserita.
Spostando la businesslogic nel model, è il model a dover rimbalzare
la form perchè mancano i dati. Non mi sembra sensato, in tal caso
il controller sarebbe sminuito a router, ovvero prende la view, legge
la action e richiama il model, il model risponde.
Tanto vale far dialogare view e model senza controller ed usare il
router frontale.


 router frontale.
come detto sopra semplifichi troppo.
 
ammettiamo che la tua applicazione non viene visualizzata solo su
un browser per PC ma anche su un palmare (quindi le view sono
diverse, per differenti tipi di risoluzione e adozione
ajax/javascript/flash, render HTML, ecc..), o che la tua 
applicazione abbia diversi client (broser, applicazione nativa
android/Iphone-Itouch, client per PC, ecc) in quel caso come fai
a far dialogare view e model senza il controller che gestisce
l'interazione tra i due???
che fai implementi gli stessi controlli ed elaborazione dei dati
(la logica dell'applicazione) per ogni tipologia di frontend?? o
più semplicemente fai in modo che il controller si preoccupi di
prendere ed interagire con i view e i model adatti lasciando la
logica di cui sopra inalterata ed in un unico punto??
a volte il model non è neanche necessario, come non è necessario
il controller.
nel paradigma MVC a volte la view dialoga direttamente con il
model (in ZF gli helperview), o a volte l'interazione tra view e
controller non richiede model (si pensi al semplice logout dove
si svuola la sola sessione, il pulsante/link "lougout" non fa
nient'altro che svuotare la sessione e ritornare all'home page) 
Ciao
-- 
Postato da Virgilio Newsgroup: lo usi da web ma con le funzioni del newsreader 
http://newsgroup.virgilio.it
Gerarchie it, italia, it-alt, tin, it.binari. Unico!

 del model.
Boh, non ci sto capendo niente.
Facciamo un esempio concreto: il mio progetto REST che sto provando a
fare con Kohana.
Ho una view per l'output (l'input non esiste, i dati arrivano via url)
Ho un model per l'interazione con una tabella del database.
Ho un controller.
Ho un router.
Il router legge la URI (/cars/parametro1/parametro2/), e smista tutto
al controller delle automobili "cars"
Benissimo. In base alla lunghezza della URI e conseguentemente al
suo numero di parametri, devo fare determinate interrogazioni al
model.
Il controller 'base', mi esplode la URI in un array rimuovendo il
nome del controller stesso, perchè superfluo:
$arrDati = array('parametro1', 'parametro2');
Se è presente solo parametro1 (URI: /cars/parametro1/) devo eseguire
una operazione, se è presente anche parametro2, devo farne una differente.
Questa logica, dove deve andare? Nel model?
Creo quindi una istanza del model e gli sparo tutta la uri in questo
modo: ?
$Model_Cars = new ORM::factory('cars');
$arrOutput  = $Model_Cars->dispatch($arrDati);
ovvero, sparo tutto così com'è (dopo la ripulita iniziale e
l'esplosione in array) al model, il quale elabora il tutto e
ritorna i risultati sottoforma di array.
Il controller prende $arrOutput e lo spara alla view, così com'è,
in base alla tipologia di richiesta (che viene identificata dal
controller, ma questo non ha importanza)
$View_XML = new View::factory('xml');
$View_XML->arrOutput = $arrOutput;
$View_XML->draw();
Va bene così? Ovvero spostare tutta la logica di elaborazione
della URL dentro il model. Io gli sparo tutto l'array esploso,
poi si arrangia il model anzichè il controller.


Gandalf Corvotempesta ha scritto:

dal punto di vista del paradigma MVC si è corretto.
all'interno del model IO farei
class MODEL{
  $arrDati;
  function dispatch($array){ 
      $this->$arrDati = $array;
      switch ($this->arrDati['tipo operazione'])
           case pippo
                $this->pippo();
                break
           case pluto
                $this->pluto();
                break
           else
            .......
      }
   private function pippo(){
      elaborazione pippo 
      return dati
   }
  private function pluto(){
      elaborazione pluto
      return dati
   }
}
in questo modo se devi implementare altre logiche hai da
modificare solo il model (il controller per il minimo necessario
che serve ad identificare la view di output corretta).
e se per caso hai necessita di richiamare questa logica da altre
parti dell'applicativo non hai problemi.


Bramante ha scritto:

Ok, faccio così, anzi, a dire il vero ho già spostato la logica
dentro il model.
Gli passo direttamente la stringa, non esplodo nemmeno in array.
Ci pensa il model a fare il parse della URI tramite espressioni
regolari.


 }
E se volessi verificare se gli header Accept ed Accept-Language siano
corretti e compatibili con il mio sistema di risposta, il check dove
lo metteresti, nel model che gestisce il RESTFul (che quindi sarà
sostanzialmente una sorta di 'namespace' o contenitore di funzioni)
oppure direttamente nel controller base, dal quale vengono estesi tutti
gli altri controller ? (nel __construct, più precisamente)
Al momento ho messo le funzioni che fanno il check di 
_SERVER['HTTP_ACCEPT'] dentro il Model_RESTFul, il quale ritorna
true o false a seconda che l'header sia accettabile o meno.
Il controller richiama il model e la rispettiva funzione, se ritorna
true va avanti, se ritorna false spara fuori un errore 406 not acceptable.
Però, così facendo, il controller diventa il solito vigile urbano
e poco più.


 
io metterei i controlli relativi i dati di input nel controller,
cioè il controllo formale che i dati siano quelli che ci si aspetta.
(per farti un esempio, nella tua stringa che i valori siano
corretti "/cars/parametro1/parametro2/" e non magari
"/pippo/questo non è un parametro valido/rischio sql inject/"
spostare i controlli formali(relativi ad UN controller) nel model
ti preclude (o ti aggrava) di poter riutilizzare il model stesso.
spiego sotto
il model che riceve quei dati si deve preoccupare che gli stessi
siano conformi alla SUA logica.
un esempio di quanto sopra.
ammettiamo che il tuo REST  vada su db a prendere i dati di una
tale marca/modello di autovettura "/cars/fiat/punto/"
se passi questa intera stringa al model ed è lui che fa i
controlli formali, lui in prima istanza si deve controllare che
quei dati siano "formalmente" validi e poi controllarli ed
analizzarli.
se sposti tali controlli "formali" (la correttezza dell'input) al
controller, il model si deve SOLO preoccupare di fare i SUOI
controlli ed analisi.
se per caso in un altro punto del tuo programma hai bisogno non
dei dati delle auto, ma dei camion e ad un certo punto hai il
REST "/camion/iveco" come ti comporti??
mettendo i controlli formali all'interno del model questo si deve
controllare che "camion" sia corretto e non una porcheria e poi
procedere con i SUOI controlli ed analisi.
se invece questi controlli li fai nei controller relativi, al
model passi solo un array di dati ("fiat/punto" e "iveco").
se "cars" e "camion" sono anch'essi dati da dover elaborare
(magari tabelle differenti, campo di databese, ecc). allora il
mio esempio va a farsi friggere :) perchè anche loro sono dati di
model.
spero di essere esauriente e comunque non prendere per oro colato
tutto quanto anche perchè come detto queste cose sono frutto più
di teoria che di pratica :)
a volte anche per me è più facile fare tutto nel controller o nel
model poi come detto da pellizzari spesso si riprende in mano la
cosa per risistemare il tutto.


 cosa per risistemare il tutto.
Non ti sto chiedendo il santo graal, semplicemente il pattern MVC
per me è nuovo e sto cercando di capire quali possano essere le
best-practise.
Poi ovviamente ci possono essere strappi alla regola, ma a forza di
strappi ci si ritrova senza calzoni :)


Gandalf Corvotempesta ha scritto:
[ CUT ]
da quello che ho letto, puoi lasciare tranquillamente nel model
il controllo degli header (per te non sono solo controlli
sull'input ma sono parte integranti di dati da dover controllare
ed elaborare) ed è quindi giusto IMHO che sia un model ad
occuparsene.
quello che mi fa sorgere il dubbio, ma è più un MIO capriccio, è
il fatto che gli header della richiesta HTTP li elabori in più punti 
1) Il router di Kohana identifica il controller, in questo caso
"cars" e ne legge il metodo di richiesta, ovvero GET.
2) "Model_RESTFul->isAcceptable()" 
dentro "isAcceptable" verifico la compatibilità degli header con
il mio programma, se è tutto ok, ritorno true e si prosegue.
3) Controller_Cars che richiama il metodo "output" del
Controller_Restful il quale in base agli header passati come
parametro, carica la view giusta e termina il programma.
se un domani la tua logica in qualche maniera cambia, sei
costretto a fare il refactoring di quasi tutto "l'accrocchio" :)
se riesci sposta tutto su un model, in questo modo hai tutto su
un unico punto del programma, e che soprattutto si occupa solo
LUI di gestire i dati degli Header.


 LUI di gestire i dati degli Header.
Per il punto 1, ovvero il router di kohana, non posso.
O meglio, in precedenza facevo il check degli header direttamente
dal mio Controller_RESTFul, poi però ho scoperto che Kohana è in
grado di riconoscere da solo il metodo di richiesta e richiamare
l'action opportuna direttamente dal router, quindi ho eliminato
dal controller tutta la sezione di rilevamento metodo.
(semplificando parecchio il codice, tra l'altro)
Per il punto 2 credo ci sia poco da dire
3) Gli header li legge però non da $_SERVER ma da alcune variabili
settate dal Controller_RESTFul.
Il Controller_RESTFul, dentro il __construct, fa anche questa semplice
cosa:
$this->output_type = Model_RESTFul->getOutput()
Dentro Model_RESTFul->getOutput() ho il check degli header.
in pratica tutto il sistema si basa sugli header (è REST, è difficile
che in seguito possa cambiare, questo software fa solo e soltanto da API
di accesso ad un database) però le funzioni di lettura header stanno
tutte nel model RESTFul.
I vari controller (in particolare il generale RESTFul) si appoggiano
sempre al model_restful per leggere gli header
Potrei bypassare il settaggio della variabile di cui sopra e richiamare
direttamente Model_RESTFul->getOutput() da dentro 
"Controller_RESTFul->output" che è il metodo che seleziona la view in
base alla tipologia di header passato.
