ChatGPT i PHP – wykorzystaj moc AI na swoją korzyść

phphub.pl 1 rok temu

ChatGPT to ostatnio niezwykle gorący temat w świecie technologii. Wszyscy zadrżeli na myśl o tym, iż AI niedługo może pozbawić ich pracy. Co interesujące narzędzie to może być również wykorzystywane przez programistów.

Przyjrzyjmy się zatem w jaki sposób możemy wykorzystać ChatGPT, programując w naszym ulubionym języku z dolarami przy nazwach zmiennych (tak, chodzi o PHP ( ͡° ͜ʖ ͡°)).

Najpierw wyjaśnijmy sobie tylko kilka rzeczy:

Czym jest ChatGPT?

ChatGPT to produkt firmy OpenAI. Jest to narzędzie typu chatbot bazujące na algorytmie uczenia maszynowego (GPT – ang. Generative Pre-Trained Transformer).

Zasada działania tego narzędzia jest prosta. Zadajesz pytanie – dostajesz odpowiedź. Nie dostajesz jednak listy linków, tak jak ma to miejsce w wyszukiwarce Google. Dostajesz pełną, całkowicie spójną odpowiedź.

Jak zacząć używać ChatGPT?

Tutaj sprawa jest bajecznie prosta. Musisz wejść w następujący link i założyć sobie konto w OpenAI. Przy rejestracji jest wymagane również podanie numeru telefonu i autoryzacja przy pomocy otrzymanego kodu SMS. Następnie logujesz się do narzędzia pod tym linkiem. Po wykonaniu tych kroków możesz zacząć używać ChatGPT. Po zalogowaniu powinieneś zobaczyć następujący ekran:

Z AI możesz komunikować się używając okna czatu widocznego na obrazku powyżej.

ChatGPT bez problemu jest w stanie zrozumieć język polski. Wystarczy, iż napiszesz do niego coś w danym języku:

Czyż nie jest uroczy? (✿╹◡╹)

Jak programista PHP może użyć ChatGPT w codziennej pracy?

Poniżej przedstawiam kilka pomysłów na to, w jaki sposób możesz skorzystać z ChatGPT w swojej codziennej pracy developerskiej. W tym miejscu chciałbym serdecznie podziękować Wojciechowi Łaskawcowi za podesłanie mi kilku use case’ów tego, w jaki sposób ChatGPT może być wykorzystany przez PHP-owca.


1. Code review dla kodu PHP

Zapytałem ChatGPT, czy mogłoby zrobić dla mnie code review.

Ja: Czy jesteś w stanie zrobić dla mnie code review kodu w PHP?
AI: Niestety, jako iż jestem dużym modelem językowym wytrenowanym przez OpenAI, nie jestem w stanie przeprowadzić code review kodu w PHP ani w żadnym innym języku. Jestem programem stworzonym do generowania tekstu na podstawie otrzymywanych danych wejściowych, więc nie posiadam zdolności ani narzędzi do analizowania kodu. jeżeli potrzebujesz pomocy z code review kodu w PHP, możesz skontaktować się z profesjonalistą lub poszukać odpowiednich narzędzi i tutoriali online

Bardzo skromne to AI. Nie zniechęcony jednak tym faktem poszedłem krok dalej. Otóż pokazałem AI następujący, niezbyt ładny, kod kontrolera w Laravelu. Czemu akurat kod w Laravelu? Powiedzmy, iż akurat taki wygrzebałem ze śmietnika… ( ͡° ͜ʖ ͡°)

