GRAPHQL I PHP

GraphQL predstavlja posebno pripremljen jezik upita namijenjen za optimizirano slanje upita i dobivanje rezultata između klijenata i servera preko HTTP protokola. Za razvoj GraphQL-a “krivac” je Facebook koji prve implementacije jezika koristi u vlastitim mobilnim aplikacijama još od 2012 godine. Od 2015. godine tehnologija postaje javno dostupna svim zainteresiranim stranama, tako da se sve intenzivnije koristi u praksi i izvan okvira samog Facebooka.

Korištenje tehnologije GraphQL moguće je implementirati u različitim razvojnim alatima.  U ovom tekstu ograničit ćemo se na primjer korištenja u programskom jeziku PHP, a kao izvor podataka koristit će se baza podataka MySQL.

PRIPREMA RAČUNALA

Pod pretpostavkom da na računalu već imate pravilno instaliranu i konfiguriranu bazu podataka MySQL i programski jezik PHP, za pisanje primjera u GraphQL-u potrebno je instalirati još nekoliko dodatnih modula. Naravno, i odgovarajuću MySQL bazu podataka kako bi se na njoj mogli izvoditi primjeri. Iako se testiranje primjera može izvoditi na različite načine, pretpostavit ćemo da u radu (kao većina korisnika) koristite preglednik Chrome te da ćete testiranje izvoditi upravo u njemu. U tom slučaju, prvo u Chrome treba instalirati odgovarajući dodatak ChromeiQL. Izravna web-adresa na kojoj je dostupan navedeni dodatak je:

https://chrome.google.com/webstore/detail/chromeiql/fkkiamalmpiidkljmicmjfbieiclmeij.

U slučaju da iz bilo kojeg razloga prethodnu vezu ne uspijete pravilno upisati/kopirati, možete upotrijebiti alternativni pristup – u trgovini dodataka za Chrome jednostavno napravite pretraživanje modula ChromeiQL. Provjera uspjeha instalacije dodatka je vrlo jednostavna. U gornjem desnom uglu preglednika treba se pojaviti novi gumb za njegovo pokretanje (označen je na pratećoj slici u nastavku).

Za implementaciju GraphQL upita u PHP jeziku koristit ćemo javno dostupnu biblioteku graphql-php, a nju možete pronaći na web-adresi:

https://github.com/webonyx/graphql-php

Biblioteku možete preuzeti klikom na gumb Clone or download ili korištenjem posebnog alata Composer, namijenjenog jednostavnijem preuzimanju sličnih dodataka u vlastite PHP projekte. U drugom slučaju treba koristiti naredbu:

composer require webonyx/graphql-php.

Slika 1. Dodatak ChromeiQL instaliran u preglednik Chrome

 

Opis demo baza podataka korištenih za demonstraciju GraphQL upita nastalih zajedničkim radom dvojice autora (Patrick Crews i Giuseppe Maxia) dostupan je na web‑adresi https://dev.mysql.com/doc/employee/en/employees-introduction.html.

Sama baza podataka u obliku spremnom za preuzimanje na vlastito računalo nalazi na adresi: https://github.com/datacharmer/test_db.

Slika 2. Pregled osnovnih tablica u demo bazi podataka

 

Po svojoj internoj strukturi baza je zapravo prilično jednostavna (sastoji se od svega šest tablica i dva pogleda), ali zato sadrži popriličan broj slogova u tablicama – ukupno oko 4 000 000 slogova. Sasvim dovoljan broj za korištenje u različitim primjerima poput optimizacije upita na bazu podataka i slično.

PRIMJER KORIŠTENJA U PHP-u

Prije prelaska na glavni dio primjera, zbog njegove cjelovitosti, navedimo sadržaj konfiguracijske datoteke config.php zadužene za nadzor pristupa bazi podataka:

