CakePHP: Checkbox zamiast multiselect
Opublikowano 2010-09-19 12:17:25 CakePHP HABTM
Załóżmy, że mamy model Post i Tag posiadający relację HABTM. Tworząc widok dodawania nowego postu chcemy mieć możliwość wyboru tagów które są przypisane do postu. Standardowo napiszemy w naszym widoku:
echo $this->Form->input('Tags', array(
'label'=>__('Tagi',true)
));
Spowoduje to stworzenie elementu select z opcją wielokrotnego wyboru. Jest to element na ogół kłopotliwy ze względu na konieczność używania przycisku control w trakcie zaznaczanie, co ze strony użyteczności jest wielkim nieporozumieniem. CakePHP przychodzi nam z pomocą i umożliwia bardzo proste rozwiązanie problemu. Wystarczy do tablicy parametrów dodać klucz multiple z wartością checkbox. Skutkuje to stworzeniem serii elementów checkbox. Całość wygląda następująco.
echo $this->Form->input('Tags', array(
'label'=>__('Tagi',true)
,'multiple'=>'checkbox'
));
Na ogół jest to rozwiązanie lepsze niż element select. Sposobem najlepszym jest jednak stworzenie elementu ktory nazywam 'multiselect-checkbox'. Do stworzenia jego potrzebujemy jednak użyć nieco javascriptu. Można się wkrótce spodziewać artykułu na ten temat.
jQuery: Jak sprawdzić czy element istnieje?
Opublikowano 2010-09-18 22:48:09 JavaScript jQuery
Jak sprawdzić czy element istnieje za pomocą jQuery? Jak sprawdzić ile takich elementów istnieje? Ostatnio spotkałem się z takim problemem. Naturalnym odruchem jest napisanie następującego kawałka kodu:
var x = $('.some-element');
if(x) {//zakładamy że ten fragment kodu wykona się tylko wtedy gdy element istnieje
alert('Błędne rozwiązanie!');
}
Niestety rozwiązanie to jest jak najbardziej błędne. Zmienna x zawsze będzie istnieć, będzie obiektem jQuery. Prawidłowy sposób polega na sprawdzeniu właściwości length tego obiektu. Wartość tej właściwości jes równa ilości znaleźionych elementów.
var x = $('.some-element');
if(x.length) {
alert('Znaleziono ' + x.length + ' elementów.');
}
Rozwiązanie proste, ale może wpędzić w chwilę zakłopotania, jeżeli nie znamy prawidłowego sposobu.
CakePHP: Korzystanie z helpera z poziomu innego helpera
Opublikowano 2010-09-16 23:30:56 CakePHP
Co należy zrobić żeby móc korzystać z jakiegoś helpera w CakePHP z poziomu innego helpera? Zadanie jest banalne i nie różni się niczym od korzystania z helperów w zwykłym kontrolerze. Zarówno sposób zaincludowania jak i sposób dostępu do helpera jest identyczny. W zaprezentowanym fragmencie kodu korzystam z HtmlHelper z poziomu stworzonego przezemnie MyHelper.
class MyHelper extends AppHelper {
var $helpers = array('Html');
function myMethod() {
return $this->Html->link('Moja strona', 'http://tomaszmazur.eu');
}
}
CakePHP: Dynamiczne ładowanie zewnętrznych modeli
Opublikowano 2010-09-04 12:33:26 CakePHP
Czasami zdarza się konieczność korzystania z modelu niepowiązanego z danym modelem/kontrolerem. Przykładem z życia wziętym jest model Setting - prosta tablica zawierajaca różne ustawienia do naszej aplikacji, prawdopodobnie modyfikowalne z poziomu panelu administracyjnego. Będziemy korzystać z tego modelu w bardzo wielu niepowiązanych modelach. W moich aplikacjach model ten zazwyczaj nie posiada żadnych powiązań. Częstym błędem początkujących programistów CakePHP jest próba korzystania z modelu z poziomu kontrolerów za pomocą właściwości $uses.
var $uses = array('Model1','Setting')
Spowoduje to załadowanie modelu Setting przy każdym uruchomieniu kontrolera. Jezeli kontroler posiada metody(akcje) dla których model Setting jest niepotrzebny, to podany kawalek kodu nie jest optymalny. Korzystanie z modelu Setting obywa sie teraz na zasadach analogicznych do korzystania z natywnego modelu kontrolera.
$results = $this->Setting->findById('1');
Zalecaną metodą ładowania zewnętrznych modeli jest ładowanie dynamiczne. Następującą linijkę kodu należy umieścić w metodzie wymagającej dostęp do modelu Setting.
$this->loadModel('Setting');
Korzystanie z modelu odbywa się na zasadach analogicznych do metody z $uses. Jest to zalecana metoda korzystania z zewnętrznych modeli.
Jeżeli zajdzie konieczność skorzystania z zewnętrznego, niepowiązanego modelu z poziomu jakiegos modelu, z przyczyn oczywistch nie możemy skorzystać z powyższej metody. Informacja dla nieco mniej obeznanych czytelników, metoda loadModel istnieje w klasie Controller, która jest niedostępna z poziomu modelu. Należy zatem skorzystać z ClassRegistry::init() w następujący sposób
$setting = ClassRegistry::init("Setting");
$results = $setting->findById('1');
Dodam, że nie zdażyła mi się jeszcze koniecznośc załadowania zewnętrznego modelu z poziomu innego modelu. Można oczywiście korzystać z instrukcji ClassRegistry::init() z poziomu kontrolera. Należy jednak pamiętać, aby przypisać model do zmiennej, z której będzie korzystać.
$setting = ClassRegistry::init("Setting");
//$results = $this->Setting->findById('1');
$results = $setting->findById('1');
Zakomentowana linijka nr 2 jest niepoprawna i zwróci błąd. Tyle w temacie dynamicznego ładowania modeli.
CakePHP: IdeaCache - Internal Server Error 500
Opublikowano 2010-09-02 15:33:20 CakePHP
Artykuł ten jest kontynuacją poprzedniego, dotyczącego błędu w aplikacjach CakePHP na serwerach home.pl. Element, który sprawia kłopot na tych serwerach to IdeaCache. Ten i podobne problemy zostały opisane w następujących linkach:
1. http://cakephp.lighthouseapp.com/projects/42648/tickets/817-class-cakelog-not-found
2. http://cakephp.lighthouseapp.com/projects/42648/tickets/923
Aby naprawić ten błąd należy zamienić kawałek kodu w pliku /cake/libs/cake_log.php
z
if (!defined('DISABLE_DEFAULT_ERROR_HANDLING')) {
set_error_handler(array('CakeLog', 'handleError'));
}
na
if (!defined('DISABLE_DEFAULT_ERROR_HANDLING')) {
$cakeLog =& CakeLog::getInstance();
set_error_handler(array(&$cakeLog, 'handleError'));
}
Musimy pamiętać o tym, że jest to ingerencja w źródła CakePHP. Przy każdej aktualizacji, będziemy musieli podmieniać wyżej wymieniony fragment kodu. Pomimo tej wady, zdecydowałem się na zastosowanie tego fixa. Jeżeli to nie zadziała, to w wyżej wymienionych linkach są również podane inne sposoby naprawy.