Google

Kategorie

Reprezentacja Wiedzy

Kalendarz

January 2012
M T W T F S S
« Jan    
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

Najbliższe urodziny osoby

January 21st, 2009 by prond

Jak pobrać daty najbliższych urodziń na podstawie dat urodzenia ?
Może tak : ?

SELECT
	CASE
		WHEN STR_TO_DATE(CONCAT(YEAR(NOW()),'-',MONTH(birth_date),'-',DAY(birth_date)),'%Y-%m-%d') < NOW()
			THEN STR_TO_DATE(CONCAT(YEAR(NOW()),'-',MONTH(birth_date),'-',DAY(birth_date)),'%Y-%m-%d') + INTERVAL 1 YEAR
		ELSE STR_TO_DATE(CONCAT(YEAR(NOW()),'-',MONTH(birth_date),'-',DAY(birth_date)),'%Y-%m-%d')
	END AS birthday
FROM
	users
ORDER BY
	birthday;

Posted in MySQL | No Comments »

CakePHP 1.2 hABTM Segmentation fault

March 27th, 2008 by prond

Znalazłem ostatnio bardzo nieprzyjemny bug w CakePHP 1.2 - po zdefiniowaniu relacji belogsTo i hasAndBelongsToMany (przyklad ponizej) dostajemy segmentation fault przy próbie wypieczenia kontrolera.

class Tag extends AppModel {
 
	var $name = 'Tag';
	var $useTable = 'tags';
	var $validate = array(
		'name' => array('required'),
		'lft' => array('numeric'),
		'rght' => array('numeric')
	);
 
	var $hasAndBelongsToMany = array (
		'Entry' => array('className' => 'Entry',
			'joinTable' => 'entries_tags',
			'foreignKey' => 'tag_id',
			'associationForeignKey' => 'entry_id',
			'unique' => true,
		)
	);
 
	var $belongsTo = array(
		'Parent' => array ( 'className' => 'Tag',
			'foreignKey' => 'parent_id',
			'conditions' => '',
			'fields' => '',
			'order' => ''
		)
	);
 
	var $actsAs = array('Tree');
}

Read the rest of this entry »

Posted in CakePHP | No Comments »

CakePHP Theme View

January 3rd, 2008 by prond

Ostatnio pokazała się krótka i zwięzła notka o tym jak stosować motywy w CakePHP 1.2 :

http://www.sanisoft.com/blog/2007/12/29/theming-your-cakephp-apps-v12/

Posted in CakePHP | No Comments »

MySQL stawianie repliki

December 31st, 2007 by prond

1) Sprawdzenie statusu serwera MASTER

Łączymy się z serwerem MASTER i wpisujemy polecenie show master status;.
Powinniśmy otrzymać mniej więcej taki rezultat jak poniżej. Jeżeli tak to można od razu przejść do punktu #3.

mysql> show master status;
+------------------+----------+-----------------------------+------------------+
| File             | Position | Binlog_Do_DB                | Binlog_Ignore_DB |
+------------------+----------+-----------------------------+------------------+
| mysql-bin.000069 |       98 | cms_company_1,cms_company_2 |                  |
+------------------+----------+-----------------------------+------------------+
1 row in set (0.00 sec)

Jeżeli otrzymamy pusty wynik należy skonfigurować bin loga (punkt #2)

mysql> show master status;
Empty set (0.00 sec)

2) Konfiguracja serwera MASTER

W pliku konfiguracyjnym MySQL (na Debianie /etc/mysql/my.ini) należy zdefiniować ścieżkę bin loga:

log_bin = /var/log/mysql/mysql-bin.log

W tym samym pliku należy ustawić server-id. Uwaga : replikacja nie działa jeżeli serwer MASTER i SLAVE mają takie same server-id

server-id = 360

Mamy jeszcze dodatkowo takie parametry jak, ktorych nazwy sa chyba na tyle intuicyjne, że nie potrzeba tłumaczyć ich znaczenia.

expire_logs_days	= 10
max_binlog_size         = 100M
binlog_do_db		= cms_company_1
binlog_do_db		= cms_company_2
#binlog_ignore_db	= test

3) Backup replikowanych baz danych z serwera MASTER

Wygodnie jest zrobić backup replikowanych baz danych razem z informacją o punkcie startu replikacji (opcja master-data)

mysqldump -h{nazwa_hosta} -P{port} -u{nazwa_uzytkownika} -p{haslo} --master-data=2 {nazwa_bazy_danych} > {nazwa_pliku_sql}

Ja ustawiam zwykle opcję master-data=2, tak aby polecenie definujące punkt startu replikacji było wykomentowane:


– Position to start replication or point-in-time recovery from

– CHANGE MASTER TO MASTER_LOG_FILE=’mysql-bin.000068′, MASTER_LOG_POS=240;

4) Sprawdzenie statusu serwera SLAVE