<?php

       $con = mysql_connect('localhost','root','') or die(mysql_error());          

       if (!$con) {

             echo "Unable to connect to DB: " . mysql_error();

             exit;

       }       

       if (!mysql_select_db("employees")) {

             echo "Unable to select mydbname: " . mysql_error();

             exit;

       }

       mysql_query("SET NAMES 'utf8'");

       mysql_query("COLLATE 'utf8_general_ci'");

?>

 

Po potrebi u prethodnoj datoteci izmijenite podatke o serveru, bazi i korisniku podacima s vlastitog računala.

Glavna datoteka sa samim programskim kodom primjera implementacije GraphQL jezika (datoteka graphql.php) sastoji se od nekoliko različitih dijelova. Izvođenje primjera pokreće se upisom sljedeće naredbe u prozoru za upis naredbi (“Naredbeni redak”):

php -S localhost:8080 ./graphql.php.

Preostalo je još samo da se u pregledniku Chrome, proširenom dodatkom ChromeiQL, pokrene taj dodatak te isproba primjer navođenjem odgovarajuće adrese u okviru Set endpoint:

http://localhost:8080

<?php

/* Dio 1 – uključivanje svih potrebnih modula */

require_once __DIR__ . './autoload.php';

require_once __DIR__ . "./_config.php";

 

use GraphQL\Type\Definition\ObjectType;

use GraphQL\Type\Definition\Type;

use GraphQL\Type\Schema;

use GraphQL\GraphQL;

 