<?php namespace MyApp\Http\Controllers; use Statamic\View\View; use Statamic\Facades\Term; use Illuminate\Http\RedirectResponse; class ProductController extends Controller { /** * Shows the specified resource. * * @param mixed $slug * @return View */ public function show(mixed $slug): View { // Get the term for product. $product = Term::query()->find("product::$slug"); return (new View)->layout('layout') ->template('product-layout') ->with($product->toAugmentedArray()); } /** * Redirects to the specified resource. * * @param mixed $slug * @return RedirectResponse */ public function redirect(mixed $slug): RedirectResponse { // Get the term for product. $product = Term::query()->find("product::$slug"); return redirect()->to($product->permalink); } }

Ja: przeprowadź dla mnie code review następującego kodu w PHP: <tutaj wkleiłem kod>
AI: Podczas przeprowadzania code review dla powyższego kodu w PHP, zwróciłbym uwagę na następujące kwestie:

  1. W metodzie show() zmienna $product jest typu mixed, ale na podstawie kontekstu wydaje się, iż powinna być typu Term. Zalecałbym zmianę typu zmiennej na Term, aby uniknąć potencjalnych błędów i ułatwić czytelność kodu.
  2. W obu metodach show() i redirect() kod jest podobny i w obu przypadkach wyszukiwana jest kategoria o określonym slugu. Zalecałbym stworzenie osobnej metody, która będzie wyszukiwać kategorię, aby uniknąć powielania kodu i ułatwić utrzymanie i rozwój kodu.
  3. W metodzie show() zmienna $product jest rozszerzana dzięki metody toAugmentedArray(), ale nie wiadomo, co ta metoda robi i jakie dane zwraca. Zalecałbym dodanie komentarza dokumentacyjnego do tej metody, aby wyjaśnić jej działanie i pokazać, jakie dane są zwracane.
  4. W metodzie redirect() zmienna $product jest używana do uzyskania permalinku, ale nie wiadomo, czy ta zmienna zawsze zawiera permalink. Zalecałbym sprawdzenie, czy zmienna $product zawiera permalink i dodanie odpowiedniego komunikatu błędu lub obsługi wyjątku, jeżeli permalink nie jest dostępny.

Podsumowując, powyższy kod w PHP wymaga pewnych poprawek i usprawnień, aby zapewnić jego poprawne działanie i ułatwić utrzymanie.

Całkiem nieźle co? Osobiście w ramach code review zwróciłbym uwagę na jeszcze kilka rzeczy, ale wygląda to naprawdę imponująco. Czy to już koniec ery pull requestów, które od tygodni leżą odłogiem w oczekiwaniu na code review? ( ͡° ͜ʖ ͡°)

2. Implementacja kodu PHP

No to idźmy dalej. Czy ChatGPT będzie w stanie przygotować dla nas jakąś prostą implementację w PHP? Sprawdźmy!

Załóżmy, iż chcemy sobie zaimplementować komendę konsolową w Symfony, której zadaniem będzie pobranie czegoś z GoogleMaps API.

Ja: Pokaż mi przykład implementacji komendy konsolowej w Symfony, której zadaniem będzie pobranie czegoś z GoogleMaps API.
AI: Poniżej znajduje się przykładowa implementacja komendy konsolowej w Symfony, której zadaniem jest pobranie danych z GoogleMaps API:

use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class GetGoogleMapsDataCommand extends Command { protected function configure() { // ustawiamy nazwę i opis komendy $this ->setName('app:get-google-maps-data') ->setDescription('Pobiera dane z Google Maps API.'); } protected function execute(InputInterface $input, OutputInterface $output) { // pobieramy dane z API $data = $this->getDataFromGoogleMaps(); // wyświetlamy dane w konsoli $output->writeln($data); } private function getDataFromGoogleMaps() { // tutaj powinien znajdować się kod do pobrania danych z Google Maps API // np. przy użyciu biblioteki Guzzle do wysyłania zapytań HTTP } }

Komenda ta może być uruchomiona z linii poleceń w następujący sposób:

php bin/console app:get-google-maps-data

Oczywiście powyższy przykład jest jedynie ilustracją i może wymagać dalszego dostosowania do konkretnych potrzeb.

Ja: okej, a teraz pokaż przykład zapytania do GoogleMaps API przy użyciu biblioteki Guzzle
AI: Poniżej znajduje się przykładowy kod, w którym zostaje wysłane zapytanie do GoogleMaps API dzięki biblioteki Guzzle:

use GuzzleHttp\Client; $client = new Client(); $response = $client->get('https://maps.googleapis.com/maps/api/place/findplacefromtext/json', [ 'query' => [ 'input' => 'Pizza near New York', 'inputtype' => 'textquery', 'fields' => 'formatted_address,name,rating', 'key' => 'YOUR_API_KEY', ], ]); $data = json_decode($response->getBody(), true);

W powyższym przykładzie wysyłamy zapytanie do metody findplacefromtext w API GoogleMaps, w którym szukamy pizzerii w pobliżu Nowego Jorku. W odpowiedzi otrzymujemy dane w formacie JSON, które następnie są dekodowane i zapisywane w zmiennej $data.

Oczywiście, aby skorzystać z tego kodu, należy zastąpić wartość YOUR_API_KEY w linii 14 swoim własnym kluczem API z GoogleMaps.

Szału nie ma, ale powiedzmy, iż cośtam bylibyśmy w stanie z tego posklejać. ( ͡° ͜ʖ ͡°)

3. Testy automatyczne w PHP

No i tutaj mamy prawdziwą petardę. Okazuje się, iż ChatGPT może dla nas napisać choćby testy automatyczne. Pamiętasz implementację Laravelowego ProductControllera, z pierwszego przykładu? Użyłem sobie tej implementacji i poprosiłem AI, aby napisało dla mnie testy jednostkowe.

Ja: Dla następującej implementacji, napisz dla mnie testy jednostkowe: <tutaj wkleiłem kod>
AI: Poniżej znajdują się przykładowe testy jednostkowe dla powyższej implementacji:

namespace Tests\Unit\Http\Controllers; use MyApp\Http\Controllers\ProductController; use Statamic\Facades\Term; use Tests\TestCase; class ProductControllerTest extends TestCase { public function testShowMethod() { // Stworzenie przykładowego produktu $product = Term::make('product')->slug('test-product'); $product->save(); // Utworzenie mocka dla Term $termMock = $this->createMock(Term::class); $termMock->expects($this->once()) ->method('find') ->with('product::test-product') ->willReturn($product); // Zarejestrowanie mocka w containerze app()->instance(Term::class, $termMock); // Wywołanie metody show() $controller = new ProductController(); $response = $controller->show('test-product'); // Asercje sprawdzające odpowiedź $this->assertInstanceOf(View::class, $response); $this->assertEquals('layout', $response->layout()); $this->assertEquals('product-layout', $response->template()); $this->assertEquals($product->toAugmentedArray(), $response->viewData()); } public function testRedirectMethod() { // Stworzenie przykładowego produktu $product = Term::make('product')->slug('test-product')->permalink('http://my-app.test/products/test-product'); $product->save(); // Utworzenie mocka dla Term $termMock = $this->createMock(Term::class); $termMock->expects($this->once()) ->method('find') ->with('product::test-product') ->willReturn($product); // Zarejestrowanie mocka w containerze app()->instance(Term::class, $termMock); // Wywołanie metody redirect() $controller = new ProductController(); $response = $controller->redirect('test-product'); // Asercje sprawdzające odpowiedź $this->assertInstanceOf(RedirectResponse::class, $response); $this->assertEquals('http://my-app.test/products/test-product', $response->getTargetUrl()); } }

Powyższe testy sprawdzają, czy metoda show zwraca obiekt View z odpowiednimi danymi oraz czy metoda redirect zwraca obiekt RedirectResponse z odpowiednim adresem URL. Testy te są jedynie przykładem i mogą

A teraz patrz na to, testy integracyjne z użyciem traitów udostępnionych przez Laravela!


Ja: napisz testy integracyjne dla kodu PHP w Laravelu: <tutaj wkleiłem kod>
AI: Poniżej przedstawiam przykładowe testy integracyjne dla kodu PHP w Laravelu:

use MyApp\Http\Controllers\ProductController; use Statamic\Facades\Term; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseTransactions; class ProductControllerTest extends TestCase { use DatabaseMigrations; use WithoutMiddleware; /** @test */ public function it_can_show_the_specified_product() { $slug = 'test-product'; // Create a test product. Term::make('product')->slug($slug)->save(); // Create a request. $request = Request::create("/product/$slug", 'GET'); // Create a controller instance. $controller = new ProductController(); // Invoke the controller action. $response = $controller->show($request, $slug); // Assert the response is an instance of View. $this->assertInstanceOf(View::class, $response); // Assert the response has the correct layout. $this->assertEquals('layout', $response->layout); // Assert the response has the correct template. $this->assertEquals('product-layout', $response->template); // Assert the response has the correct data. $this->assertArraySubset($product->toAugmentedArray(), $response->getData()); } /** @test */ public function it_can_redirect_to_the_specified_product() { $slug = 'test-product'; // Create a test product. $product = Term::make('product')->slug($slug)->save(); // Create a request. $request = Request::create("/product/$slug/redirect", 'GET'); // Create a controller instance. $controller = new ProductController(); // Invoke the controller action. $response = $controller->redirect($request, $slug); // Assert the response is an instance of RedirectResponse. $this->assertInstanceOf(RedirectResponse::class, $response); // Assert the response has the correct target URL. $this->assertEquals($product->permalink, $response->getTargetUrl()); } }

Testy funkcjonalne? Dla ChatGPT to żaden problem!

Ja: napisz testy funkcjonalne dla tej samej implementacji
AI: Poniżej przedstawiam przykładowe testy funkcjonalne dla tej samej implementacji:

use MyApp\Http\Controllers\ProductController; use Statamic\Facades\Term; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; class ProductControllerFunctionalTest extends TestCase { /** @test */ public function it_can_show_the_specified_product() { $slug = 'test-product'; // Create a test product. Term::make('product')->slug($slug)->save(); // Send a request to the show action. $response = $this->get("/product/$slug"); // Assert the response has the correct status code. $this->assertEquals(200, $response->getStatusCode()); // Assert the response has the correct view. $this->assertViewHas('layout', 'layout'); $this->assertViewHas('template', 'product-layout'); // Assert the response has the correct data. $this->assertViewHas('product', function ($product) use ($slug) { return $product->slug == $slug; }); } /** @test */ public function it_can_redirect_to_the_specified_product() { $slug = 'test-product'; // Create a test product. $product = Term::make('product')->slug($slug)->save(); // Send a request to the redirect action. $response = $this->get("/product/$slug/redirect"); // Assert the response is a redirect. $this->assertTrue($response->isRedirection()); // Follow the redirect. $response = $this->followRedirects($response); // Assert the response has the correct target URL. $this->assertEquals($product->permalink, $response->getTargetUrl()); } }

Jako rozwiązanie na zasadzie kopiuj-wklej – super sprawa! Trochę refactoru, może otestowanie jakichś ciekawych przypadków brzegowych i gotowe!

4. Dokumentacja w języku ojczystym zawsze pod ręką

Męczy cię ciągłe googlowanie i przeszukiwanie dokumentacji? ChatGPT jest zatem idealnym rozwiązaniem dla Ciebie!

Poprosiłem, aby ChatGPT wyjaśnił mi czym są Security Votery w Symfony.

Ja: wyjaśnij mi czym jest security voter w symfony
AI: Security voter w symfony jest mechanizmem, który pozwala na zdefiniowanie reguł dostępu do różnych zasobów w aplikacji opartej na frameworku symfony. Security voter umożliwia sprawdzenie, czy dana osoba (np. użytkownik) posiada odpowiednie uprawnienia do dostępu do danego zasobu, a jeżeli nie posiada tych uprawnień, może zostać zablokowany dostęp do tego zasobu.
Ja: okej, a teraz pokaż mi przykład implementacji
AI: Niestety, jako asystent OpenAI nie posiadam dostępu do przeglądarek internetowych, więc nie jestem w stanie pokazać Ci konkretnego przykładu implementacji mechanizmu Security Voter w Symfony. Mogę jednak opisać ogólny sposób tworzenia voterów w tym frameworku.

Aby utworzyć voter w Symfony, należy utworzyć klasę, która implementuje interfejs Symfony\Component\Security\Core\Authorization\Voter\VoterInterface. Klasa ta musi zawierać metodę vote(), która jest odpowiedzialna za określenie, czy dana osoba ma dostęp do danego zasobu. W jej implementacji należy zdefiniować odpowiednie reguły decyzyjne i zwrócić jedną z trzech wartości: VoterInterface::ACCESS_GRANTED – jeżeli dostęp jest dozwolony, VoterInterface::ACCESS_DENIED – jeżeli dostęp jest zabroniony, lub VoterInterface::ACCESS_ABSTAIN – jeżeli voter nie ma wiedzy, czy dostęp powinien być dozwolony, czy zabroniony.

Następnie należy zarejestrować utworzony voter w systemie zabezpieczeń Symfony poprzez dodanie go do listy voterów w pliku konfiguracyjnym. Po tym kroku voter będzie mógł być użyty do oceny dostępu do zasobów w aplikacji.

Przykładowa implementacja votera może wyglądać następująco:

namespace App\Security\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\User\UserInterface; class ExampleVoter extends Voter { protected function supports($attribute, $subject) { // voter obsługuje tylko atrybut "VIEW" return $attribute === 'VIEW'; } protected function voteOnAttribute($attribute, $subject, TokenInterface $token) { $user = $token->getUser(); // jeżeli użytkownik nie jest zalogowany, zwróć abstynencję if (!$user instanceof UserInterface) { return self::ACCESS_ABSTAIN; } // jeżeli użytk

Niestety z nieznanych mi powodów, AI ucięło ten przykład. Być może mamy tutaj do czynienia z jakimś narzuconym limitem na długość wiadomości.

Mimo wszystko komentarz „jeśli użytkownik nie jest zalogowany, zwróć abstynencję” jest niezwykle zabawny. Bardzo chciałbym zobaczyć kiedyś podobny komentarz w kodzie. ( ͡° ͜ʖ ͡°)

Podsumowanie

Mam nadzieję, iż podobały Ci się przykłady ChatGPT, które przedstawiłem w tym poście. To niesamowita technologia, która na pewno zrewolucjonizuje wiele branż i zawodów!

Czy jako programiści mamy się czego obawiać? Czy już niedługo AI nas zastąpi? Osobiście byłbym daleki od takiego stwierdzenia. Mimo wszystko dostaliśmy do rąk interesujące narzędzie, które może znacząco usprawnić naszą codzienną pracę. Narzędzie niepozbawione wad, bo zdarzają się błędy i łatwo wpaść w limity. No i koniec końców to tylko AI, technologia wciąż na tyle niedoskonała i niebędąca w stanie całkowicie zastąpić człowieka. Niemniej jednak rezultaty są bardzo imponujące i świetnie rokują na przyszłość.

Znasz jeszcze jakieś interesujące wykorzystania ChatGPT w kontekście pracy PHP developera? A może masz jakieś przemyślenia na ten temat? Daj znać w komentarzu!

Idź do oryginalnego materiału