Etykiety

czwartek, 30 listopada 2017

Laravel od podstaw: zapis danych z formularza

W poprzedniej części szkolenia, pt. Kontrolery zasobów przedstawiłem ogólny zarys kontrolerów zasobów oraz opisałem korzyści płynące z ich stosowania w środowisku Laravel. W tej części skupię się na opisie przykładowej procedury zachowania w tabeli bazy danych informacji wprowadzanych do formularza.

Tworzymy prosty formularz HTML i widok formularza


Aby rozpocząć przygotuję prosty formularz HTML, bez dodatkowej stylizacji, ponieważ stylami i zaawansowanymi widokami mam zamiar zając się w kolejnych części szkolenia. Zakładając, iż czytelnik zapoznał się z poprzednimi częściami szkolenia i wykonał opisanie w nich czynności, takie jak migracje i wprowadzanie szkoleniowych danych do tabeli, niniejsza część szkolenia stanowi kontynuację poprzednich części. Stworzę więc prosty formularz, poprzez który będzie można wprowadzać nowe posty do tabeli bazy danych.

Nasz szkoleniowy formularz HTML, zachowany w pliku
resources/views/posts/nowy.blade.php
względem katalogu głównego naszej szkoleniowej aplikacji, może wyglądać następująco:
<html>

 <head></head>

 <body>

 <form method="POST" action=" {{asset('/posty')}} ">

   {{ csrf_field() }}

  <div>
    <label for="title">Tytuł:</label>
    <input type="text" id="title" name="title">
  </div>

  <br />

  <div>
    <label for="body">Treść:</label>
    <textarea id="body" name="body"></textarea>
  </div>

  <br />

  <div>
    <button type="submit">Zapisz</button>
  </div>

 </form>

 </body>

Są dwa aspekty powyższego formularza, na które należy zwrócić szczególną uwagę, ponieważ są one związane ściśle ze środowiskiem Laravel.

Pole CSRF


Laravel ułatwia ochronę aplikacji przed atakami polegającymi na fałszowaniu żądań między witrynami (CSRF). Ataki typu "cross-site request" są rodzajem złośliwego exploita polegającego na wykonywaniu nieautoryzowanych poleceń w imieniu uwierzytelnionego użytkownika.

Funkcja csrf_field() wywołana w formularzu, ma za zadanie wstawić do formularza ukryte pole z wartością, która po wysłaniu formularza będzie porównywana z wartością zachowaną w specjalnie stworzoznej w celach kontrolnych zmiennej sesyjnej. Możemy podejrzeć źródło strony formularza, a wówczas zobaczymy, iż w formularzu widnieje element ukrytego pola z wartością w postaci długiego ciągu znaków. Jeśli do naszego formularza nie dodamy tej funkcji, wysłanie go nie będzie możliwe.

Akcja formularza


Jak zapewne czytelnicy dobrze wiedzą, atrybut action określa w formularzu HTML adres url, na który ma zostać wysłane żądanie HTTP formularza. W naszym przypadku będzie to żądanie typu POST, skierowane do adresu określonego przez funkcję asset(), która zwróci bezwzględny adres URL na podstawie określonego w niech adresu względnego '/posty'.

Po utworzeniu pliku formularza, musimy się zająć utworzeniem widoku. W tym celu do naszego pliku
routes/web.php
dodajemy wpis, kierujący żądanie HTTP typu GET adresu względnego posty/nowy do funkcji create() naszego kontrolera zasobów PostController:
Route::get('/posty/nowy', 'PostController@create');

Następnie w klasie naszego kontrolera zasobów PostController tworzymy metodę create(), wyświetlającą formularz, czyli zwracającą utworzony widok formularza:
 public function create() {

        return view('posts.create');

   }

Jeśli wszystkie czynności zostały wykonane zgodnie ze wskazówkami, po przejściu na względny adres url /posty/nowy naszej szkoleniowej aplikacji, w przeglądarce powinien się pojawić nasz szkoleniowy formularz html.

Szkoleniowa wersja przykładowego formularza html
Szkoleniowa wersja przykładowego formularza hrml

Wyświetlając źródło strony, warto przyjrzeć się efektom funkcji csrf_field(). Pole typu hidden oraz przypisana do niego wartość pojawiły się w efekcie zastosowania tej funkcji w kodzie.

Efekt działania funkcji csrf()
Efekt działania funkcji csrf()


Tworzymy nową trasę


Formularz jest już widoczny, lecz musimy utworzyć trasę dla akcji formularza, czyli przypisaną do żądania typu POST na adres /posty. W tym celu wystarczy dodać do naszego szkoleniowego pliku routes/web następującą zawartość, która będzie miała za zadanie przekierowywać takie żądanie do funkcji store() kontrolera PostController, której strukturę za chwilę przedstawię:
Route::post('/posty', 'PostController@store');

Tworzymy metodę store() w klasie kontrolera zasobów


