Wszystkie wpisy, których autorem jest kelu

[PHP] Zapytania do bazy i kodowanie

Napotkałem na znany pewnie dosyć problem polskich znaków, ale nie mogłem znaleźć sensownego rozwiązania.
Problem miałem mianowicie z botami które przechowywały starą wersję strony która była jeszcze w kodowaniu ISO-8859-2 i przez to zapytania do formularza wyszukiwania wysyłały w tymże kodowaniu. Jako, że nasze kodowanie na stronie i w bazie jest teraz w UTF-8 to oczywiście zapytania z polskimi znakami które były przekazywane w pasku URL w złym formatowaniu wywalały błędy w zapytaniach SQL.

Porównanie URLi:

ISO-8859-2: example.com/?keyword=z%B3%B1czka
UTF-8: example.com/?keyword=złączka

Nie spodziewałem się, że rozwiązanie będzie tak proste, zrobiłem to przy pomocy takiej funkcji:

$keyword = mb_convert_encoding( $keyword, 'utf-8', array('UTF-8','ISO-8859-2') );

Funkcja ta po prostu próbuje przetworzyć kodowanie na utf-8. Dzięki temu, że w argumencie podałem oba kodowania to funkcja radzi sobie (w odpowiedniej kolejności) ze znakami zakodowanymi w obu kodowaniach i przetwarza je w odpowiedni ciąg (nie ma wymogu, żeby ciąg był w konkretnym kodowaniu – dzięki temu znaki w UTF-8 się nie zepsują po przepuszczeniu przez tą funkcję).

[php] Explode bez pustych stringów

Natrafiłem na mały problem, związany z uzyciem funkcji explode. Chciałem wywalić wszystkie elementy tablicy które są pustymi stringami. Można oczywiście przeiterować całą wynikową tablicę usuwając niepotrzebne wartości, ale znalazłem prostszą metodę przy pomocy wyrażeń regularnych:

$exploded = preg_split('@/@', '1/2//3/', NULL, PREG_SPLIT_NO_EMPTY);

Źródło: http://stackoverflow.com/questions/64570/explode-that-doesnt-return-empty-strings#answer-64608

MSSQL – Jak sprawdzić jakie zapytania zostały wywołane.

W pracy korzystamy z serwera magazynowego WF-MAG. Sklep mamy w PHP + mysql więc jest problem w synchronizacji danych między wf-magiem a stroną. WF-Mag oczywiście nie udostępnia informacji o wywoływanych procedurach czy zapytaniach na bazie, struktura bazy też nie jest zbyt przejrzysta (hahaha), więc zawsze jest trochę problematyczne pisanie zapytań do bazy. Na szczęście okazuje się, że jest zapytanie uniwersalne dla serwera MSSQL 2008 (nie wiem czy dla innych wersji też, nie sprawdzałem). Zapytanie wyrzuca po prostu wszystkie zapytania które były wywoływane ostatnio na bazie (także te ukryte przez WF-Maga).

SELECT deqs.last_execution_time AS [Time], dest.TEXT AS [Query]
FROM sys.dm_exec_query_stats AS deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest
ORDER BY deqs.last_execution_time DESC

Sprawdzanie miejsca zajmowanego przez katalogi i pliki

Kolejna prościutka komenda, a zawsze szukam jej po necie. Warto pamiętać, czasem jest to najlepszy sposób na sprawdzenie ile które katalogi zajmują. Mi się przydaje na hostingu, jak zaczyna brakować miejsca mogę sprawdzić na szybko który katalog najwięcej miejsca zabiera. Komenda oczywiście wypisuje miejsce zajmowane przez pliki i katalogi w folderze w którym aktualnie się znajdujemy. Ponadto warto nadmienić, że sprawdza objętość katalogów rekursywnie, więc jest to bardzo praktyczna metoda.

