Aplikacje internetowe

Bełdziowe spojrzenie na aplikacje internetowe

Kolejne starcie

W dzisiejszej notce zajmiemy się obsługą podstawowych elementów Kohany. Zapoznamy się z obsługa elementów MVC. Nauczymy się m.in. korzystać z bazy danych oraz operować na obrazach. Do dzieła!

Listowanie zdjęć

Z listowaniem zdjęć spotkamy się w czterech miejscach: na stronie głównej jako listę ostatnio dodanych fotek, w RSS, przeglądarce kategorii oraz wyszukiwarce. Do obsłużenia tych operacji posłużymy się dwoma metodami. Pierwsza będzie odpowiadała za wyszukiwarkę druga za pozostałe operacje.

public function get( $cat_id, $offset, $where = null )
{
   if( $cat_id )
      $where = array( 'f.cat_id'=> $cat_id );

   return $this -> db -> select( 'f.id, f.name, f.file, u.username' )
                      -> orderby( 'f.id', 'DESC' )
                      -> limit( 20, $offset )
                      -> join( 'users AS u', 'f.user_id = u.id' )
                      -> getwhere( 'fotos AS f', $where );
}

W powyższym kodzie przy pomocy Active Record budujemy zapytanie pobierające z tabel fotos oraz users dane potrzebne do wyświetlenia zdjęć czyli id zdjęcia, tytuł zdjęcia, nazwę pliku oraz login użytkownika, który owe zdjęcie dodał.

Do pobrania wyników wyszukiwania posłużymy się „czystym” SQL. Powodem takiego działania jest konstrukcja warunku WHERE, którego uzyskanie przy pomocy Active Records jest ciężkie.