Nasza metoda o nazwie store() będzie miala za zadanie wykonywać walidację formularza, a następnie zachowywać nowe posty w tabeli bazy danych. Kod naszej szkoleniowej funkcji jest bardzo krótki i przejrzysty:
 public function store() {

      // Podstawowa walidacja formularza
      $this->validate(request(), [

        'title' => 'required|min:3|max:60',
        'body'  => 'required|min:20|max:5000'

      ]);


      // Zachowuje nowy post, utwrzozony z pól title oraz body przesłanego formularza:
      Post::create(request(['title', 'body']));


      /**

      *         Alternatywnie, zamiast create()

      *         $post = new Post(request(['title', 'body']));
      *         $post->save();

      */

      // Przekierowanie do /posty
      return redirect('/posty');

Metoda validate(), służaca do walidacji danych formularza, jest dostępna z poziomu klasy naszego kontrolera i może przyjmować różne reguły. Więcej na temat dostępnych reguł walidacji formularzy można przeczytać w oficjalnej dokumentacji Laravel

Metoda create() tworzy nowy post z zapodanej kolekcji danych i zapisuje go w tabeli bazy danych.

Jednak to nie wszystko. Laravel chroni naszą aplikację przed atakami nie tylko opisaną wyżej funkcją csrf_field(), ale także w dodatkowy sposób. Aby dane z formularza zostały zachowane w bazie danych, należy określić w klasie naszego modelu, jakie dane mogą być modyfikowane przez użytkowników. A więc, aby nasz formularz i przygotowane funkcje zadziałały, wewnątrz klasy modelu Post, czyli w pliku app/Post.php należy dodać:
protected $fillable = ['title', 'body'];

Teraz wszystko powinno już działać. Sprawdźmy to:

 Nasz szkoleniowy formularz HTML
Nasz szkoleniowy formularz HTML


Nasza szkoleniowa dynamiczna lista postów
Nasza szkoleniowa dynamiczna lista postów

Wszystko wygląda tak jak powinno, oczywiście w wersji szkoleniowej, a nie produkcyjnej. Ale co z ewentualnymi błędami walidacyjnymi?

Błędy walidacji


Gdy korzystamy z metody validate() wewnątrz klas kontrolerów zasobów, zwraca ona ewentualne błędy walidacyjne do specjalnej zmiennej sesyjnej, która jest dostępna w skryptach formularzy w postaci tablicy $errors. Zobaczmy jak to działa w praktyce, dodając do naszego formularza kilka linijek kodu tuż po znaczniku końca formularza:
 <ul>

        @foreach ($errors->all() as $error)

                <li>{{$error}}</li>

        @endforeach


   </ul>

Następnie, mając na uwadze reguły walidacyjne spróbujmy wpisać do pól formularza po jednym znaku, a nstępnie wysłać formularz:

Testujemy walidację
Testujemy walidację


Błędy walidacyjne
Błędy walidacyjne

Informacje o błędach są w języku angielskich, ale tym zajmiemy się w kolejnych częściach szkolenia, jak również ładnie sformatowanymi formularzami, złożonymi widokami oraz stylami CSS.

Serdecznie zapraszam do kolejnej części szkolenia Laravel od podstaw, p.t. Szablony widoków i style CSS

środa, 29 listopada 2017

Laravel od podstaw: kontrolery zasobów

W poprzedniej części szkolenia Laravel od Podstaw, p.t. Modele wyjaśniłem jakie podstawowe funkcje pełnią modele w Laravel, oraz jak mogą one ułatwić pracę z tabelami bazy danych. W niniejszej części przedstawię czytlenikom kontrolery zasobów.

Kontrolery zasobów w Laravel


W pierwszej części szkolenia, p.t. Podstawy Routingu omówiłem najprostsze zasady tworzenia tras. Wstępnie zaprezentowałem możliwość przekierowania żądań do kontrolera zasobów, lecz omówienie tematu kontrolerów odłożyłem na kolejną część szkolenia. Nadszedł czas aby lepiej poznać zasady działania kontrolerów zasobów.

Przekazywanie żądań do wyspecjalizowanego kontrolera zasobów ma kilka ważnych zalet. Po pierwsze każdy utworzony w standardowy sposób kontroler zasobów Laravel umożliwia bezpośrednie odwoływanie się do bardzo potężnych metod, takich jak validate, dispatch, czy middleware, które będą omawiane w kolejnych częściach szkolenia. Po drugie, w przypadku rozbudowanych aplikacji, umieszczanie wszystkich metod w pliku routes/web.php to raczej mało efektywne podejście.

Kontrolery zasobów w praktyce


W poprzedniej części, w której zaprezentowałem modele przedstawiłem sposób tworzenia modeli za pomocą polecenia
php artisan make:model

W celach szkoleniowych wykasujmy teraz poprzednio utworzony model Post i stwórzmy go ponownie, z wiadomych powodów bez opcji –migration, ale tym razem z opcją --controller, z poziomu głównego katalogu naszej szkoleniowej aplikacji:

Tworzenie kontrolera zasobów
Tworzenie kontrolera zasobów

Świetnie! Mamy już nasz pierwszy kontroler zasobów. Kontrolery zasobów znajdują się w katalogu
app/Http/Controllers
Zobaczmy teraz co zawiera nasz kontroler o nadanej mu automatycznie nazwie PostController.php:

Przykładowy kontroler zasobów Laravel
Przykładowy kontroler zasobów Laravel

Następnie dodajmy do niego funkcję przekazującą pozyskane z bazy danych posty do widoku posts/index.blade.php:
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;

class PostController extends Controller
{

 public function index() {

   $posts = Post::all();

   return view('posts.index', compact('posts'));

   /**
    * Alternatywnie i z takim samym efektem
    *
    * return view('posts.index')->with('posts', $posts);
    *
    */

 }

}

?>

Ponieważ za chwilę objaśnię również metodę wyświetlającą treść poszczególnych postów, tak powinien teraz wyglądać nasz plik widoku listy postów resources/views/posts/index.blade.php:
<html lang="pl">

<head>

        <title>Szkoleniowe posty</title>

</head>

<body>
        <h1>Lista postów</h1>

        <ul>
                @foreach($posts as $post)

                        <li><a href="posts/{{ $post->id }}">{{ $post->title }}</a></li>

                @endforeach

        </ul>

</body>

</html>

Aby jednak lista tytułów postów mogła się prawidłowo wyświetlać za pomocą utworzonej funkcji kontrolera po przejściu na względny adres /posty, należy w pliku routes/web.php umieścić przekierowanie do funkcji index() kontrolera postów. Nasz plik routes/web.php powinien więc wyglądać następująco:
<?php

Route::get('/posty', 'PostController@index');

?>

Sprawdźmy teraz czy lista postów, z odnośnikami do treści poszczególnych postów, wyświetla się prawidłowo:

Szkoleniowy widok listy postów z odnośnikami do treści
Szkoleniowy widok listy postów z odnośnikami do treści

Świetnie! Wygląda na to, że wszystko działa, więc dodajmy możliwość wyświetlania treści poszczególnych postów w wyniku kliknięcia w odnośniki do treści.

Do naszego kontrolera PostController dodajmy funkcję o nazwie show(). Jako argument funkcji, w zmiennej $post przekazywany będzie obiekt klasy Post:
public function show(Post $post) {
        return view('posts.show')->with('post', $post);
   }

Do naszego pliku routes/web.php dodajmy trasę prowadzącą do metody show() kontrolera zasobów PostController:
Route::get('/posty/{post}', 'PostController@show');

Następnie stwórzmy widok resources/views/posts/show.blade.php:
<html lang="pl">

        <head>

                <title>Szkoleniowa treść posta</title>

        </head>

        <body>
                <h1>{{$post->title}}</h1>

                <hr>

                <p>{{ $post->body }}</p>

        </body>

</html>

Gotowe! Teraz po wejściu na względny adres /posty i kliknięciu w którykolwiek odnośnik do treści posta, w przeglądarce pojawia się treść wybranego posta, przykładowo:

Nasz szkoleniowy widok treści wybranego posta
Nasz szkoleniowy widok treści wybranego posta


Jak to działa


Laravel jest bardzo potężnym narzędziem programistycznym i wiele - nie tyle ciężkiej ile żmudnej pracy - potrafi wykonać za nas, pod warunkiem pisania kodu zgodnego z pewnymi regułami.

Aby funkcja show() kontrolera PostKontroler działała prawidłowo, należy zwrócić szczególną uwagę aby nazwa zmiennej parametru $post była zgodna z nazwą parametru {post} w funkcji pliku routes/web.php. Całą resztę skojarzeń wykonuje za nas Laravel!

Podsumowanie


W niniejszej części zobaczyliśmy podstawy działania kontrolerów zasobów oraz konkretny przykład przekazywania parametrów do kontrolera. Wiemy już jak pozyskiwać dane z tabeli bazodanowej i potrafimy przekazywać je z kontrolera zasobów do widoku. W kolejnej części pokażę jak zapisywać w tabeli bazy danych wprowadzone do formularza web informacje.

Serdecznie zapraszam do kolejnej części niniejszego szkolenia, p.t Zapis danych z formularza

wtorek, 28 listopada 2017

Laravel od podstaw: modele

W poprzednich częściach szkolenia omówiłem podstawowe sposoby korzystania z bazy danych w środowisku Laravel. W części pt. Laravel od podstaw: migracje pokazałem jak tworzy się tabele bazodanowe, natomiast w części pt. Laravel od podstaw: tabele bazodanowe i dynamiczne widoki zaprezentowałem metodę DB::table(), która pozwala wykonywać rozmaite zapytania SQL. W tej części szkolenia skupię się na Modelach, które umożliwiają korzystanie z bardziej efektywnych metod bazodanowych.

Modele w Laravel


W środowisku Laravel każda tabela bazy danych może mieć odpowiedni "Model", służący do interakcji z tą tabelą za pomocą metod klasy. Modele umożliwiają wykonywanie zapytań SQL na odpowiadających im tabelach w prosty i efektywny sposób. Każdy z modeli jest rozszerzeniem klasy bazodanowej Illuminate\Database\Eloquent\Model, co oznacza, że można w nim korzystać z udostępnianych przez tą klasę metod.

Załóżmy, że chcemy stworzyć stronę internetową, na której mamy zamiar wyświetlać posty użytkowników. Do tego będzie nam potrzebna tabela bazodanowa z postami oraz model, poprzez który będziemy się odnosić do naszej tabeli, zapisywać w niej dane oraz pozyskiwać znajdujące się w niej informacje. Za chwilę omówię pracę z modelami na kilku praktycznych przykładach. Zanim przejdziemy do praktyki, uprzejmie proszę czytelników, którzy śledzili poprzednie części szkolenia o usunięcie z bazy danych utworzonej tabeli o nazwie posts, jeśli oczywiście ją utworzyli.

Cofanie migracji


Aby przywrócić poprzednią wersje bazy danych, można użyć polecenia php artisan migrate:rollback. To polecenie wycofuje ostatnią "partię" migracji, która może zawierać wiele plików migracji.

Zobaczmy jak taka akcja powinna wyglądać w przypadku naszej szkoleniowej aplikacji:

Cofanie migracji
Cofanie migracji w Laravel

Aby definitywnie usunąć tabelę posts, należy teraz usunąć skrypt migracji odpowiedzialny za jej tworzenie, co spowoduje, że w następnej migracji tabela nie zostanie utworzona. W naszym przypadku zrobię to tak:
rm database/migrations/2017_11_25_195109_create_posts_table.php -fr

Modele i migracje


Tworzenie modelu odbywa się za pomocą polecenia
php artisan make:model
Wraz modelem można automatycznie utworzyć odpowiednią migrację, dodając parametr –migration, ale nie jest to koniecznie, gdyż można utworzyć odpowiednią migrację w osobnym kroku, korzystając z omówionego w jednej z poprzednich części szkolenia sposobu.

Zanim przejdziemy do praktyki i utworzymy nasz pierwszy model, wspomnę, że w przypadku tworzenia migracji wraz z tworzonym modelem, Laravel automatycznie tworzy tabele noszącą nazwę w liczbie mnogiej odnośnie do nazwy modelu, oczywiście w języku angielskim. Przykładowo, jeśli model to post, tabela będzie nosiła nazwę posts. Można jednak temu zapobiec i nadać własną nazwę tabeli, określając ją parametrem -–create=nazwa_tabeli w osobnym kroku tworzenia migracji za pomocą polecenia php artisan make:migration

Zobaczmy jak to wszystko wygląda w praktyce. Z wiersza poleceń i z poziomu katalogu naszej szkoleniowej aplikacji nauka, stwórzmy nasz pierwszy model o nazwie Post, wraz ze skryptem migracyjnym, który będzie odpowiedzialny na utworzenie tabeli bazodanowej:

Tworzenie modelu
Tworzenie modelu

Jak widać, model został pomyślnie utworzony. Został również utworzony skrypt migracyjny, który, jak wiadomo z poprzednich części szkolenia, został zapisany w katalogu database/migrations względem katalogu naszej aplikacji.

Zmodyfikujmy teraz skrypt migracyjny i dodajmy do niego linie umożliwiające utworzenie kolumn związanych z tytułem i ciałem postów, podobnie jak we wcześniejszej części szkolenia. Docelowo metoda up() naszego szkoleniowego skryptu migracyjnego powinna wyglądać następująco:
public function up()  {

    Schema::create('posts', function (Blueprint $table) {

        $table->increments('id');

        $table->timestamps();

        // Tytuł i ciało posta

        $table->string('title');

        $table->text('body');

      })

Po zmodyfikowaniu skryptu w wyżej udokumentowany sposób możemy przystąpić do wdrożenia nowej wersji bazy danych:


Świetnie! Tabela powiązana z modele Post została pomyślnie utworzona. Zobaczmy teraz jak wygląda nasz model, który znajduje się w pliku app/Post.php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    //
}

?>

Jak zapewne łatwo czytelnikom wywnioskować z powyższego kodu i o czym już wspomniałem wcześniej, klasa \App\Post jest rozszerzeniem Illuminate\Database\Eloquent\Model, co oznacza, że możemy się poprzez instancje obiektów tej klasy odwoływać do bazodanowych funkcji modelu Eloquenta, jednak ich działania będą skierowane do tabeli posts, ponieważ jest to tabela bazy danych powiązana z modelem Post.

Na początku może się to wydawać trudne do zrozumienia, ale kilka przykładów powinno wszystko wyjaśnić. Zanim posłużę się Modelami w skryptach php naszej szkoleniowej aplikacji, udokumentuję kilka prostych operacji bazodanowych, które wykonam z poziomu interfejsu Laravel php artisan tinker.

Od modelu do tabeli


W części pt. Laravel od podstaw: tabele bazodanowe i dynamiczne widoki zaprezentowałem metodę DB::table() oraz sposób wprowadzania nowych rekordów do tabeli. Wyglądało to tak:
DB::table('posts')->insert(['title'=>'Nasz pierwszy post', 'body'=>'Lorem ipsum.... blabablabla...']);
Natomiast pozyskiwanie rekordów z tabeli wyglądało tak:
DB::table('posts')->get();
Te same działania można wykonać odwołując się do metod modelu Eloquent poprzez klasę naszego modelu, w bardziej przejrzysty i skuteczny sposób. Skorzystam z powłoki php artisan tinker, aby na początek wprowadzić kilka przykładowych rekordów do tabeli, a następnie je pozyskać na różne sposoby:


Więcej przykładów:


Wiemy już wystarczająco wiele, aby nasza szkoleniowa funkcja w pliku routes/web.php zwracająca widok z tytułami postów wyglądała następująco:
Route::get('/posty', function() {

        /**
         *  Ten sposób został omówiony w poprzedniej części szkolenia
         *  $posts = DB::table('posts')->get();
        */

        // Tego nauczyliśmy się teraz - widoczny efekt jest taki sam
        $posts = \App\Post::all();

        return view('posts.index', compact('posts'));

});

W niniejszej części szkolenia dowiedzieliśmy się czym są modele oraz jaka jest relacja pomiędzy nimi, a tabelami bazy danych. Nauczyliśmy się odwoływać do tabeli bazy danych poprzez klasę modelu, korzystając z metod Eloquent'a. Zobaczyliśmy kilka praktycznych przykładów pracy z modelami w powłoce php artisan tinker oraz praktyczne zastosowanie modelu szkoleniowego Post w funkcji trasy. W kolejnej części szkolenia mam zamiar zaprezentować kontrolery zasobów oraz zastosować w funkcjach kontrolerów zasobów to czego nauczyliśmy się o modelach i nieco więcej.

Serdecznie zapraszam do kolejnej części niniejszego szkolenia, p.t. Kontrolery zasobów

niedziela, 26 listopada 2017

Laravel od podstaw: tabele bazodanowe i dynamiczne widoki

W poprzedniej części niniejszego szkolenia, pt. Migracje, objaśniłem metodę tworzenia tabeli bazy danych MySQL z poziomu środowiska Laravel. W tej części skupię się na metodach wprowadzania danych do tabeli oraz na sposobach ich odczytu i przekazywania do widoków.

Laravel udostępnia wiele sposobów wprowadzania danych do istniejących tabeli bazy danych. Aby początkowo objaśnić najprostszy z nich, uruchomię z głównego katalogu naszej szkoleniowej aplikacji interfejs php artisan tinker. Php artisan tinker jest rozwiązaniem typu repl (read-eval-print loop), umożliwiającym interaktywne działania z aplikacją Laravel.

Metoda DB::table


Objaśnię na początek, jak wprowadzać dane do tabeli i wykonywać na nich niektóre typowe operacje bazodanowe, korzystając z metody Laravel DB::table() z poziomu php artisan tinker, a potem omówię jeden z podstawowych sposobów przekazywania danych do widoków.

Najprostszym sposobem wykonywania operacji bazodanowych z poziomu środowiska Laravel to korzystanie z metody DB::table(). W kolejnych częściach szkolenia przedstawię bardziej zaawansowane i bardziej efektywne narzędzia bazodanowe, lecz wymaga to wcześniejszego zapoznania się z tematem Modeli.

Przedstawię sposób pracy z metodą DB::table()->insert(), która jest w przybliżeniu odpowiednikiem SQL 'INSERT INTO'. Zaprezentuję także metodę DB::table()->get, która służy do pozyskiwania wyników, oraz sposób filtrowania wyników za pomocą klauzuli where, odpowiadająca w przybliżeniu SQL'owemu WHERE.

Przechodząc z teorii do praktyki wpisuję i zatwierdzam polecenie
php artisan tinker
Poniższy kod przedstawia popularne zastosowania metody DB::table na naszej szkoleniowej tabeli. Operacje wykonywane są z poziomu interfejsu php artisan tinker, Warto z góry przeanalizować format w jakim dane są zwracane:
>>> DB::table('posts')->insert(['title'=>'Nasz pierwszy post', 'body'=>'Lorem ipsum.... blabablabla...']);
=> true
>>> DB::table('posts')->get();
=> Illuminate\Support\Collection {#741
     all: [
       {#743
         +"id": 5,
         +"title": "Nasz pierwszy post",
         +"body": "Lorem ipsum.... blabablabla...",
         +"created_at": null,
         +"updated_at": null,
       },
     ],
   }
>>> DB::table('posts')->insert(['title'=>'Nasz drugi post', 'body'=>'Kolejny tekst...']);
=> true
>>> DB::table('posts')->get();
=> Illuminate\Support\Collection {#747
     all: [
       {#736
         +"id": 5,
         +"title": "Nasz pierwszy post",
         +"body": "Lorem ipsum.... blabablabla...",
         +"created_at": null,
         +"updated_at": null,
       },
       {#742
         +"id": 6,
         +"title": "Nasz drugi post",
         +"body": "Kolejny tekst...",
         +"created_at": null,
         +"updated_at": null,
       },
     ],
   }
>>> DB::table('posts')->where('id', '>', 5)->get();
=> Illuminate\Support\Collection {#758
     all: [
       {#755
         +"id": 6,
         +"title": "Nasz drugi post",
         +"body": "Kolejny tekst...",
         +"created_at": null,
         +"updated_at": null,
       },
     ],
   }

Metoda DB::table() pozwala wykonywać cały szereg rozmaitych zapytań SQL. Więcej informacji na ten temat znajduje się w oficjalnej dokumentacji Laravel

Istotnym faktem jest format w jakim dane są zwracane z tabeli w efekcie zastosowania metody get(). Są one zwracane w postaci kolekcji informacji klasy Illuminate\Support\Collection. Ten format można docelowo zmienić, ale jest on w istocie bardzo wygodny i przydatny.

Dynamiczne widoki


Wiemy już z poprzednich części szkolenia jak tworzyć trasy i widoki. Dowiedzieliśmy się teraz jak pozyskiwać dane z tabeli bazy danych. Możemy teraz to wszysko połączyć razem aby uzyskać dynamiczne widoki.

Otwórzmy teraz plik routes/web.php w ulubionym edytorze i dodajmy do niego następującą zawartość:
Route::get('/posty', function() {

        $posts = DB::table('posts')->get();

        return $posts;

});

Po przejściu na adres względny /posty naszej aplikacji, zobaczymy w przeglądarce następującą treść:
[{"id":5,"title":"Nasz pierwszy post","body":"Lorem ipsum.... blabablabla...","created_at":null,"updated_at":null},
{"id":6,"title":"Nasz drugi post","body":"Kolejny tekst...","created_at":null,"updated_at":null}
]

Jak widać została nam zwrócona kolekcja wartości. Wiemy już dobrze w jakiej postaci są zwracane dane z tabeli, pozyskując je w wyżej opisany sposób. Świetnie! Teraz możemy posunąć się o krok dalej i zastosować poznane przed chwilą metody do pozyskania danych z naszej szkoleniowej tabeli, a następnie przekazać je do widoku.

Stwórzmy szkoleniowy widok w pliku
resources/views/posts/index.blade.php

Zawartość pliku widoku może być następująca:
<html lang="pl">

        <head>

                <title>Szkoleniowe posty</title>

        </head>

        <body>

                <ul>

                        @foreach($posts as $post)

                                <li>{{$post->title}}</li>

                        @endforeach

                </ul>

        </body>

</html>

Dostosujmy nasz plik routes/web.php w następujący sposób:
Route::get('/posty', function() {

        $posts = DB::table('posts')->get();

        return view('posts.index', compact('posts'));

});

Po zastosowaniu opisanych zmian, pod względnym adresem /posty widnieje teraz następująca dynamiczna treść:



W tej części przedstawiłem podstawowe metody pracy z tabelami danych w Laravel. Pokazałem jak wprowadzić proste dane do tabeli oraz jak je z niej odczytać. Wyjaśniłem również jak przekazać dane z tabeli do widoku. W kolejnej części mam zamiar omówić Modele, które udostępniają o wiele skuteczniejsze metody pracy z tabelami danych.

Serdecznie zapraszam do kolejnej części niniejszego szkolenia, p.t. Modele

Laravel od Podstaw: migracje

W poprzednich artykułach z serii Laravel od Podstaw objaśniłem tworzenie tras routingu oraz podstawy pracy z widokami i szablonami. Pokazałem na kilku przykładach w jak prosty, a zarazem efektywny sposób można przekazywać zmienne do widoków.

W niniejszej części szkoleniowej mam zamiar omówić tak zwane migracje. W następnych częściach szkolenia zapiszę i odczytam przykładowe informacje z tabeli bazy danych za pomocą narzędzi Laravel i zaprezentuję sposoby przekazywania danych z bazy danych do widoków. Gdy już wyjaśnię pojęcia związane z Modelami, pokażę jak pracować z danymi z poziomu klasy korzystając w metod Eloquent'a.

Laravel udostępnia sporą ilość sterowników do rozmaitych baz danych, a także daje możliwość pracy z własnymi sterownikami. Aby zapoznać się z obsługiwanymi sterownikami warto zajrzeć do pliku config/database.php


W celach szkoleniowych skupię się jednak jedynie na MySQL, choć nie będzie to miało żadnego wpływu na sposób pracy z danymi z poziomu aplikacji.

Baza danych, użytkownik i uprawnienia


Przed rozpoczęciem pracy z bazą danych MySQL należy utworzyć nową bazę danych, utworzyć użytkownika i nadać mu odpowiednie uprawnienia. Zakładam, że osoby zainteresowane nauką Laravel generalnie wiedzą jak to zrobić. Tym wszystkim, którzy jednak nie mają pojęcia jak się za to zabrać, ułatwię nieco sprawę i opiszę jak to wykonać z poziomu klienta MySQL.

Zakładając, że baza danych ma się nazywać nauka, nazwa użytkownika ma brzmieć bob, natomiast hasło to glasses-101, procedura może wyglądać przykładowo następująco:
MariaDB [(none)]> create database nauka;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> grant usage on *.* to 'bob'@'localhost' identified by 'glasses-101';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> grant all on nauka.*  to 'bob'@'localhost';
Query OK, 0 rows affected (0.00 sec)

Praca z bazą danych w Laravel


Plik znajdujący się w głównym katalogu aplikacji, noszący nazwę .env zawiera zbiór ważnych ustawień, a między innymi, ustawienia związane z dostępem do bazy danych z poziomu aplikacji Laravel.


Aby umożliwić dostęp do wcześniej utworzonej bazy danych z poziomu Laravel, ustawienia bazodanowe w pliku .env powinny wyglądać następująco:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nauka
DB_USERNAME=bob
DB_PASSWORD=glasses-101

W przypadku konieczności można oczywiście podać prawidłowy port oraz odpowiedni adres IP hosta.
Laravel - plik ustawień .env
Plik .env


Laravel 5.4 specified key was too long error


Uwaga! W przypadku Laravel 5.4, aby operacje bazodanowe działały prawidłowo, plik
app/Providers/AppServiceProvider.php
powinien zawierać wstępnie następującą treść:
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {

                Schema::defaultStringLength(191);

    }

    public function register()
    {
    }
}