Łączymy się z serwerem MASTER i wpisujemy polecenie show slave status;.
W przypadku, gdy nie mamy postawionej repliki wynik powinien być pusty:

mysql> show slave status;
Empty set (0.00 sec)

Dla serwera z działającą repliką dostaniemy rezultat jak poniżej. Powinniśmy wtedy zatrzymać replikę przy pomocy poleceń slave stop; reset slave;

mysql> show slave status;
+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+----------------------------+---------------+-----------------------+------------------+-------------------+------------------------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
| Slave_IO_State                   | Master_Host | Master_User | Master_Port | Connect_Retry | Master_Log_File  | Read_Master_Log_Pos | Relay_Log_File             | Relay_Log_Pos | Relay_Master_Log_File | Slave_IO_Running | Slave_SQL_Running | Replicate_Do_DB              | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Master_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Master_SSL_Allowed | Master_SSL_CA_File | Master_SSL_CA_Path | Master_SSL_Cert | Master_SSL_Cipher | Master_SSL_Key | Seconds_Behind_Master |
+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+----------------------------+---------------+-----------------------+------------------+-------------------+------------------------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
| Waiting for master to send event | master360   | master_user |        3306 |            60 | mysql-bin.001007 |            37474461 | master360-relay-bin.001460 |      37472499 | mysql-bin.001007      | Yes              | Yes               | cms_company_1, cms_company_2 |                     |                    |                        |                         |                             |          0 |            |            0 |            37474461 |        37472499 | None            |                |             0 | No                 |                    |                    |                 |                   |                |                     0 |
+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+----------------------------+---------------+-----------------------+------------------+-------------------+------------------------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
1 row in set (0.00 sec)

5) Konfiguracja i startowanie repliki

