CakePHP

Come ottenere una lista di tutti i componenti e relative actions

Grazie a questo component, è facilissimo !

http://cakebaker.42dh.com/2006/07/21/how-to-list-all-controllers/

Behavior Linkable: dove non arriva Containable

Grazie al suggerimento di Tox che ha + fiuto del cane di Lycos nello scovare risorse in rete, ho provato il LinkableBehavior per risolvere un problema con una query che con Containable non riuscivo a rendere efficente.

Problema

Ho il seguente schema di modelli:
Regions hasMany District hasMany City hasMany Customer.
Ho necesità di ottenere l’elenco dei clienti (Customer) che risiedono nella provincia (District) di Torino (id=1).

Soluzione con LinkableBehavior

Model:

var $actsAs = array('Linkable');

Codice:

$customers = $this->District->City->Customer->find('all',array(
        'link'=>array('City'=>array('District')),
        'conditions'=>array('District.id'=>$id),
        'fields'=>array('Customer.id','Customer.nome','Customer.cognome','City.name')))

Risultato:


Array
(
    [0] => Array
        (
            [Customer] => Array
                (
                    [id] => 1
                    [nome] => Giuseppe
                    [cognome] => De Santis
                )

            [City] => Array
                (
                    [name] => Buttigliera Alta
                )

        )

)

Query eseguita (unica):

SELECT `Customer`.`id`, `Customer`.`nome`, `Customer`.`cognome`, `City`.`name` FROM `customers` AS `Customer` LEFT JOIN `cities` AS `City` ON (`City`.`id` = `Customer`.`city_id`) LEFT JOIN `districts` AS `District` ON (`District`.`id` = `City`.`district_id`) WHERE `District`.`id` = 1

Meglio di così….

Risorsa utile: http://planetcakephp.org/aggregator/items/891-linkable-behavior-taking-it-easy-in-your-db

Effetti JQuery in CakePHP 1.3

Con CakePHP 1.3 è possibile sfruttare altri framework Javascript oltre all’accoppiata Prototype/Scriptaculous utilizzando il JsHelper.
Per utilizzare JQuery è sufficiente seguire le istruzioni del manuale on line http://book.cakephp.org/view/1592/Js che riassumo di seguito.

  1. Scaricare JQuery http://docs.jquery.com/Downloading_jQuery
  2. Copiare gli script in app/webroot/js
  3. Includere la libreria in tutte le pagine. Per fare questo si può modificare il file /app/views/layout/default.ctp inserendo il codice
    echo $this->Html->script('jquery-1.4.2.min'); 

    nella sezione <head></head>.

  4. Includere il seguente comando
    echo $js->writeBuffer();

    prima del tag </body>

  5. Richiamare il JsHelper inserendo il seguente codice nel controller
    var $helpers = array('Js' => array('Jquery'));

A questo punto siamo pronti per utilizzare gli effetti di JQuery nelle nostre views

Nella view inseriamo il seguente codice che permette di mostrare o nascondere un DIV con effetto slide.
Creiamo i link e il box

<a href="#" id="apri">Apri il box</a> | <a href="#" id="chiudi">Chiudi il box</a>
<div id="box" style=" border: 1px solid green; height:200px; width:100px; display:none"></div>

e poi aggiungiamo il codice PHP

 $apri = $js->get("#box")->effect('slideIn');
 $chiudi = $js->get("#box")->effect('slideOut');
 $js->get("#apri")->event('click', $apri );
 $js->get("#chiudi")->event('click', $chiudi );

Volendo includere un effetto non disponibile con JsHelper è possibile inserire del codice nativo JQuery e riutilizzarlo nel seguente modo

$codice = '$("#box").toggle("blind",{},500);';
$js->get("#toggle")->event('click', $codice );

Notepad++ : come far riconoscere l’HTML nei template .ctp e .thtml0

Un editor leggero e veloce che uso al posto del classico blocco note e anche per eseguire delle piccole modifiche su semplici progetti.
Per progetti in php + complessi uso Eclipse con plugin legati al PHP.

Utilizzando massicciamente i template con i vari sistemi da me utilizzati (Smarty, CakePHP, ecc), mi trovo di fronte a estensioni del tipo tpl, thtml, che non contengono altro che codice HTML, ma che non sono riconosciuti dall’editor come tali e quindi non viene attivata la colorazione del codice.

Per Notepad++ è sufficente aggiungere l’estensione nel file langs.xml che si trova nella directory di installazione del programma.

La dove è definito il linguaggio html

E’ sufficente aggiungere le estensioni da associare all’HTML

e poi registrare le due estensioni selezionando da menu:

CONFIGURAZIONE > OPZIONI > ASSOCIAZIONE TIPI DI FILE > CUSTOMIZE

e inserire nel campo le estensioni “thtml” e “ctp” per poi trasferirle con la freccietta

Impostazioni di Notepad++

Per abilitare la gestione in Dreamweaver, potete seguire questo tutorial: http://www.techwave.it/blog/2010/03/09/visualizzare-i-files-thtml-e-ctp-in-dreamweaver/