Jeśli powyższe zmiany nie zostaną wprowadzone, jakakolwiek próba wykonania operacji na bazach danych spowoduje wyświetlenie następującego komunikatu o błędzie:
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table users add unique users_email_unique(email))

[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

PHP artisan


Do utworzenia tabeli MySQL posłużę się dedykowanymi narzędziami frameworka Laravel. Aby wygenerować skrypt tworzący tabelę bazy danych można skorzystać z php artisan. Czym jest php artisan? Otóż jest to specjalny zestaw poleceń, którym można się posługiwać w celu wykonania bardzo rozmaitych czynności. Aby wstępnie zapoznać się z funkcjami php artisan można wydać następujące polecenie z poziomu głównego katalogu aplikacji:
php artisan list
Powyższe polecenie wyświetli całą listę funkcji oferowanych przez interfejs php artisan.

Kilka słów o migracjach


W Laravel pod pojęciem migracji kryją się operacje bazodanowe, takie jak tworzenie i usuwanie tabeli, usuwanie istniejących i ponowne tworzenie czystych tabeli, przywracanie konkretnej wersji struktury bazy danych, czyli konkretnej wersji migracji.

Migracje są jak pewien rodzaj kontroli wersji bazy danych, dzięki czemu zespół programistów może łatwo modyfikować i udostępniać schemat bazy danych aplikacji. Migracje są zazwyczaj sparowane z narzędziem do tworzenia schematów Laravel, aby łatwo budować schemat bazy danych aplikacji.

Przed utworzeniem nowych tabeli należy wygenerować specjalny, służący do tego zadania skrypt migracyjny, który generowany jest wedle ustalonego schematu Laravel.

Więcej informacji o migracjach można znaleźć w oficjalnej dokumentacji Laravel.

Za każdym razem gdy wykonywane jest polecenie
php artisan migrate
Laravel uruchamia wszystkie skrypty migracyjne, które znajdują się w katalogu
database/migrations

Po świeżej instalacji Laravel w wersji 5.4 w katalogu tym powinny się znajdować 2 skrypty migracyjne:
2014_10_12_000000_create_users_table.php
2014_10_12_100000_create_password_resets_table.php
Skrypty te mają za zadanie utworzenie struktury tabel users i password_resets, związanych z uwierzytelnianiem. Uwierzytelnianie to jeden z tematów, które mam zamiar opisać w kolejnych częściach niniejszego tutorialu.

Tworzymy skrypt migracyjny


Jeśli wykonaliśmy już wszystkie wstępne czynności konfiguracyjne, które opisałem wcześniej i które są związane z umożliwieniem dostępu do bazy danych skryptom Laravel, możemy teraz wydać, z poziomu katalogu głównego naszej aplikacji, następujące polecenie, które ma za zadanie utworzyć skrypty migracyjne służące do wygenerowania tabeli o przykładowej nazwie 'posts':
php artisan make:migration create_posts_table
Zakładając, że wykonanie skryptu się powiodło, w katalogu skryptów migracyjnych, o którym pisałem wyżej, powinien widnieć nowy skrypt o nazwie podobnej do:
2017_11_25_195109_create_posts_table.php
Jeśłi otworzymy ten plik w naszym ulubionym edytorze, zobaczymy następującą treść:
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}
Osoby mające doświadczenie z SQL na pewno zrozumieją znaczenie tego kodu. Jednak nasza szkoleniowa tabela posts, która docelowo będzie zawierała posty, oprócz samego identyfikatora id i kolumn związanych z czasem utworzenia oraz aktualizacji wierszy, powinna posiadać dodatkowe kolumny, takie jak ciało (czyli treść) i tytuł. W tym celu należy zmodyfikować funkcję up(), czyli metodę tworzącą tabelę, w następujący sposób:
 public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
        });
    }