Przed włączeniem repliki należy się upewnić, że id serwera SLAVE jest różne od MASTER. W tym celu należy sprawdzić wartość zmiennej server_id.
Możną ją zmienić w pliku konfiguracyjnym (jak w punkcie #2) bądź poprzez polecenie set global server_id = {nowe_id};. Lepiej to jednak zrobić w pliku konfiguracyjnym, ponieważ przy restarcie serwera wartość zmienniej server_id jest brana właśnie stamtąd.

Teraz edytujemy (i odkomentowujemy) wygenerowane polecenie startu replikacji i dodajemy do niego dane niezbedne do polaczenia z serwerem MASTER.

CHANGE MASTER TO MASTER_HOST='{master_host}', MASTER_PORT={master_port}, MASTER_LOG_FILE='{master_log_file}',MASTER_LOG_POS={master_position}, MASTER_USER='{master_user}', MASTER_PASSWORD='{master_password}'

Robimy restore bazy z backupów.

mysql -h{nazwa_hosta} -P{port} -u{nazwa_uzytkownika} -p{haslo} {nazwa_bazy_danych} < {nazwa_pliku_sql}

Startujemy replikę.

mysql> slave start;

Sprawdzamy status repliki.

mysql> show slave status;

Posted in MySQL | No Comments »

CakePHP .pot generator

December 28th, 2007 by prond

Prosty i prymitywny generator plikow .pot dla aplikacji napisanej w CakePHP.
Wystarczy odpalic ten skrypt z katalogu pod którym jest aplikacja.

for file in $(ls app/views); do
xgettext -L PHP --keyword=__:1 --keyword=__d:2 --keyword=__dc:2 --keyword=__n:1,2 --keyword=__dn:2,3 --keyword=__dcn:2,3 -p app/locale/ -o $file.pot app/controllers/${file}_controller.php app/views/$file/*.ctp
done

Posted in CakePHP | No Comments »

CakePHP MySQL CollationBehavior

December 28th, 2007 by prond

Aplikacje wielojęzykowe przyspażają wielu problemów. Jednym z nich jest sortowanie wyników zapytania.
W MySQL mamy wiele opcji porównywania napisów. Ja najczęściej stosuję utf8_general_ci, ale przy tej opcji “ogonki” lądują na końcu zwracanych wyników (po znakach ASCII). Można jednak w zależości od wybranego języka używać innych COLLATION, np.:

SELECT *
FROM products
ORDER BY name COLLATE utf8_polish_ci
LIMIT 10;

Tutaj “ą” wystąpi przed “b” i tak dalej.
Jako, że najczęściej piszę aplikacje w CakePHP zrobiłem dla tego frameworka mały behavior, który ułatwia mi życie dostosowując COLLATION do aktualnie ustawionego języka.
Read the rest of this entry »

Posted in CakePHP | No Comments »

Drag Drop Tree oparte na prototype i script.aculo.us

December 5th, 2007 by prond

Od pewnego czasu wykorzystuję w projektach gotowe skrypty drzewek z drag&drop.
Niestety jak dotąd nie znalazłem takiego, które:

  • pozwala na umieszczenie na stronie kilku instancj
  • współpracuje dobrze z prototype i script.aculo.us
  • pozwala łatwo i bez modyfikacji kodu dołączyć funkcję, która wyśle AJAXem dokonaną modyfikację struktury drzewa

Dlatego przyszła pora na napisanie własnego drzewka, opartego właśnie na prototype i script.aculo.us.

Demo wciąż aktualizowanej wersji umieściłem na http://weblog.axent.pl/examples/js.drag-drop-tree/.

Po zaimplementowaniu wszystkich podstawowych funkcji wrzucę tu dokumentację. Póki co dostępne są następujące funkcje:

  • opuszczanie elementów _pod_ i _za_ danym elementem
  • wywoływanie dowolnej funkcji przed i po zmianie struktury drzewa

Posted in Przykłady prac, Javascript | 2 Comments »

CakePHP, budowanie drzewa ACOs dla AuthComponent

December 3rd, 2007 by prond

CakePHP 1.2 udostepnia deweloperom bardzo wygodny AuthComponent. Dołączenie go w aplikacji jest na prawdę szybkie i przyjemne. Wystarczy zerknąć na następujące dwa tutoriale :

Wszystko idzie gładko aż do momentu, w którym chcemy zbudować drzewo Acos.
Read the rest of this entry »

Posted in CakePHP | No Comments »

Zapisywanie wielu rekordów w CakePHP

September 18th, 2007 by prond

Byłem ostatnio zmuszony do zbudowania w CakePHP aplikacji,
która miałaby pozwalać na masową edycję stron, produktów, etc.

Szperając na blogach i forach nie udało mi się jednak znaleźć rozwiązania,
które pozwalałoby jednocześnie korzystać ze wszystkich udogodnień CakePHP.

Po paru eksperymentach udało mi się zneleźć dość satysfakcjonujące rozwiązanie.
Przynajmniej nadal mogę korzystać z takich ‘automagicznych’ elementów jak
walidacja i helpera do formularzy.

Kontroler : controllers/pages_controller.php

function addMany($count = 2) {
    for ($i=1;$i&lt;=$count;$i++) {
        $modelName = "Page{$i}";
        $this->{$modelName} = & new Page;
        $this->{$modelName}->useTable = "page";
        $this->{$modelName}->name = $modelName;
        ClassRegistry::addObject("Page{$i}",$this->{$modelName});
    }
 
    if (!empty($this->data)) {
        for ($i=1;$i&lt;=$count;$i++) {
            $modelName = "Page{$i}";
            $this->{$modelName}->create($this->data);
            $this->{$modelName}->save();
        }
    }
 
    $languages = $this->Page->Language->generateList();
 
    $this->set('count',$count);
    $this->set(compact('languages'));
}

Widok : views/pages/add_many.php

    <div class="page">
    <form action="" method="post">
    <?php for ($i=1;$i<=$count;$i++) : ?>
        <fieldset>
            <legend><?php __('Add');?> <?php __('Page');?></legend>
        <?php
            echo $form->input("Page{$i}.language_id");
            echo $form->input("Page{$i}.name");
            echo $form->input("Page{$i}.urn");
            echo $form->input("Page{$i}.description");
            echo $form->input("Page{$i}.keywords");
            echo $form->input("Page{$i}.published_from");
            echo $form->input("Page{$i}.published_to");
            echo $form->input("Page{$i}.published");
            echo $form->input("Page{$i}.contents");
        ?>
        </fieldset>
    <?php endfor; ?>
    <?php echo $form->end('Submit');?>
    </div>
    <div class="actions">
        <ul>
            <li><?php echo $html->link(__('List', true).' '.__('Pages', true), array('action'=>'index'));?></li>
            <li><?php echo $html->link(__('List', true).' '.__('Languages', true), array('controller'=> 'languages', 'action'=>'index')); ?> </li>
            <li><?php echo $html->link(__('New', true).' '.__('Language', true), array('controller'=> 'languages', 'action'=>'add')); ?> </li>
        </ul>
    </div>

Posted in CakePHP | 15 Comments »

CakePHP 1.2 : zapisywanie modeli

August 23rd, 2007 by prond

Domyślnie ‘wypieczony’ w Cake 1.2 kod zapisujący model wygląda następująco:

function add() {
	if (!empty($this->data)) {
		$this->cleanUpFields();
		$this->Page->create();
		if ($this->Page->save($this->data)) {
			$this->Session->setFlash('The Page has been saved');
			$this->redirect(array('action'=>'index'), null, true);
		} else {
			$this->Session->setFlash('The Page could not be saved. Please, try again.');
		}
	}
}

Moim zdaniem brakuje w nim rozróżnienia sytuacji, w której pola są nie poprawne od błędu przy zapisie do bazy.
Read the rest of this entry »

Posted in CakePHP | No Comments »

« Previous Entries