du -sh ./*

Jeszcze warto czasem odpalić komendę w ten sposób, żeby posortować sobie po rozmiarach i sprawdzić co zajmuje najwięcej (jeśli mamy dużo plików w katalogu):

du -s ./* | sort -n

Jednoznaczny print Binary Search Tree w konsoli

Prawdę mówiąc szukałem i szukałem jakiegoś prostego rozwiązania na jednoznaczne wyświetlenie drzewa w konsoli i o ile problem wydaje się trywialny to nie znalazłem nic zadowalającego mnie. W takim wypadku należało samemu napisać coś prostego.

Mój pomysł jest banalny, ale wydaje się skuteczny – w jednoznaczny sposób z zapisu w konsoli jestem w stanie odczytać jakie drzewo mam zapisane w pamięci.

Oto kod:

void inorder(BinarySearchTreeNode* p)
{
	if(p != nullptr)
    {
		if (p != root && (p->left || p->right) ) cout << "{";
		if(p->left) 
        {
            inorder(p->left);
            cout << "<-";
        }

		cout << p->value;

        if(p->right)
        {
            cout << "->";
            inorder(p->right);
        }
		if (p != root && (p->left || p->right)) cout << "}";
   }
}

Kilka słów wyjaśnienia – w tym celu przykład:

{{0<-1->2}<-3->{4<-5->6}}<-7->{{8<-9->10}<-11->{12<-13->14}}

Żeby rozszyfrować to przykładowe drzewo muszę zawsze wziąć element nie zawarty w żadnym nawiasie (najwyżej) i potraktować go jako korzeń drzewa. W tym przypadku będzie to 7. Potem strzałeczki w lewo i prawo to jego poddrzewa – każde poddrzewo zawarte w nawiasie traktuje jako kolejne drzewo i rozpoczynam cały proces od początku. Jeżeli nie ma nawiasu to znaczy że doszliśmy do liścia. Koniec ;-)


(wybaczcie jakość rysunku, ale nie znalazłem żadnego narzędzia prostego do rysowania grafów xD)

Pobieranie selectora na rzecz którego wywołujemy metodę on() przy wykorzystaniu selectora dziecka

Dzisiaj odkryłem małą ciekawostkę dotyczącą funkcji on() w jQuery. Otóż rozważmy następujący kod:

<div class="container">
    <a href="#" class="click_element">CLICK</a><br/>
</div>
$("div.container").on("click", "a.click_element", function (event) {
    $(event.delegateTarget).append("delegateTarget dodaje tekst...<br/>");
    $(this).closest('div.container').append("Potem metoda closest()<br/>");
    $(this).parents('div.container').append("Można też przy pomocy parents().parent()<br/>");
    return false;
});

Okazuje się, że najlepiej korzystać z parametru eventu event.delegateTarget – jest to dokładnie funkcjonalność do której został stworzony. Jeśli dobrze to zrozumiałem, to przekazujemy w ten sposób selektor przy każdym wywołaniu tej przypiętej funkcji, czyli nic to nie kosztuje. Jednak przy bardziej skomplikowanych i zagnieżdżonych układach HTML’u metody closest() i parents() mogą zająć więcej czasu wykonania.

Link do fiddle’a: http://jsfiddle.net/HV8NS/.

Widget tabs – usuwanie zawartości taba przy przełączaniu

Korzystałem z jQueryUI tabs do ładowania contentu  przez ajax i próbowałem uzyskać efekt kółeczka które się ładuje podczas faktycznego ładowania zapytania. Kółeczko = loading

Problem w tym, że domyślnie widget tabs nie obsługuje takiej funkcjonalności.

Rozwiązanie:


<div class="tabs">
    <div>
        <ul>
            <li><a href="ajax1.php">Tab 1</a></li>
            <li><a href="ajax2.php">Tab 2</a></li>
        </ul>
    </div>
    <div class="loading" style="text-align: center;">
        <img src="images/loading.gif">
    </div>
</div>

 


$(".tabs").tabs({
    ajaxOptions: {
        cache: false
    },
    load: function() {
        $(".loading").hide();
    },
    beforeLoad: function(event, ui) {
        $(".loading").show();
        $(ui.panel).siblings('.ui-tabs-panel').empty();
    }
});

Najważniejsza część to $(ui.panel).siblings('.ui-tabs-panel').empty();. Ten kawałek powoduje, że przed załadowaniem treści przy pomocy ajax treść wszystkich tabów jest wyzerowana.

Do ściągnięcia działający przykład: tabs.rar

Start bloga

Witam Cię przypadkowy przybyszu :-)

Blog nie został założony pod „publikę”, więc raczej nie spodziewaj się cudów w wyglądzie czy jakiegoś ścisłego contentu. Celem bloga jest bardziej prowadzenie dziennika ciekawostek programistycznych czy technik które mogą mi się kiedyś jeszcze przydać. Jeśli ktoś na tym skorzysta - fine with me.

A więc do pracy!