Warto tutaj oczywiście zapoznać się z funkcjami i możliwościami frameworka Laravel związanymi z określaniem typu kolumn

Uruchomienie migracji i utworzenie nowych tabel


Wydajmy teraz z poziomu głównego katalogu aplikacji polecenie, które ma za zadanie wykonanie istniejących skryptów migracyjnych:
php artisan migrate

Po uruchomieniu migracji powinny się wyświetlić informacje o pomyślnym wykonaniu skryptów:


Można teraz użyć klienta MySQL i sprawdzić czy struktura utworzonej tabeli jest zgodna z oczekiwaniami:


Dowiedzieliśmy się w tej części szkolenia jak dokonać wstępnych ustawień związanych z dostępem do serwera bazodanowego. Poznaliśmy pojęcie migracji w środowisku Laravel. Zapoznaliśmy się ze sposobem tworzenia skryptów migracyjnych oraz utworzyliśmy naszą pierwszą tabelę bazy danych za pomocą narzędzi Laravel. W kolejnym artykule omówię podstawowe operacje na utworzonej tabeli bazy danych z poziomu Laravel.

Serdecznie zapraszam do kolejnej części niniejszego szkolenia, p.t. Tabele bazodanowe i dynamiczne widoki

sobota, 25 listopada 2017

