PHP je out?

PHP je u posljednje vrijeme pod poprilično velikim “anti-marketingom”. Imamo naše drage prijatelje iz MS-a i njihova backend rješenja, mnoštvo novih database servis provajdera (kao Firebase) kojima je također u interesu da zgrabe dio PHP kolača. A imamo i framework/PSR ekipicu koja sa svojim nepotrebno kompliciranim standardima samo plaši/tjera JS developere od PHP-a. U biti, vi možete pisati PHP i bez OOP, “funkcionalno” kao JS i sve ovo gore vas netreba zamarati, jer biste kao freelancer trebali više učiti kako koristiti tuđa rješenja a ne zamarati se sa standardima.

Realnost je da su PHP aplikacije ~70% interneta. WordPress broji oko 400 milijuna instalacija. Znači, slobodno se uhvatite WP-a (koji se btw, već koristi u mnoštvu državnih institucija i agencija). WordPress je, kada ga upoznate iznutra, jako zanimljivo osmišljena tehnologija. U biti, sve što morate znati oko PHP-a je: sigurnost, PDO/SQL, REST komunikacija i kako to sve ugraditi u WP. A ako i trebate nešto kompliciranije (web api), imate Composer. S Composer-om možete instalirati, dbal, fastroutes, di container, twig, validator… ili što vam već treba. PHP nije prastara tehnologija (poput MS Windows 😊) i PHP može sve što i node.js pa i ponešto više.

Nečemo bespotrebno komplicirati, pa ćemo koristiti samo dvije skripte, bez OOP, libsa…

Mail funkcija

Za PHP nam je naravno potreban server. Php već dolazi sa built-in development serverom ali problem je što mail funkcija ne radi. Webhosting više nije skup kao nekada. Stoga je najbolje uzeti pretplatu na neki od popularnijih pružatelja hosting usluga.

Kada šaljemo podatke na server, šaljemo ih tako da u prvom dijelu šaljemo zaglavlje (header) u kojem je opisan tip sadržaja, njegova veličina i zatim sadržaj.

Podatke šaljemo u dva osnovna tipa: POST i GET. GET je uobičajeni mod u kojem internet preglednik čita stranice, znači, uzmi podatke sa poslužitelja i učitaj u preglednik. Postoje i drugi zahtjevi koji su u biti pod-vrste POST zahtjeva, ali to sad nije bitno.

POST s druge strane šalje podatke iz preglednika na poslužitelj. Naprimjer forme i datoteke.

POST zahtjev mora imati nekakvu endpoint datoteku ili rutu. Endpoint će obraditi zahtjev i odrediti odgovor zahtjeva. Tako ćemo odrediti da će nam odgovor biti u JSON formatu.

header('Content-type:application/json;charset=utf-8');

Ako zahtjev nije tipa POST, odgovori sa kodom 405. Naravno možemo odgovoriti i sa kodom 404.

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['forbidden'=> "Method Not Allowed"]);  
    http_response_code(405);
    die();
}

Što znači da poslužitelj ne podržava tip zahtjeva. Nakon što smo provjerili zahtjev, provjeravamo $_POST i $_FILES varijable.

Te smo varijable postavili ranije (JS dio) sa append metodom u FormData objektu:

    postData.append('ds_pdf_file[]', pdfInput[i]);
    postData.append("ds_form_data", JSON.stringify(formValues));

Znači ako postoje, nastavi, ako ne, odgovori sa kodom 404 ili nečim sličnim.

if (isset($_FILES['ds_pdf_file']) && isset($_POST['ds_form_data'])) 
{...}

Nadalje, da bismo provjerili sadržaj zahtjeva, dump-amo varijable sa error_log(print_r(‘hello’,true)) funkcijama. Tako jednostavno možemo vidjeti ispis zahtjeva u terminalu ili log datoteki. Bitno je naglasiti da ako pošaljemo ispis sa echo u browser, dobijamo JSON grešku. To se događa zato što smo postavili tip JSON u header-u POST odgovora zahtjeva. Također je potrebno pripaziti na whitespace i ostale stvari koje ne prolaze JSON standard.

    error_log(print_r($_FILES['ds_pdf_file'], true));
    error_log(print_r(json_decode($_POST['ds_form_data']), true));

‘ds_form_data’ smo ranije u JS dijelu pretvorili u JSON pa ćemo podatke prebaciti u asocijativni niz (associative array) sa json_decode funkcijom.

$formData = json_decode($_POST['ds_form_data']);

Podatke ‘filtriramo’ prije nego što ih koristimo.

$ime = filter_var($formData->ime, FILTER_SANITIZE_STRING);
$prezime = filter_var($formData->prezime, FILTER_SANITIZE_STRING);
$nazivUlice = filter_var($formData->nazivUlice, FILTER_SANITIZE_STRING);
$kucanskiBroj = filter_var($formData->kucanskiBroj, FILTER_SANITIZE_STRING);
$mjesto = filter_var($formData->mjesto, FILTER_SANITIZE_STRING);
$postanskiBroj = filter_var($formData->postanskiBroj, FILTER_SANITIZE_STRING);
$mobitel = filter_var($formData->mobitel, FILTER_SANITIZE_STRING);
$email = filter_var($formData->email, FILTER_SANITIZE_STRING);
$datumRodenja = filter_var($formData->datumRodenja, FILTER_SANITIZE_STRING);
$spol = filter_var($formData->spol, FILTER_SANITIZE_STRING);
$vozacka = filter_var($formData->vozacka, FILTER_SANITIZE_STRING);
$ip = $_SERVER['REMOTE_ADDR'];

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) 
{
  echo json_encode(['fail'=>  json_encode("Email is invalid.")]);  
  die(); 
}