try {

    /* Dio 2 – postavljanje upita koji vraća rezultate */

    $queryType = new ObjectType([

        'name' => 'Query',

        'fields' => [

            'echo' => [

                'type' => Type::string(),

                'args' => [

                    'emp_no' => ['type' => Type::string()],

                ],

                'resolve' => function ($root, $args) {

                    $query = "select s.salary, s.from_date, s.to_date, e.first_name,

e.last_name

                                  from salaries s

                                  inner join employees e on s.emp_no = e.emp_no

                             where s.emp_no = '" . $args['emp_no'] . "'

  order by s.from_date desc limit 1";

                    $result = mysql_query($query);

                    while($rec = mysql_fetch_array($result)) {

                           $salary = $rec['salary'];

                           $period = $rec['from_date'] . ' - ' . $rec['to_date'];

                           $employee = $rec['first_name'] . ' ' . $rec['last_name'];

                    }

                    return $root['prefix'] . $salary . ' (' . $period . ') ' . $employee;

                }

            ],

        ],

    ]);

 

    /* Dio 3 – izvođenje mutacije */

    $mutationType = new ObjectType([

        'name' => 'Calc',

        'fields' => [

            'add' => [

                'type' => Type::string(),

                'args' => [

                    'emp' => ['type' => Type::string()],

                   'from' => ['type' => Type::string()],

                   'to' => ['type' => Type::string()],

                     'salary' => ['type' => Type::int()],

                ],

                'resolve' => function ($root, $args) {

                    $query = "insert into salaries (emp_no, salary, from_date, to_date)

                           values ('" . $args['emp'] . "'," . $args['salary'] . ",'" .

                           $args['from'] . "','" . $args['to'] . "')";

                    $result = mysql_query($query);

                           if ($result == 1)

                                  return "Added salary for " . $args['emp'];

                           else

                                  return "Error adding salary";

                },

            ],

        ],

    ]);

 

    $schema = new Schema([

        'query' => $queryType,

        'mutation' => $mutationType,

    ]);

 

    $rawInput = file_get_contents('php://input');

    $input = json_decode($rawInput, true);

    $query = $input['query'];

    $variableValues = isset($input['variables']) ? $input['variables'] : null;

 

    $rootValue = ['prefix' => 'Last salary: '];

    $result = GraphQL::executeQuery($schema, $query, $rootValue, null, $variableValues);

    $output = $result->toArray();

 

    /* Dio 4 – obrada grešaka */

} catch (\Exception $e) {

    $output = [

        'error' => [

            'message' => $e->getMessage()

        ]

    ];

}

 

/* Dio 5 – prikaz rezultata izvođenja */

header('Content-Type: application/json; charset=UTF-8');

echo json_encode($output);

 

U prvom dijelu, na samom početku datoteke izvodi se uključivanje svih potrebnih modula u programski kod. To je mjesto na kojem vlastiti PHP kod povezujemo s implemetacijom GraphQL jezika u programskom jeziku PHP – ranije spomenuta biblioteka graphql-php.

Drugi dio datoteke demonstrira implemetaciju GraphQL upita koji vraća podatke iz MySQL baze podataka. U konkretnom slučaju je to iznos zadnje plaće za zadanu šifru zaposlenika. Evo primjera GraphQL upita zadanog u pregledniku Chrome uz pomoć dodatka ChromeiQL:

query {

       echo(emp_no:"10001")

}

 

Kao rezultat njegovog izvođenja dobije se:

{

“data“: {

       “echo“: “Last salary: 88958 (2002-06-22 – 9999-01-01) Georgi Facello“

}

 

Osim čitanja postojećih podataka, GraphQL može se upotrijebiti i za dodavanje, izmjenu ili brisanje podataka u bazi podataka. U terminologiji GraphQL-a takav oblik naredbe naziva se “mutacija”.

Slika 3. Primjer izvođenja GraphQL upita u pregledniku Chrome

 

Evo primjera mutacije koja djelatniku sa šifrom 10001 dodaje novi iznos ukupne plaće za zadani period:

mutation {

add(emp: "10001", salary: 55555, from: "2017-01-01", to: "2018-01-01")

}

 

Nakon uspješnog dodavanja novog podatka u bazu, mutacija vraća poruku o uspjehu vlastitog izvođenja:

{

“data“: {

       “add“: “Added salary for 10001“

}

 

Primijetite i da je u slučaju upita i u slučaju mutacije potrebno definirati sve dozvoljene argumente koje je potrebno poznavati za pravilno zadavanje upita. U prvom slučaju to je samo jedan parametar, emp_no, a u drugom slučaju četiri parametra:  emp, salary, from i to.

 

Četvrti dio PHP datoteke zadužen je za obradu eventualnih pogrešaka nastalih prilikom izvođenja GraphQL upita. U praksi može biti bitno složeniji u odnosu na trenutačni primjer (kao uostalom i ostali dijelovi – na primjer, formatiranje datuma). Ne treba zaboraviti da greške prilikom izvođenja (posebno mutacija) mogu nastati i zato što sama MySQL baza ne dozvoljava njihovo izvođenje.

 

Na primjer, pretpostavimo da u tablici za zapis vrijednosti plaća definiramo UNIQUE indeks na stupcima za zapis šifre radnika te početnog i/ili završnog datuma na koji se odnosi vrijednost plaće. U tom slučaju ponovno izvođenje iste mutacije iz prethodnog primjera nije dozvoljeno, pa bi primjer vratio opis greške nastale prilikom izvođenja mutacije:

{

“data“: {

       “add“: “Error adding salary“

}

 

Slika 4. Primjer izvođenja mutacije u pregledniku Chrome

 

ZAKLJUČAK

Jezik upita GraphQL predstavlja vrlo korisnu i danas široko rasprostranjenu tehnologiju za postavljanje različitih vrsta optimiziranih upita preko HTTP protokola. Osim implementacije u PHP jeziku, demonstrirane u ovom tekstu, uz pomoć odgovarajućih javno dostupnih biblioteka postoji mogućnost njegovog korištenja u većini najpopularnijih programskih jezika. Zato o njemu treba razmišljati kao o vrlo upotrebljivoj alternativi za druge tehnologije slične namjene.

 

Dodatne informacije o korištenju GraphQL jezika možete saznati na seminaru autora teksta koji bi se trebao održati u rujnu 2018. u prostorijama Srca.