Laravel od podstaw: widoki i szablony

Znając już podstawy routingu w Laravel, możemy teraz przejść do pracy z widokami i uruchomić naszą pierwszą stronę internetową stworzoną w tym świetnym frameworku. Zrobimy to teraz wspólnie krok po kroku. Z poprzedniego artykułu wiemy już, że po dokonaniu świeżej instalacji frameworka mamy jeden gotowy widok przykładowy:
resources/views/welcome.blade.php
Mamy również wstępnie ustawioną regułę routingu, która jest powiązana z tym widokiem:
Route::get('/', function() {

        return view('welcome');

});
Znamy już podstawy działania routingu w Laravel i wiemy do czego służą powyższa reguła, wraz z powiązanym z nią widokiem.

Nasza pierwsza strona internetowa stworzona w Laravel


Utwórzmy teraz prosty, szkoleniowy plik HTML zawierające następujący kod:
<!doctype html>
<html lang="pl">

    <head>

        <title>Moje pierwsze widoki w Laravel</title>

    </head>

    <body>

        <p>Przykładowy paragraf treści</p>

    </body>

</html>
Następnie zapiszmy ten plik jako:
resources/views/mojastrona.blade.php
Po zapisaniu pliku przejdży do reguł routingu i dodajmy do pliku
routes/web.php
Następującą zawartość:
Route::get('/mojastrona', function() {

        return view('mojastrona');

});
Po przejściu na względny adres URL /mojastrona, oczywiście względem adresu naszej aplikacji, pojawia się widok HTML związany ze stroną, czyli nic ciekawego poza napisem:
"Przykładowy paragraf treści"
Świetnie! Wiemy już jak utworzyć widok i powiązać go z trasą routingu. Teraz zobaczmy jak proste jest dodanie do naszego widoku treści generowanej w PHP.

