Kodėl PHP vis dar gyvas ir net klesti?
Jei paklaustumėte bet kurio „senior” kūrėjo prieš dešimt metų, ar PHP išliks populiari kalba, daugelis būtų linktelėję abejodami. Kalba turėjo reputacijos problemų – chaotiškas funkcijų pavadinimų sumaišas, nekonzistentiška sintaksė, saugumo spragos, kurias buvo lengva padaryti. Tačiau PHP neišnyko. Ji evoliucionavo. Ir šiandien PHP 8.x versija yra visiškai kitoks žvėris nei tas, kurį daugelis prisimena iš 2005-ųjų.
PHP šiuo metu maitina apie 77% visų svetainių, kurių serverio technologiją galima nustatyti. Tai apima WordPress, Drupal, Joomla ir daugybę kitų sistemų. Bet tai ne tik „legacy” kodas – aktyviai kuriamos naujos aplikacijos, startuoliai renkasi PHP, ir didžioji dalis to yra dėl vieno dalyko: Laravel framework’o.
Laravel pakeitė tai, kaip žmonės žiūri į PHP. Jis pavertė kalbą, kuri buvo laikoma „antraeile”, į rimtą įrankį, su kuriuo galima statyti enterprise lygio sistemas, API, realaus laiko aplikacijas ir dar daugiau. Šiame straipsnyje išnagrinėsime tiek PHP kaip kalbą, tiek Laravel kaip ekosistemą – nuo pagrindų iki praktinių dalykų, kurie tikrai praverčia kasdieniame darbe.
PHP 8.x – kas pasikeitė ir kodėl tai svarbu
PHP 8.0 buvo tikras lūžio taškas. Jis atnešė JIT (Just-In-Time) kompiliatorių, kuris teoriškai turėjo padidinti našumą iki 3x. Praktikoje web aplikacijoms skirtumas ne toks dramatiškas (dauguma laiko praleidžiama laukiant duomenų bazės ar I/O operacijų), bet skaičiavimų intensyvioms užduotims – reikšmingas.
Bet svarbiau nei JIT – sintaksiniai patobulinimai, kurie padarė PHP rašymą malonesnį:
- Named arguments – galite perduoti argumentus pagal pavadinimą, ne tik pagal poziciją
- Match expressions – kaip switch, bet griežtesnis ir grąžina reikšmę
- Nullsafe operator (?->) – nebereikia rašyti daugybės if/null patikrinimų
- Union types – funkcija gali priimti kelis tipus
- Constructor property promotion – klasių kūrimas tapo žymiai kompaktiškesnis
PHP 8.1 pridėjo Enums (pagaliau!), Fibers asinchroniniam programavimui ir readonly properties. PHP 8.2 ir 8.3 tęsė šią trajektoriją su readonly klasėmis, geresniais tipų patikrinimais ir našumo pagerinimais.
Praktinis patarimas: jei dar rašote PHP 7.x kodą, rimtai pagalvokite apie migraciją. PHP 7.4 jau nebegauna saugumo atnaujinimų. Migracija į 8.x dažniausiai nėra tokia skausminga, kaip atrodo – rector/rector įrankis gali automatizuoti didelę dalį konversijų.
Štai kaip atrodo modernaus PHP kodas su constructor promotion ir named arguments:
class User {
public function __construct(
public readonly string $name,
public readonly string $email,
public readonly UserRole $role = UserRole::Viewer,
) {}
}
$user = new User(
name: 'Jonas Jonaitis',
email: '[email protected]',
role: UserRole::Admin,
);
Tai jau atrodo kaip rimta, tipizuota kalba – ne tas „laukinių vakarų” PHP, kurį daugelis prisimena.
Laravel pagrindai – architektūra, kurią verta suprasti
Laravel sukūrė Taylor Otwell 2011 metais kaip alternatyvą CodeIgniter framework’ui, kuris tuo metu dominavo PHP pasaulyje. Idėja buvo paprasta: sukurti framework’ą, kuris būtų malonus naudoti, turėtų aiškią struktūrą ir leistų kūrėjams koncentruotis į logiką, o ne infrastruktūrą.
Laravel remiasi keliais pagrindiniais principais:
MVC architektūra (Model-View-Controller) yra pagrindas, bet Laravel ją išplečia. Jūs turite Models (Eloquent ORM), Views (Blade templating engine) ir Controllers, bet taip pat yra Middleware, Service Providers, Facades, Jobs, Events, Listeners ir dar daugiau. Iš pradžių tai gali atrodyti per daug, bet kiekvienas komponentas turi aiškią paskirtį.
Service Container yra Laravel širdis. Tai dependency injection konteineris, kuris automatiškai „surenka” klases ir jų priklausomybes. Jums nereikia rankiniu būdu kurti objektų – tiesiog deklaruojate, ko jums reikia, ir Laravel tai pateikia:
class OrderController extends Controller {
public function __construct(
private OrderService $orderService,
private PaymentGateway $paymentGateway,
) {}
public function store(CreateOrderRequest $request): JsonResponse {
$order = $this->orderService->create($request->validated());
return response()->json($order, 201);
}
}
Service Providers yra vieta, kur registruojate viską į Service Container. Kiekvienas paketas, kurį instaliuojate per Composer, dažniausiai turi savo Service Provider, kuris automatiškai užregistruoja reikalingus komponentus.
Praktinis patarimas naujiems Laravel kūrėjams: nesistenkite iš karto suprasti visų konceptų. Pradėkite nuo Routes → Controllers → Models grandinės. Kai tai taps natūralu, eikite prie Middleware, tada prie Events/Jobs. Bandymas suprasti viską iš karto – greičiausias kelias į frustracijos pragarą.
Eloquent ORM – duomenų bazė be SQL galvos skausmo
Eloquent yra viena iš priežasčių, kodėl žmonės įsimyli Laravel. Tai Active Record implementacija, kuri leidžia dirbti su duomenų baze naudojant PHP objektus, o ne rašyti raw SQL užklausas.
Paprasta Eloquent užklausa atrodo taip:
// Visi aktyvūs vartotojai, surūšiuoti pagal vardą
$users = User::where('active', true)
->orderBy('name')
->get();
// Vartotojas su jo užsakymais ir produktais
$user = User::with(['orders.products'])
->findOrFail($id);
// Sukurti naują įrašą
$post = Post::create([
'title' => 'Mano pirmas straipsnis',
'content' => $content,
'user_id' => auth()->id(),
]);
Bet Eloquent gali daug daugiau nei paprasti CRUD veiksmai. Relationships sistema leidžia aprašyti ryšius tarp modelių:
class User extends Model {
public function orders(): HasMany {
return $this->hasMany(Order::class);
}
public function roles(): BelongsToMany {
return $this->belongsToMany(Role::class)
->withTimestamps()
->withPivot('granted_by');
}
}
Viena iš dažniausių klaidų, kurią daro pradedantieji su Eloquent – N+1 problema. Tai atsitinka, kai cikle kiekvienam įrašui darote atskirą duomenų bazės užklausą:
// BLOGAI – N+1 problema
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name; // Kiekvienam postui – atskira užklausa!
}
// GERAI – Eager loading
$posts = Post::with('author')->get();
foreach ($posts as $post) {
echo $post->author->name; // Tik 2 užklausos iš viso
}
Laravel Telescope arba Debugbar įrankiai padeda aptikti tokias problemas – matote tiksliai, kiek užklausų vykdoma ir kiek laiko jos užima. Rekomenduoju juos naudoti development aplinkoje nuo pat pradžių.
Kitas svarbus Eloquent aspektas – Scopes. Tai leidžia pakartotinai naudoti užklausų logiką:
class Post extends Model {
public function scopePublished(Builder $query): Builder {
return $query->where('published_at', '<=', now())
->whereNotNull('published_at');
}
public function scopeByCategory(Builder $query, string $category): Builder {
return $query->whereHas('categories', fn($q) =>
$q->where('slug', $category)
);
}
}
// Naudojimas
$posts = Post::published()->byCategory('technologijos')->latest()->paginate(15);
Artisan, Queues ir kiti Laravel įrankiai, kurie taupo laiką
Laravel ekosistema yra plati, ir vienas iš jos privalumų – įrankiai, kurie tikrai naudojami kasdieniame darbe, o ne tik egzistuoja dokumentacijoje.
Artisan yra Laravel komandų eilutės įrankis. Su juo galite generuoti kodus, vykdyti migracijas, paleisti testus ir dar daugiau:
# Sukurti naują Controller
php artisan make:controller ProductController --resource
# Sukurti Model su Migration, Factory ir Seeder
php artisan make:model Product -mfs
# Vykdyti migracijas
php artisan migrate
# Paleisti interaktyvią PHP konsolę su Laravel kontekstu
php artisan tinker
Tinker yra ypač naudingas – tai REPL aplinka, kurioje galite testuoti Eloquent užklausas, kurti objektus, tikrinti logikos fragmentus be reikalo rašyti testų ar kurti laikinų kontrolerių.
Queue sistema yra vienas iš tų dalykų, kuris iš karto pagerina aplikacijos jautimą. Vietoj to, kad vartotojas lauktų, kol išsiunčiamas el. laiškas ar apdorojamas failas, galite „nustumti” šią užduotį į eilę ir atlikti ją fone:
// Job klasė
class SendWelcomeEmail implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(private User $user) {}
public function handle(Mailer $mailer): void {
$mailer->to($this->user)->send(new WelcomeEmail($this->user));
}
}
// Dispatch'inimas iš kontrolerio
SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(5));
Queue’ams galite naudoti Redis, Amazon SQS, duomenų bazę ar net paprastą sync driver’į (testams). Horizon – Laravel paketas Queue monitoringui – suteikia gražią dashboard’ą, kurioje matote, kas vyksta su jūsų eilėmis realiu laiku.
Laravel Scheduler leidžia apibrėžti periodines užduotis tiesiogiai kode, vietoj to, kad konfigūruotumėte daugybę cron įrašų:
// app/Console/Kernel.php
protected function schedule(Schedule $schedule): void {
$schedule->command('reports:generate')->dailyAt('06:00');
$schedule->job(new CleanupOldFiles)->weekly()->onSunday();
$schedule->call(function () {
DB::table('sessions')->where('last_activity', '<', now()->subDays(7))->delete();
})->daily();
}
Serverio pusėje reikia tik vieno cron įrašo: * * * * * php /path/to/artisan schedule:run. Visa kita valdoma kode.
Saugumas Laravel aplikacijose – ką žinoti iš karto
PHP turėjo blogą saugumo reputaciją, ir ji nebuvo visiškai neužtarnautą. SQL injection, XSS, CSRF – visa tai buvo realios problemos, kurias lengva padaryti. Laravel daug ką išsprendžia automatiškai, bet svarbu suprasti, kaip.
SQL Injection – Eloquent ir Query Builder automatiškai naudoja prepared statements. Jei naudojate Eloquent arba DB::table()->where(), jūs esate apsaugoti. Pavojus atsiranda, kai naudojate raw SQL su vartotojo įvestimi:
// PAVOJINGA
$users = DB::select("SELECT * FROM users WHERE name = '$name'");
// SAUGU
$users = DB::select("SELECT * FROM users WHERE name = ?", [$name]);
// ARBA TIESIOG NAUDOKITE ELOQUENT
$users = User::where('name', $name)->get();
CSRF apsauga – Laravel automatiškai generuoja CSRF token’ą kiekvienai sesijai ir tikrina jį POST/PUT/DELETE užklausose. Blade šablonuose tiesiog pridėkite @csrf direktyvą formose.
Mass Assignment – tai dažna klaida, kai leidžiate vartotojams tiesiogiai perrašyti modelio laukus. Laravel apsaugo nuo to per $fillable arba $guarded savybes:
class User extends Model {
// Tik šie laukai gali būti mass-assigned
protected $fillable = ['name', 'email', 'password'];
// ARBA nurodyti, kurie laukai NEGALI būti mass-assigned
protected $guarded = ['id', 'is_admin', 'role'];
}
Authentication ir Authorization – Laravel turi Gates ir Policies sistemą, kuri leidžia aiškiai apibrėžti, kas ką gali daryti:
// Policy
class PostPolicy {
public function update(User $user, Post $post): bool {
return $user->id === $post->user_id || $user->isAdmin();
}
}
// Kontroleryje
public function update(Request $request, Post $post): Response {
$this->authorize('update', $post);
// Jei vartotojas neturi teisių – automatiškai 403
$post->update($request->validated());
return response()->noContent();
}
Papildomas patarimas: visada naudokite Form Requests validacijai. Tai ne tik saugiau, bet ir palaiko kontrolerius švariais. Form Request klasė atlieka ir validaciją, ir autorizacijos patikrinimą prieš pasiekiant kontrolerio metodą.
Testavimas Laravel – kodėl tai ne tik „gera praktika”
Daugelis kūrėjų žino, kad reikia rašyti testus, bet nedaro to, nes „nėra laiko” arba „projektas per mažas”. Tiesą sakant, Laravel testų rašymą padarė pakankamai paprastą, kad ši pasiteisinimų serija nebetiktų.
Laravel naudoja PHPUnit pagrindu, bet prideda savo abstrakcijos sluoksnį, kuris labai supaprastina HTTP testus:
class PostApiTest extends TestCase {
use RefreshDatabase;
public function test_authenticated_user_can_create_post(): void {
$user = User::factory()->create();
$response = $this->actingAs($user)
->postJson('/api/posts', [
'title' => 'Test Post',
'content' => 'Some content here',
]);
$response->assertCreated()
->assertJsonPath('title', 'Test Post');
$this->assertDatabaseHas('posts', [
'title' => 'Test Post',
'user_id' => $user->id,
]);
}
public function test_guest_cannot_create_post(): void {
$this->postJson('/api/posts', ['title' => 'Test'])
->assertUnauthorized();
}
}
Factories yra neatsiejama testavimo dalis – jos leidžia greitai generuoti test duomenis:
// Sukurti 10 postų su autoriumi
Post::factory()
->count(10)
->for(User::factory()->create())
->published()
->create();
Laravel taip pat turi Pest integracijos palaikymą – tai modernesnė, ekspresyvesnė testavimo framework’as, kuris daugeliui atrodo malonesnė alternatyva PHPUnit sintaksei:
it('allows admin to delete any post', function () {
$admin = User::factory()->admin()->create();
$post = Post::factory()->create();
actingAs($admin)
->deleteJson("/api/posts/{$post->id}")
->assertNoContent();
expect(Post::find($post->id))->toBeNull();
});
Praktinis patarimas: pradėkite nuo Feature testų (HTTP lygio), ne Unit testų. Feature testai tikrina realius scenarijus ir suteikia daugiau pasitikėjimo, kad sistema veikia kaip tikimasi. Unit testus rašykite kompleksiai logikai – skaičiavimams, algoritmams, business rules.
Nuo „Hello World” iki produkcijos – ką tikrai reikia žinoti
Teorija yra gera, bet Laravel ekosistema yra tokia plati, kad lengva pasiklysti. Štai keletas praktinių dalykų, kurie padeda perkelti projektą į realų pasaulį.
Laravel Sail – Docker aplinka, kuri leidžia paleisti Laravel projektą be jokio lokalaus PHP, MySQL ar Redis diegimo. Viena komanda ./vendor/bin/sail up – ir turite veikiančią aplinką. Tai ypač naudinga komandose, kur skirtingi žmonės naudoja skirtingas operacines sistemas.
Caching – Laravel turi universalią caching sąsają, kuri veikia su Redis, Memcached, failų sistema ar net duomenų baze. Tinkamas caching gali dramatiškai pagerinti aplikacijos greitį:
// Cache'uoti brangią operaciją 60 minučių
$popularPosts = Cache::remember('popular_posts', 3600, function () {
return Post::withCount('views')
->orderByDesc('views_count')
->limit(10)
->get();
});
// Cache'uoti su tags (reikia Redis)
Cache::tags(['posts', 'homepage'])->put('featured', $posts, 3600);
// Išvalyti visą posts tag'ą
Cache::tags('posts')->flush();
Laravel Octane – jei jums reikia maksimalaus našumo, Octane paleidžia aplikaciją su Swoole arba RoadRunner serveriu, kas eliminuoja PHP bootstrap’o laiką kiekvienai užklausai. Tai gali padidinti throughput’ą kelis kartus.
Deployment – Laravel Forge yra mokamas serverio valdymo įrankis, kuris supaprastina deployment’ą. Alternatyviai, Laravel Vapor leidžia deploy’inti į AWS Lambda (serverless). Jei norite pilnos kontrolės, Envoyer suteikia zero-downtime deployment’ą.
Keli dalykai, kuriuos verta žinoti prieš einant į produkciją:
- Visada naudokite
php artisan config:cacheirphp artisan route:cacheprodukcijoje .envfailas neturi patekti į versijų kontrolę – naudokite.env.examplekaip šabloną- Nustatykite
APP_DEBUG=falseprodukcijoje – kitaip vartotojai gali matyti stack traces su jautriais duomenimis - Konfigūruokite proper logging – Laravel palaiko Slack notifikacijas, kai atsiranda kritinės klaidos
- Naudokite database transactions ten, kur reikia atominio operacijų atlikimo
Laravel ekosistema taip pat apima Livewire – tai leidžia kurti reaktyvias UI komponentes be JavaScript rašymo. Ir Inertia.js – tiltas tarp Laravel backend’o ir Vue/React frontend’o, kuris eliminuoja poreikį kurti atskirą API. Šie įrankiai leidžia full-stack PHP kūrėjams kurti modernias aplikacijas neprarandant produktyvumo.
PHP ir Laravel kartu sudaro ekosistemą, kuri nėra „seksualiausia” technologijų pasaulyje – niekas nesukuria YouTube video apie tai, kaip jie „atrado” PHP. Bet ji veikia. Ji yra brandi, turi milžinišką bendruomenę, daugybę paketų, gerą dokumentaciją ir – svarbiausia – leidžia kurti realias sistemas realiu greičiu. Kartais tai yra svarbiau nei naudoti naujausią, madingausią stack’ą. Jei dar nedirbote su Laravel, pradėkite nuo oficialios dokumentacijos ir Laracasts platformos – tai geriausi resursai, kuriuos rasite. Ir neišsigąskite dydžio – framework’as auga kartu su jūsų supratimu.