Controllare lo stato di un campo con AJAX e CakePHP

Foto di Danilo Rizzuti

Foto di Danilo Rizzuti

Immaginiamo di avere un form con una select che mi permette di selezionare la nazione a cui fa riferimento l’articolo.
Voglio consentire che l’utente traduca la nazione selezionata nella sua lingua nativa senza uscire dalla compilazione del form.
Leggi l’appunto »

Cakephp: leggere la configurazione del database

A volte si usano Vendors di terze parti che hanno un proprio accesso al DB, quindi è utile passare i parametri di collegamento al DB specificati in app/config/database.php.

if (class_exists('DATABASE_CONFIG')) {
	$dbconfig =& new DATABASE_CONFIG();
}

$host = $dbconfig->default['host'];
$login = $dbconfig->default['login '];
$password= $dbconfig->default['password'];

Ordinare i risultati con i campi dei model associati ricorsivamente: ORDER BY FIELD.

Il titolo è un po’ contorto, ma non sono riuscito a trovare di meglio.
L’esigenza nasce quando voglio ordinare il risultato di una query che vede interessati vari Model utilizzando un determinato campo per l’ordinamento.
Faccio l’esempio: ho i seguenti model e le seguenti relazioni.

Continent hasMany Country
Country hasMany News

Il modello Continent ha un campo ‘order’ che serve a mantenere un determinato ordine di presentazione per i continenti.
Voglio ottenere una lista di News ordinate per Continent.order.
Poichè il model News ha molte relazioni con altri model (Tag, Area, Comment, ecc. ecc. ), utilizzo il behavior Containable.
A questo punto non è sufficente impostare l’elemento ‘order’ a ‘Continent.order ASC’, perchè la query restituisce un errore. Infatti CakePHP esegue prima una query per ricavare l’elenco delle News e per ogni News ricavata esegue una successiva query per determinare il continente relativo al country.

//
$this->Continent->find('all', array('order' => 'Continent.name')) // Restituisce un errore nell query SQL
//
 

SOLUZIONI
Una soluzione generica che risolve ampiamente il problema è impiegare questo behavior suggeritomi da fzanardo nel forum, ma che non ho personalmente provato.

Una soluzione light invece è la seguente:

// estraggo gli di dei continenti ordinati in base al campo 'order'
$continents = array_keys($this->News->Country->Continent->find('list',array('fields'=>array('id','order'),'recursive'=>-1,'order'=>'order')));

$lista = $this->News->find('all',array(	'conditions'=>$conditions,
												'contain'=>array(
															'Area',
															'Country'=>array('Continent'),
														),
												'order' => array('FIELD(Country.continent_id,'.implode(',',$continents).')')

ORDER BY FIELD(Country.continent_id, 1,4,3,6,5,2) sarà l’impostazione del’ordine che consentirà di ottenere l’ordine voluto, mantenendo la query leggera.
Riferimento: http://cakebaker.42dh.com/2008/06/10/order-by-field/

Attenti al model del plugin in CakePhp

Quando si crea un plugin, si possono utilizzare la maggior parte delle convenzioni comuni, facendo attenzione però al model.
Ad esempio: ho un plugin chiamato categories che mi consente di gestire le categorie strutturate con gerarchia ad albero e in questo plugin dichiaro il model Category.
Se nella mia applicazione voglio creare una relazione con il model Article dovrò fare attenzione di inserire nel campo ‘className’ il nome del plugin anteposto al nome del model, così come nell’esempio riportato qui sotto.

var $belongsTo = array(
        'Category' => array(
            'className' => 'Categories.Category',
            'foreignKey' => 'category_id'
        )
    );

Riferimento al manuale: http://book.cakephp.org/view/117/Plugin-Models

poEdit e i file .ctp

Se si tenta di utilizzare poEdit per la traduzione di file con estensione .ctp inizialmente si ottiene un messaggio del tipo:
“Poedit non ha trovato alcun file nelle directory analizzate”
Se si va in File > Preferenze > Parser e si modifica PHP si può aggiungere una estensione e si avrà una lista del tipo
“*.php;*.ctp”
Ma questo non basta perchè si otterrebbe un messaggio del tipo:
“xgettext: warning:file `users/login’ extension `ctp’ is unknown;will try C”

Per far processare correttamente i file .ctp da poEdit è sufficente aggiungere una riga nel comando del parser.

  1. Aprire le preferenze di poEdit
  2. Selezionare Parsers e scegliere PHP
  3. Modificare il setup del parser PHP e alla fine del comando del parser aggiungere:
    --language=php

Riavviare il programma

Estendere un controller

Per estendere un controller è sufficente importare il controller da inserire prima della dichiarazione della nuova classe che ne è l’estensione.

Esempio:

App::import('Controller', 'Nodes');
class ArticlesController extends NodesController {
    var $name = 'Articles';
}

Giusto da far notare che si deve importare “Nodes” e non “NodesController”

Successiva »