Laravel jest świetnym środowiskiem programistycznym i pozwala w bardzo przyjazny sposób tworzyć czysty i przejrzysty kod, oddzielając warstwę PHP od warstwy HTML. Do tego właśnie służą szablony z rozszerzeniem .blade.php.

Jak się posługiwać szablonami? Otóż zmienne można przekazywać do widoku na wiele sposobów. Zacznijmy od najprostszego z nich. Aby sprawdzić jak to się robi edytujmy naszą regułę routingu i dodajmy do niej wartość, którą mamy zamiar wyświetlić w powiązanym z nią widoku:
Route::get('/mojastrona', function() {

        return view('mojastrona')->with('tekst', 'Mój przykładowy paragraf');

});
Dostosujmy teraz nasz szkoleniowy widok, tak aby mogła się w nim prawidłowo wyświetlać przekazywana przez funkcje php wartość:
<!doctype html>

<html lang="pl">

    <head>

        <title>Moje pierwsze widoki w Laravel</title>

    </head>

    <body>

        <p>{{$tekst}}</p>

    </body>

</html>
Jeśli po zapisaniu powyższych zmian w plikach routingu i wodoku widzimy w przeglądarce tekst, który przekazaliśmy do widoku za pomocą funkcji PHP, oznacza to, że ten kolejny krok także się powiódł. Predstawię teraz kilka innych podstawowych sposobów przekazywania wartości do widoków w środowisku Laravel.