public function search( $cat_id, $word, $offset )
{
   if( $cat_id )
      $sql = 'AND f.cat_id = '. $cat_id;

   return $this -> db -> query( 'SELECT f.id, f.name, f.file, u.username
                                 FROM fotos AS f
                                 INNER JOIN users AS u ON f.user_id = u.id
                                 WHERE (f.name LIKE "%'. $word .'%"
                                 OR f.desc LIKE "%'. $word .'%" )'.
                                 $sql.'
                                 ORDER BY f.id DESC
                                 LIMIT '. $offset .', 20' );
}

Poniżej znajdują się sposoby wywołania obu metod:

  • ORM :: factory( ‚foto’ ) -> get( NULL, 0 ) – pobranie ostatnich 20 zdjęć – wykorzystywane zarówno w RSS jak i na stronie głównej
  • ORM :: factory( ‚foto’ ) -> get( 1, 10 ) – pobranie zdjęć z kategorii o id = 1 zaczynając od 10 zdjęcia
  • ORM :: factory( ‚foto’ ) -> search( 1, ‚a’, 10 ) – wynik będzie taki sam jak powyżej z tą różnicą, że wyświetlone zostaną tylko te zdjęcia, które w nazwie bądź opisie zawierają literę „a”

Tworzenie miniatur

Powyższy kod mimo, że zapewni nam wyświetlanie zdjęć posiada jedną wadę – wyświetlone zdjęcie będą w oryginalnym rozmiarze. Musimy więc wyposażyć się w mechanizm tworzenia miniatur. Kohana udostępnia nam bibliotekę Image, która umożliwia w prosty sposób manipulację obrazkami. Przy jej pomocy wygenerujemy miniatury dla naszych zdjęć.

Kontroler odpowiedzialny za generowanie miniatur składa się z czterech metod. Pierwsza z nich będzie spełniała rolę kontrolną. Po otrzymaniu nazwy pliku oraz trybu będzie sprawdzała czy w cache istnieje wygenerowana miniatura, jeśli tak wywoła metodę odpowiedzialną za jej wyświetlenie, w przeciwnym wypadku zajmie się jej generowaniem. Wspomniany tryb to nic innego jak identyfikator na podstawie, którego będziemy określać rozmiary miniatury.

public function index( $file, $mode )
{
   if( !$file )
      exit;
			
   $thumbnail = str_replace( '.', '_' . $mode . '.', $file );

   if( file_exists( Kohana :: config( 'cache.default.params' ) . '/' .  $thumbnail ) )
      $this -> show( $thumbnail );
   else
      $this -> createThumbnail( $file, $mode );
}

W powyższym kodzie prócz opisanego wcześniej działania sprawdzamy czy przekazana została nazwa pliku, jeśli nie kończymy działanie skryptu. Dodatkowo tworzymy nazwę pliku miniatury tak, aby zawierała w sobie nazwę trybu.

Zajmijmy się teraz właściwym procesem generowania miniatury. Na początku pobieramy z pliku konfiguracyjnego rozmiary miniatury na podstawie przekazanego trybu. Kolejnym krokiem jest próba otwarcia obrazka, a następnie zmiana jego rozmiaru. Dodatkowo sprawdzamy czy pobrane wymiary nie są równe 0. Sytuacja taka ma miejsce w chwili gdy chcemy wyświetlić zdjęcie w oryginalnym rozmiarze. Na końcu zapisujemy miniaturę po czym ją wyświetlamy.

private function createThumbnail( $fileName, $mode )
{
   $mode = Kohana :: config( 'thumbnail.' . $mode );

   try
   {
      $image = new Image( Kohana :: config( 'upload.directory' ) .'/' . $fileName );
   }
   catch( Exception $e )
   {
      exit;
   }

   if( $mode[ 'w' ] !== 0 && $mode[ 'h' ] !== 0 )
      $image -> resize( $mode[ 'w' ], $mode[ 'h' ], Image :: AUTO );
			
   $thumbnail = str_replace( '.', '_' . $mode . '.', $fileName );
  $image -> save( Kohana :: config( 'cache.default.params' ) . '/' . $thumbnail );
			
   $this -> show( $thumbnail );
}

Ostatnią metodą do omówienia jest pokazanie zdjęcia użytkownikowi. Osiągamy to za pomocą:

private function show( $fileName )
{
   $fileEx = file :: extension( $fileName );
   $fileMime = Kohana :: config( 'mimes.' . $fileEx );
			
   header( 'Content-type: ' . $fileMime[0] );
   readfile( Kohana :: config( 'cache.default.params' ) . '/' . $fileName );
   exit;
}

W powyższym kodzie korzystamy z helpera file, który można znaleźć na svn. Dodatkowo w kontrolerze znajduje się magiczna metoda __call, dzięki której możemy pominąć bezpośrednie odwoływanie się do akcji index.

Uzupełnieniem powyższego kodu jest plik konfiguracyjny zawierający informacje o rozmiarach miniatur.

$config = array( 'normall' => array( 'w' => 0,
                                     'h' => 0 ),
             'foto'        => array( 'w' => 127,
                                     'h' => 98  ),
             'preview'     => array( 'w' => 500,
                                     'h' => 350 ),
             'gm'          => array( 'w' => 200,
                                     'h' => 150 ),
             'marker'      => array( 'w' => 60,
                                     'h' => 60 ) );

Kanał RSS

Zajmijmy się teraz wygenerowaniem kanału RSS zawierającego 20 ostatnio dodanych zdjęć. W punkcie Listowanie zdjęć został opisane sposób wyciągnięcia potrzebnych danych z bazy. Teraz zajmiemy się samym kanałem RSS.

Kohana posiada w sobie helper umożliwiający obsługę formatu RSS. Przy jego pomocy generowanie kanału ogranicza się to wygenerowania odpowiedniej tablicy z danymi.

$lastFotos = ORM :: factory( 'foto' ) -> get( NULL, 0 );
foreach( $lastFotos as $foto )
{
   $fotos[ ] = array( 'title'       => $foto -> name,
                      'link'        => url :: base( ) . 'foto/show/' . $foto -> id . '/' . url :: title( $foto -> name ),
                      'description' => html :: image( 'thumbnail/' . $foto -> file . '/foto' ),
                      'author'      => $foto -> username,
                      'pubDate'     => $foto -> add );
}

header( 'Content-type: text/xml' );
die( feed :: create( array( 'title' => 'tytul strony',
                            'link'  => url :: base( ) ),
                     $fotos ) );

Zarządzanie zdjęciami

Po dodaniu zdjęcia użytkownik może zapałać chęcią jego edycji lub usunięcia. Linki do obu opcji znajdują się na stronie zdjęcia. Nie możemy jednak „tak po prostu” ich tam umieścić ponieważ każdy użytkownik miałby do nich dostęp. Musimy sprawdzić czy aktualny użytkownik jest autorem zdjęcia, bądź też czy jest administratorem.

<? if( Session :: get( 'auth_user' ) -> id == $foto -> user_id || 
       Auth :: instance( ) -> logged_in( 'admin' ) ): ?>
   <li>
      <strong>Zarz±dzanie:</strong>
      <?= html :: anchor( 'foto/edit/' . $foto -> id, 'Edytuj' ) ?>
      <?= html :: anchor( 'foto/delete/' . $foto -> id, 'Usuñ' ) ?>
   </li>
<? endif ?>

Sposób edycji danych poznaliśmy w notce Praca z formularzami II tak więc zostanie on pominięty, zajmijmy się więc opcją usuwania.

$foto = new Foto_Model( $id );
if( ( Session :: get( 'auth_user' ) -> id != $foto -> user_id ) && !$this -> auth -> logged_in( 'admin' ) )
   url :: redirect( '/' );

   $foto -> delete( );

   Session :: instance( ) -> set_flash( 'flash', Kohana :: lang( 'foto.deleted' ) );
   url :: redirect( '/' );

W powyższym kodzie pobieramy dane zdjęcia o identyfikatorze przekazanym przez użytkownika. Następnie sprawdzamy czy jest on autorem zdjęcia bądź też administratorem. Jeśli tak usuwamy zdjęcie, a następnie dodajemy do sesji komunikat o poprawności wykonania operacji po czym przekierowujemy użytkownika na stronę główną.


Tagi:
Kategoria: Kohana, Tutorial


10 komentarzy

  1. piszesz na serio bardzo konkretne arty, wiele dające, ale byłoby jeszcze cudniej gdybyś zainstalował jakąś wtykę do kolorowania składni… pozdrawiam.

  2. thx, kwestie wtyki przemyślę i zapewne coś się pojawi :-)

  3. Bardzo fajne tutoriale:). Czy mógłbyś do ostatniej części dołączyć całość kodu?
    Z góry dziękuję:)

  4. spox, wieczorem wrzucę :)

  5. hmmm http://www.beldzio.com/zrzut/zalka.rar wydaje się być kompletnym kodem

  6. Dziękuję, działa jak trzeba:).

    Próbuję zrobić własny system logowania, ale niestety ciągle dostaję błąd:
    C:/xampp/htdocs/kohanalogowanie3/system/libraries/ORM.php [364]:
    The table property does not exist in the User_Model class.

    Wiesz może z czego on wynika? Zastanawiam się po czym powinien dziedziczyć model. Mój dziedziczy po Auth_User_Model, wcześniej próbowałem po prostu Model i działały przynajmniej niektóre metody (sprawdzenie czy użytkownik jest już w bazie). Chociaż przy próbie logowania pojawiał się błąd:
    Fatal error: Call to undefined method User_Model::has() in C:\xampp\htdocs\kohanalogowanie3\modules\auth\libraries\drivers\Auth\ORM.php on line 90

    Poza tym zastanawiam się czy w modelu muszą się znajdować jakiekolwiek zmienne i metody, jeżeli nie robimy walidacji.

    Z góry dziękuję za odpowiedź.
    Pozdrawiam.

  7. Jeśli kod z załącznika działa to zobacz kontroler login oraz model user znajdujące się w nimi porównaj ze swoim kodem :)

  8. Przyznam się, że zazwyczaj takie odpowiedzi mnie denerwują, bo jak to można posądzać mnie o to, że nie sprawdziłem wszystkiego co się dało, ale tym razem była to odpowiedź właściwa:)).

    Zrobiłem tak: oczyściłem Twój model i w tym momencie był identyczny jak mój.
    Usunąłem cała walidację i miałem dokładnie ten sam kod odpowiedzialny za logowanie (2 linijki…), z tą subtelną różnicą, że u mnie dalej sypało błędami.
    W końcu przekopiowałem zawartość modules i ruszyło (nie wiem jak na to wpadłem)… Trudno odpowiedzieć mi teraz, dlaczego tak się stało skoro Auth pobrałem razem z kohana ze strony, a konfiguracji nie ruszałem.
    Posiedzę jeszcze nad tym i może coś wywnioskuję:)
    W każdym razie dziękuję za pomoc. Mam nadzieję, że nie wyczerpałem jeszcze Twojej cierpliwości, bo niedługo pewnie znowu nie będę czegoś wiedział (chociaż tym razem będę się starał zadawać mniej retoryczne pytania;))).

    Pozdrawiam.

  9. wilman napisał(a):

    Bełdzio, możesz podrzucić jeszcze zrzut bazy danych? Bo w paczce z kodem go chyba nie ma ;)
    Pozdrawiam

Dodaj komentarz