Slažemo $htmlMessage varijablu koju ćemo koristiti kao sadržaj email poruke.

$htmlMessage = '<h1> CV Prijava </h1>';    
$htmlMessage .= 'Ime: <b>' . $ime . '</b><br>';
$htmlMessage .= 'Prezime: <b>' . $prezime . '</b><br>';
$htmlMessage .= 'Datum rođenja: <b>' . $datumRodenja . '</b><br>';
$htmlMessage .= 'Spol: <b>' . $spol . '</b><br>';
$htmlMessage .= 'Ulica: <b>' . $nazivUlice .' '. $kucanskiBroj .'</b><br>';
$htmlMessage .= 'Mjesto: <b>' . $postanskiBroj .', '. $mjesto .'</b><br>';
$htmlMessage .= 'Mobitel: <b>' . $mobitel .'</b><br>';
$htmlMessage .= 'Email: <b>' . $email .'</b><br>';
$htmlMessage .= 'Vozačka: <b>' . $vozacka .'</b><br>';
$htmlMessage .= 'Adresa zahtjeva: <b>' . $ip . '</b><br>';

Pravimo email attachment name.

$pdfFileName = date("Ymd_Hi") .'_'. $ime .'_'. $prezime .'_'. $datumRodenja . '.pdf';
$pdfFileName = str_replace(' ', '_', $pdfFileName);

sendAttachment funkcija

Funkcija radi slično kao http response. Slaže header sa opisom i veličinom, dodaje html i privitak te na kraju zove built-in ‘mail’ funkciju. Bitno je napomenuti da je potrebno imati email ‘From’ i ‘Reply-to’ vrijednosti unesene i da je to email adresa od našeg web-hostinga. Skripta je testirana i radi na gmail-u.

Cijela skripta:

<?php

require_once __DIR__ . "/sendAttachment.php";

header('Content-type:application/json;charset=utf-8');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['forbidden'=> "Method Not Allowed"]);  
    http_response_code(405);
    die();
}

if (isset($_FILES['ds_pdf_file']) && isset($_POST['ds_form_data']))
{

    error_log(print_r($_FILES['ds_pdf_file'], true));
    error_log(print_r(json_decode($_POST['ds_form_data']), true));
    
    
    
    $formData = json_decode($_POST['ds_form_data']);
    
    $ime = filter_var($formData->ime, FILTER_SANITIZE_STRING);
    $prezime = filter_var($formData->prezime, FILTER_SANITIZE_STRING);
    $nazivUlice = filter_var($formData->nazivUlice, FILTER_SANITIZE_STRING);
    $kucanskiBroj = filter_var($formData->kucanskiBroj, FILTER_SANITIZE_STRING);
    $mjesto = filter_var($formData->mjesto, FILTER_SANITIZE_STRING);
    $postanskiBroj = filter_var($formData->postanskiBroj, FILTER_SANITIZE_STRING);
    $mobitel = filter_var($formData->mobitel, FILTER_SANITIZE_STRING);
    $email = filter_var($formData->email, FILTER_SANITIZE_STRING);
    $datumRodenja = filter_var($formData->datumRodenja, FILTER_SANITIZE_STRING);
    $spol = filter_var($formData->spol, FILTER_SANITIZE_STRING);
    $vozacka = filter_var($formData->vozacka, FILTER_SANITIZE_STRING);
    $ip = $_SERVER['REMOTE_ADDR'];
    
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) 
    {
        echo json_encode(['fail'=>  json_encode("Email is invalid.")]);  
        die(); 
    }
    
    $htmlMessage = '<h1> CV Prijava </h1>';    
    $htmlMessage .= 'Ime: <b>' . $ime . '</b><br>';
    $htmlMessage .= 'Prezime: <b>' . $prezime . '</b><br>';
    $htmlMessage .= 'Datum rođenja: <b>' . $datumRodenja . '</b><br>';
    $htmlMessage .= 'Spol: <b>' . $spol . '</b><br>';
    $htmlMessage .= 'Ulica: <b>' . $nazivUlice .' '. $kucanskiBroj .'</b><br>';
    $htmlMessage .= 'Mjesto: <b>' . $postanskiBroj .', '. $mjesto .'</b><br>';
    $htmlMessage .= 'Mobitel: <b>' . $mobitel .'</b><br>';
    $htmlMessage .= 'Email: <b>' . $email .'</b><br>';
    $htmlMessage .= 'Vozačka: <b>' . $vozacka .'</b><br>';
    $htmlMessage .= 'Adresa zahtjeva: <b>' . $ip . '</b><br>';
    
    error_log($htmlMessage);          
        
    $pdfFileName = date("Ymd_Hi") .'_'. $ime .'_'. $prezime .'_'. $datumRodenja . '.pdf';
    $pdfFileName = str_replace(' ', '_', $pdfFileName);
    
    $eMessage = '';
    $sendSuccessful = 0;

    $sendSuccessful = sendAttachment('report.fake.mail@gmail.com', 'developer@ioox.studio', 'CV Forma', $htmlMessage, $pdfFileName, $_FILES['ds_pdf_file']['tmp_name'][0], $eMessage);
   
    
    if ($sendSuccessful)
    {
        echo json_encode(['success'=> json_encode($eMessage)]);  
        die();
    }
    else
    {
        echo json_encode(['fail'=> json_encode($eMessage)]);  
        die();         
    }
}

http_response_code(404); 
die(); 

Html/Css dio.
Javascript dio.