Oto kilka przykładów, których efekt jest dokładnie taki sam jak we wstępnie omówionym sposobie przekazywania zmiennej do widoku:
Route::get('/mojastrona', function() {

        return view('mojastrona', [

                'tekst' => 'Mój przykładowy paragraf'

                ]);

});

Route::get('/mojastrona', function() {

        $tekst = 'Mój przykładowy paragraf';

        return view('mojastrona', compact('tekst'));

});

Wiemy już jak przekazywać zmienne do widoku i w jaki sposób się do nich z widoku odwoływać. Zobaczmy teraz jak przekazywać do widoku kolekcje i w jaki sposób z nimi pracować z poziomu widoku. Oto jeden ze sposobów przekazywania kolekcji zmiennych do widoku:
Route::get('/mojastrona', function() {

        $lista = [

                'To jest pierwszy element',
                'To jest drugi element',
                'To jest trzeci element',

        ];

        return view('mojastrona', compact('lista'));

});
<!doctype html>

<html lang="pl">

    <head>

        <title>Moje pierwsze widoki w Laravel</title>

    </head>

    <body>

        <ul>

        @foreach ($lista as $element)

        <li>{{$element}}</li>

        @endforeach

        </ul>

    </body>


Efekt działania powyższego kodu w przeglądarce
Efekt działania powyższego kodu w przeglądarce

Świetnie! Wiemy już jak w podstawowy sposób posługiwać się widokami i przekazywać do nich zmienne. W kolejnych artykułach z tej serii posłużę się rozmaitymi przykładami z wartościami pozyskiwanymi z bazy danych, ale najpierw będzie konieczne omówienie podstaw pracy z bazami danych w środowisku Laravel. Zrobię to w kolejnym artykule.

Serdecznie zapraszam do kolejnej części niniejszego szkolenia, p.t. Migracje

piątek, 24 listopada 2017

Laravel od podstaw: podstawy routingu


Laravel to bardzo rozbudowany, a zarazem prosty w użyciu i przejrzysty framework PHP. Od dłuższego czasu jestem jego zwolennikiem, więc postanowiłem przedstawić ten framework swoim czytelnikom, poświęcając mu całą serię artykułów tematycznych. Mam nadzieję, że moje przedsięwzięcie okaże się przydatne, a pasjonaci języka PHP i opartych na nim frameworków będą mogli czerpać z niego wiele korzyści.



Laravel świetnie sobie radzi z tworzeniem witryn internetowych i wszelkiego rodzaju aplikacji webowych. Ponieważ routing, trasy i widoki to podstawowe elementy niemalże każdej współczesnej witryny web, sądzę że warto od nich rozpocząć tą prygodę.

Trasy i widoki w Laravel


Czym są routing, trasy i widoki? Otóż w Laravel pod pojęciem routingu kryje się zbiór reguł przypisujących dane funkcje lub widoki do tras. Trasa jest częścią adresu URL aplikacji web, a może służyć, między innymi, do prowadzenia użytkownika do konkretnego jej widoku, czyli do tego co wyświetlane jest w przeglądarce po przejściu do wybranego adresu URL. Trasa może także służyć do wywołania konkretnej akcji wewnętrznej, takiej jak przykładowo zapisanie do bazy danych informacji wprowadzonych do formularza przez użytkownika. Do podstawowego zarządzania trasami i odpowiadającymi im widokami służy plik, którego ścieżka, względem katalogu aplikacji, jest następująca:
routes/web.php
Co się powinno w tym pliku znajdować? Otóż plik ten powinien zawierać definicje tras routingu aplikacji i przypisanych im wartości zwrotnych lub funkcji. W pliku tym można określać akcje przypisane do różnego rodzaju żądań skierowanych do określonych adresów URL. Mogą to być przykładowo żądania typu GET i POST, ale nie tylko.

W przypadku świeżej instalacji frameworka Laravel, plik odpowiedzialny za routing w katalogu nowej aplikacji zawiera następujący wpis:
Route::get('/', function () { return view('welcome'); });
Powyższy wpis oznacza tyle, że po wejściu na główną stronę witryny powinien pojawić się widok o nazwie 'welcome', który jest w tym przypadku oparty o szablon .blade, znajdujący się w głównym katalogu widoków. Szablony typu .blade są bardzo potężnym narzędziem frameworka Laravel, więc omówię je dogłębnie w jednym z kolejnych artykułów.

Świeża instalacja Laravel: domyślny widok powitania
Świeża instalacja Laravel: domyślny widok powitania

Glówna ścieżka, pod którą umieszczane są pliki widoków aplikacji to:
resources/views
Przytoczę kilka podstawowych przykładów routingu w Laravel. Po przetestowaniu i zrozumieniu poniższych przykładów, zachęcam czytelników do zagłębienia tematu korzystając z oficjalnej dokumentacji frameworka Laravel

Proste przykłady reguł routingu w Laravel


Efektem poniższego wpisu, jest wyświetlenie się napisu 'Witamy!' po przejściu na względny adres URL /, czyli na główną stronę serwisu web. W odpowiedzi na żądanie HTTP typu GET z adresem strony głównej aplikacji:
Route::get('/', function () {
  return 'Witamy!';
});

Poniższy wpis routingu powoduje wyświetlenie się napisu 'Witamy' w odpowiedzi na każdego rodzaju żądanie HTTP z adresem strony głównej aplikacji web:
Route::any('/', function () {
  return 'Co tu robić?';
});

Definiując reguły routingu możemy również przypisać wewnętrzną nazwę określanej trasy, do której można się w ten sposób odwoływać z poziomu skryptów php, przykładowo:
Route::get('/', function () {
  return 'Witamy!';
})->name('home');

Poniższy przykład powoduje wyświetlenie się nazwy użytkownika w odpowiedzi na żądanie HTTP GET pod adresem względnym /panel/{login} W tym przypadku parametr URL o nazwie login przyjmuje dowolny ciąg znaków:
Route::get('/panel/{login}', function ($login) {
  return 'Witamy użytkownika '.$login;
});

Poniższy wpis przypisuje do względnego adresu URL '/posty' naszej aplikacji i żądania HTTP typu GET metodę index() kontrolera zasobów PostController oraz ustawia nazwę wewnętrzną dla tej reguły. Kontrolery zasobów frameworka Laravel omówię bardziej szczegółowo w jednym z kolejnych artykułów niniejszej serii:
Route::get('/posts','PostController@index')->name('home');

Aby wyświetlić aktualną listę routingu, można wydać następujące polecenie z głównego katalogu aplikacji
php artisan route:list

Przykładowy efekt polecenia php artisan route:list
Przykładowy efekt polecenia php artisan route:list


Co dalej?


Przedstawiłem tutaj kilka podstaw, które okażą się niezbędne do zrozumienia kolejnych tematów. Do routingu, tras i widoków będę nieustannie powracał w kolejnych artykułach z tej serii, poszerzając zakres pojęć o kolejne elementy.

Serdecznie zapraszam do kolejnej części niniejszego szkolenia, p.t. Widoki i Szablony