PHP 8 förväntas släppas i december 2020 och kommer att ge oss många kraftfulla funktioner och positiva språkförbättringar.

Många RFC (Request for comments) har redan godkänts och implementerats, så det är dags för oss att dyka in i några av de mest spännande tilläggen som borde göra PHP snabbare och mer tillförlitligt.

Eftersom PHP 8 fortfarande är under utveckling kan det komma flera förändringar innan den slutliga utgåvan i december. Vi kommer att hålla koll på dessa ändringar och uppdatera det här inlägget regelbundet, så se till att du inte missar något om PHP 8 och kolla det här inlägget igen då och då.

Så, vilka funktioner och förbättringar bör vi förvänta oss från PHP 8? Vad är den största nyheten med PHP 8, nästa stora utgåva av det populära programmeringsspråket?

Nu börjar vi!

PHP-JIT (Just in Time-kompilator)

Den mest hyllade funktionen som kommer med PHP 8 är Just-In-time (JIT)-kompilatorn. Vad handlar JIT om?

RFC-förslaget beskriver JIT enligt följande:

”PHP JIT implementeras som en nästan oberoende del av OPcache. Det kan vara aktiverat/inaktiverat vid PHPs kompileringstid och vid driftstid. När det är aktiverat lagras inbyggd kod för PHP-filer i en ytterligare region i OPcachens delade minne och op_array→opcodes[].handler sparar visare till ingångspunkterna för JIT-koden.”

Så, hur kom vi till JIT och vad är skillnaden mellan JIT vs OPcache?

För att bättre förstå vad JIT betyder för PHP, låt oss ta en snabb titt på hur PHP exekverar från källkoden till slutresultatet.

PHP-exekveringen är en 4-stegsprocess:

Följande bild visar en visuell representation av den grundläggande PHP-exekveringsprocessen.

Grundläggande PHP-exekveringsprocess

Grundläggande PHP-exekveringsprocess

Så, hur gör OPcache PHP snabbare? Och vad förändras i exekveringsprocessen med JIT?

OPcache-tillägget

PHP är ett tolkningsspråk. Detta innebär att när ett PHP-skript körs kommer tolken parsa, kompilera, och exekvera koden om och om igen för varje begäran. Detta kan leda till att det slösas CPU-resurser och tar extra lång tid.

Det är här OPcache-tillägget kommer in i bilden.

”OPcache förbättrar PHP-prestanda genom att lagra förkompilerade skript-bytekod i ett delat minne, vilket tar bort behovet av att PHP laddar och parsar skript för varje begäran.”

Med OPcache aktiverat går PHP-tolken igenom 4-stegsprocessen som nämns ovan endast första gången skriptet körs. Eftersom PHP-bytekoder lagras i ett delat minne är de omedelbart tillgängliga som mellanliggande representation på låg nivå, och kan exekveras på Zend VM direkt.

PHP-exekveringsprocess med OPcache aktiverat

PHP-exekveringsprocess med OPcache aktiverat

Från och med PHP 5.5 är Zend OPcache-tillägget tillgängligt som standard och du kan kontrollera om du har det korrekt konfigurerat genom att helt enkelt anropa phpinfo() från ett skript på din server eller kolla din php.ini-fil (se inställningarna för OPcache-konfiguration).

Zend OPcache-sektionen i en phpinfo-sida

Zend OPcache-sektionen i en phpinfo-sida

Förladdning

OPcache har nyligen förbättrats med implementeringen av förladdning, en ny OPcache-funktion som lades till med PHP 7.4. Förladdning ger ett sätt att lagra en angiven uppsättning skript i OPcacheminnet ”innan någon applikationskod körs”, men det ger inte någon påtaglig prestandaförbättring för typiska webbaserade applikationer.

Du kan läsa mer om förladdning i vår introduktion till PHP 7.4.

Med JIT tar PHP ett kliv framåt.

JIT – Just in Time-kompilator

Även om Opkoder är i form av mellanliggande representation på låg nivå måste de fortfarande kompileras till maskinkod. JIT ”introducerar inte någon ytterligare IR-form (Mellanliggande Representation)”, men använder DynASM (Dynamic Assembler för kodgenereringsmotorer) för att generera maskinkod direkt från PHP-bytekod.

Kort sagt översätter JIT de heta delarna av den mellanliggande koden till maskinkod. Genom att kringgå kompilering skulle det kunna ge betydande förbättringar i prestanda och minnesanvändning.

Zeev Surasky, medförfattare till PHP JIT-förslaget, visar hur mycket snabbare beräkningarna skulle vara med JIT:

Men, skulle JIT effektivt förbättra WordPress-prestanda?

JIT för webbapplikationer

Enligt JIT-förslaget bör implementeringen av just in time-kompilatorn förbättra PHP-prestanda. Men skulle vi verkligen uppleva sådana förbättringar i verkliga applikationer som WordPress?

De tidiga testerna visar att JIT skulle göra CPU-intensiva arbetsbelastningar betydligt snabbare, men RFC varnar:

”…precis som de tidigare försöken – det verkar för närvarande inte avsevärt förbättra verkliga applikationer som WordPress (med opcache.jit=1235 326 förfrågningar/s vs 315 förfrågningar/s).

Det är planerat att tillhandahålla ytterligare ansträngningar och förbättra JIT för verkliga applikationer, med hjälp av profilering och spekulativa optimeringar.”

Med JIT aktiverat skulle koden inte köras av Zend VM, utan av själva CPU:n och detta skulle förbättra beräkningshastigheten. Webbapplikationer som WordPress är också beroende av andra faktorer som TTFB, databasoptimering, HTTP-förfrågningar etc.

Så när det gäller WordPress och liknande applikationer bör vi inte förvänta oss en stor ökning i PHP-exekveringshastighet. Ändå kan JIT ge flera fördelar för utvecklare.

Enligt Nikita Popov:

”Fördelarna med JIT-kompilatorn är ungefär (och som redan beskrivits i dess RFC):

  • Betydligt bättre prestanda för numerisk kod.
  • Något bättre prestanda för ”typisk” PHP-webbapplikationskod.
  • Möjligheten att flytta mer kod från C till PHP, eftersom PHP nu kommer att vara tillräckligt snabbt.”

Så medan JIT knappast kommer att medföra stora förbättringar av WordPress-prestanda kommer det att uppgradera PHP till nästa nivå, vilket gör det till ett språk som många funktioner nu kan skrivas direkt i.

Nackdelen skulle dock vara den större komplexiteten som kan leda till ökade kostnader för underhåll, stabilitet och felsökning. Enligt Dmitrij Stogov:

”JIT är extremt enkelt, men ändå ökar det nivån på hela PHP-komplexiteten, risken för nya typer av buggar och kostnader för utveckling och underhåll.”

Förslaget att inkludera JIT i PHP 8 godkändes med 50 röster mot 2.

PHP 8 kommer senare i år. 🚀 Kolla in vår djupdykning in de nya funktionerna!Click to Tweet

PHP 8 förbättringar och nya funktioner

Förutom JIT kan vi förvänta oss många funktioner och förbättringar med PHP 8. Följande lista är vårt handplockade urval av kommande tillägg och förändringar som bör göra PHP mer tillförlitligt och effektivt.

Validering för Abstrakta Trait-metoder

Traits definieras som ”en mekanism för kodåteranvändning i arvsbaserade språk som PHP”. Vanligtvis används de för att deklarera metoder som kan användas i flera klasser.

De kan också innehålla abstrakta metoder. Dessa metoder deklarerar helt enkelt metodens signatur, men metodens implementering måste ske inom klassen med hjälp av detta trait.

Enligt PHP-manualen;

”Traits stöder användningen av abstrakta metoder för att införa krav på den uppvisande klassen.”

Detta innebär också att metodernas signaturer måste matcha varandra. Med andra ord måste typen och antalet nödvändiga argument vara lika.

Hur som helst, enligt Nikita Popov, författare till denna RFC, är signaturvalidering för närvarande endast verkställt ibland.

Följande exempel från Nikita avser det första fallet (ej verkställd signatur:

trait T {
	abstract public function test(int $x);
}
 
class C {
	use T;

	// Allowed, but shouldn't be due to invalid type.
	public function test(string $x) {}
}

Med detta sagt föreslår denna RFC att alltid visa ett allvarligt fel om implementeringsmetoden inte är kompatibel med abstract trait-metoden, oavsett ursprung:

Fatal error: Declaration of C::test(string $x) must be compatible with T::test(int $x) in /path/to/your/test.php on line 10

Denna RFC har enhälligt godkänts.

Inkompatibla Metodsignaturer

I PHP ger ärvda fel på grund av inkompatibla metodsignaturer antingen ett allvarligt fel eller en varning beroende på vad som orsakar felet.

Om en klass implementerar ett gränssnitt ger inkompatibla metodsignaturer ett allvarligt fel. Enligt dokumentationen för objektgränssnitt:

”Den klass som implementerar gränssnittet måste använda en metodsignatur som är kompatibel med LSP (Liskov Substitutionsprincip). Om du inte gör det kommer det att leda till ett allvarligt fel.”

Här är ett exempel på ett arvsfel med ett gränssnitt:

interface I {
	public function method(array $a);
}
class C implements I {
	public function method(int $a) {}
}

I PHP 7.4 skulle koden ovan ge följande fel:

Fatal error: Declaration of C::method(int $a) must be compatible with I::method(array $a) in /path/to/your/test.php on line 7

En funktion i en barnklass med en inkompatibel signatur skulle ge en varning. Se följande kod från RFC:

class C1 {
	public function method(array $a) {}
}
class C2 extends C1 {
	public function method(int $a) {}
}

I PHP 7.4 skulle koden ovan helt enkelt ge en varning:

Warning: Declaration of C2::method(int $a) should be compatible with C1::method(array $a) in /path/to/your/test.php on line 7

Nu föreslår denna RFC att alltid ge ett allvarligt fel för inkompatibla metodsignaturer. Med PHP 8 skulle koden vi såg tidigare ovan leda till följande:

Fatal error: Declaration of C2::method(int $a) must be compatible with C1::method(array $a) in /path/to/your/test.php on line 7

Arrayer som börjar med ett negativt Index

Om en array börjar i PHPH med ett negativt index (start_index < 0), startar följande index från 0 (mer om detta iarray_fill-dokumentationen). Titta på följande exempel:

$a = array_fill(-5, 4, true);
var_dump($a);

I PHP 7.4 skulle resultatet vara följande:

array(4) {
	[-5]=>
	bool(true)
	[0]=>
	bool(true)
	[1]=>
	bool(true)
	[2]=>
	bool(true)
}

Nu föreslår denna RFC att ändra på detta så att det andra indexet skulle vara start_index + 1, beroende på värdet av start_index.

I PHP 8 skulle koden ovan resultera i följande array:

array(4) {
	[-5]=>
	bool(true)
	[-4]=>
	bool(true)
	[-3]=>
	bool(true)
	[-2]=>
	bool(true)
}

Med PHP 8 ändrar arrayer som börjar med ett negativt index sitt beteende. Läs mer om bakåtkompatibiliteter på RFC-sidan.

Unionstyper

Unionstyper accepterar värden som kan vara av olika slag. För närvarande tillhandahåller PHP inte stöd för unionstyper, med undantag för ?Type-syntaxen och den speciella iterable-typen.

Innan PHP 8 kunde unionstyper endast anges i phpdoc-anteckningar, vilket visas i följande exempel från RFC:

class Number {
	/**
	 * @var int|float $number
	 */
	private $number;

	/**
	 * @param int|float $number
	 */
	public function setNumber($number) {
		$this->number = $number;
	}

	/**
	 * @return int|float
	 */
	public function getNumber() {
		return $this->number;
	}
}

Unionstyperna 2.0 RFC föreslår att lägga till stöd för unionstyper i funktionssignaturer, så att vi inte längre kommer att förlita oss på inline-dokumentation, utan skulle definiera unionstyper med en T1|T2|…-syntax istället:

class Number {
	private int|float $number;

	public function setNumber(int|float $number): void {
		$this->number = $number;
	}

	public function getNumber(): int|float {
		return $this->number;
	}
}

Nikita Popov förklarar i RFC,

”Att stödja unionstyper i språket gör det möjligt för oss att flytta mer typinformation från phpdoc till funktionssignaturer, med de vanliga fördelarna som detta medför:

  • Typer är faktiskt verkställda, så misstag kan fångas tidigt.
  • Eftersom de verkställs är typinformation mindre sannolikt att bli föråldrad eller missa edge-cases.
  • Typer kontrolleras genom arv, vilket verkställer Liskovs Substitutionsprincip.
  • Typer är tillgängliga genom Reflection.
  • Syntaxen är mycket mindre standardiserad än phpdoc.”

Unionstyper stöder alla tillgängliga typer, med vissa begränsningar:

Du kan läsa mer om Unionstyper V2 i dess RFC.

Konsekventa typfel för interna funktioner

När en parameter av olaglig typ används beter sig interna och användardefinierade funktioner annorlunda.

Användardefinierade funktioner skapar ett TypeError, men interna funktioner beter sig på olika sätt, beroende på flera omständigheter. Hur som helst, det typiska beteendet är att visa en varning och returnera null. Se följande exempel i PHP 7.4:

var_dump(strlen(new stdClass));

Detta skulle resultera i följande varning:

Warning: strlen() expects parameter 1 to be string, object given in /path/to/your/test.php on line 4
NULL

Om strict_types är aktiverat, eller argumentinformationen specificerar typer skulle beteendet vara annorlunda. I sådana scenarier upptäcks typfelet och resulterar ett TypeError.

Denna situation skulle leda till ett antal problem som förklaras väl i problemavsnittet på förslagets RFC-sida.

För att ta bort dessa inkonsekvenser föreslår denna RFC att få den interna parametern som parsar API:er att alltid generera ett ThrowError i händelse av en felmatchad parametertyp.

I PHP 8 ger koden ovan följande fel:

Fatal error: Uncaught TypeError: strlen(): Argument #1 ($str) must be of type string, object given in /path/to/your/test.php:4
Stack trace:
#0 {main}
  thrown in /path/to/your/test.php on line 4

Uttrycket throw

I PHP är throw en sats, så det är inte möjligt att använda det på platser där endast ett uttryck är tillåtet.

Denna RFC föreslår att konvertera satsen throw till ett uttryck så att den kan användas i alla sammanhang där uttryck är tillåtna. Till exempel arrow-funktioner, null coalesce-operatör, ternary och elvis-operatörer etc.

Se följande exempel från RFC:

$callable = fn() => throw new Exception();

// $value is non-nullable.
$value = $nullableValue ?? throw new InvalidArgumentException();
 
// $value is truthy.
$value = $falsableValue ?: throw new InvalidArgumentException();

Svaga kartor

En svag karta är en samling data (objekt) där nycklarna är svagt refererade, vilket innebär att de inte hindras från att samlas in som skräp.

PHP 7.4 lade till stöd för svaga referenser som ett sätt att behålla en referens till ett objekt som inte hindrar själva objektet från att förstöras. Nikita Popov påpekar:

”Råa svaga referenser är bara av begränsad användbarhet för sig själva och svaga kartor används mycket oftare i praktiken. Det är inte möjligt att implementera en effektiv svag karta ovanpå PHP:s svaga referenser eftersom möjligheten att registrera en förstörelse-callback inte tillhandahålls.”

Därför introducerar denna RFC en WeakMap-klass för att skapa objekt som ska användas som svaga kartnycklar som kan förstöras och tas bort från den svaga kartan om det inte finns några ytterligare referenser till nyckelobjektet.

I långvariga processer skulle detta förhindra minnesläckor och förbättra prestanda. Se följande exempel från RFC:

$map = new WeakMap;
$obj = new stdClass;
$map[$obj] = 42;
var_dump($map);

Med PHP 8 skulle koden ovan producera följande resultat (se koden här):

object(WeakMap)#1 (1) {
	[0]=>
	array(2) {
		["key"]=>
		object(stdClass)#2 (0) {
		}
		["value"]=>
		int(42)
	}
}

Om du avmarkerar objektet tas nyckeln automatiskt bort från den svaga kartan:

unset($obj);
var_dump($map);

Nu skulle resultatet bli följande:

object(WeakMap)#1 (0) {
}

För en närmare titt på svaga kartor, se förslagets RFC. Förslaget godkändes enhälligt.

Avslutande kommatecken i parameterlistan

Avslutande kommatecken är kommatecken som bifogas listor över objekt i olika sammanhang. PHP 7.2 introducerade avslutande kommatecken i listsyntax, PHP 7.3 introducerade avslutande kommatecken i funktionsanrop.

Behöver du en blixtsnabb, säker samt utvecklarvänlig hosting för dina webbplatser? Kinsta är byggt med WordPress-utvecklare i åtanke och förser sina användare med en mängd verktyg och en kraftfull instrumentpanel. Kolla in våra planer

PHP 8 introducerar nu avslutande kommatecken i parameterlistor med funktioner, metoder och stängningar, som visas i följande exempel:

class Foo {
	public function __construct(
		string $x,
		int $y,
		float $z, // trailing comma
	) {
		// do something
	}
}

Detta förslag antogs med 58 röster mot 1.

Tillåt ::class-syntax på objekt

För att hämta namnet på en klass kan vi använda Foo\Bar::class-syntaxen. Denna RFC föreslår att utöka samma syntax till objekt så att det nu är möjligt att hämta namnet på klassen för ett visst objekt som visas i exemplet nedan:

$object = new stdClass;
var_dump($object::class); // "stdClass"
 
$object = null;
var_dump($object::class); // TypeError

Med PHP 8 ger  $object::class samma resultat som get_class($object). Om $object inte är ett objekt, ger det ett TypeError-undantag.

Detta förslag godkändes enhälligt.

Attribut v2

Attribut, även känd som annoteringar, är en form av strukturerade metadata som kan användas för att ange egenskaper för objekt, element eller filer.

Fram till PHP 7.4 var doc-kommentarer det enda sättet att lägga till metadata i deklarationer av klasser, funktioner etc. Nu introducerar RFC-förslaget Attribut v2 attribut för PHP som definierar dem som en form av strukturerade, syntaktiska metadata som kan läggas till deklarationer av klasser, egenskaper, funktioner, metoder, parametrar och konstanter.

Attribut läggs till före de deklarationer de hänvisar till. Se följande exempel från RFC:

<>
class Foo
{
	<>
	public const FOO = 'foo';

	<>
	public $x;

	<>
	public function foo(<> $bar) { }
}

$object = new <> class () { };

<>
function f1() { }

$f2 = <> function () { };

$f3 = <> fn () => 1;

Attribut kan läggas till före eller efter en doc-block-kommentar:

<>
/** docblock */
<>
function foo() {}

Varje deklaration kan ha ett eller flera attribut och varje attribut kan ha ett eller flera associerade värden:

<>
<<SingleArgument(0)>>
<<FewArguments('Hello', 'World')>>
function foo() {}

Se RFC-sidan för en djupare översikt över PHP-attribut, användning, och alternativ syntax. Observera att Attribut v2 för närvarande väntar på implementering.

Nya PHP-functioner

PHP 8 för med sig flera nya funktioner till programmeringsspråket:

str_contains

Innan PHP 8 var strstr och strpos de typiska alternativen för utvecklare som behövde söka efter en nål i en given sträng. Problemet är att ingen av funktionerna anses vara särskilt intuitiva och deras användning kan vara förvirrande för nya PHP-utvecklare. Se följande exempel:

$mystring = 'Managed WordPress Hosting';
$findme = 'WordPress';
$pos = strpos($mystring, $findme);

if ($pos !== false) {
	echo "The string has been found";
} else {
	echo "String not found";
}

I exemplet ovan använde vi jämförelseoperatören !==, som också kontrollerar om två värden är av samma typ. Detta hindrar oss att få ett fel om nålens position är 0:

”Den här funktionen kan returnera Boolesk FALSE men kan också returnera ett icke-booleskt värde som evalueras till FALSE […] Använd ===-operatören för att testa returvärdet för denna funktion.”

Dessutom tillhandahåller flera ramverk hjälpfunktioner för att söka efter ett värde i en given sträng (se Laravel Hjälpdokumentation som ett exempel).

Nu föreslår denna RFC införandet av en ny funktion som gör det möjligt att söka i en sträng: str_contains.

str_contains ( string $haystack , string $needle ) : bool

Dess användning är ganska enkel. str_contains kollar om $needle finns i $haystack och returnerar true eller false i enlighet därmed.

Så tack vare str_contains kan vi skriva följande kod:

$mystring = 'Managed WordPress Hosting';
$findme   = 'WordPress';

if (str_contains($mystring, $findme)) {
	echo "The string has been found";
} else {
	echo "String not found";
}

Vilket är mer läsbart och mindre felbenäget (se denna kod här).
Vid skrivande stund är str_contains skiftlägeskänsligt men det kan förändras i framtiden.

Förslaget str_contains antogs med 43 röster mot 9.

str_starts_with() och str_ends_with()

Förutom str_contains-funktionen tillåter två nya funktioner dig att söka efter en nål i en given sträng: str_starts_with och str_ends_with.

Dessa nya funktioner kontrollerar om en viss sträng börjar eller slutar med en annan sträng:

str_starts_with (string $haystack , string $needle) : bool
str_ends_with (string $haystack , string $needle) : bool

Båda funktionerna returnerar false om $needle är längre än $haystack.

Enligt Will Hudgins, författaren till denna RFC:

str_starts_with och str_ends_with-funktionaliteten är så vanliga att många stora PHP-ramverk har stöd för det, inklusive Symfony, Laravel, Yii, FuelPHP, och Phalcon.”

Tack vare dem kunde vi nu undvika att använda suboptimala och mindre intuitiva funktioner som substr, strpos. Båda funktionerna är skiftlägeskänsliga:

$str = "WordPress";
if (str_starts_with($str, "Word")) echo "Found!";

if (str_starts_with($str, "word")) echo "Not found!";

Du kan se denna kod här.

Denna RFC har godkänts med 51 röster mot 4.

get_debug_type

get_debug_type är en ny PHP-funktion som returnerar en variabels typ. Den nya funktionen fungerar på ett ganska likartat sätt som gettype-funktionen, men get_debug_type returnerar inbyggda typnamn och löser klassnamn.

Det är en bra förbättring för språket, eftersom gettype() inte är användbart för typkontroll.

Förslaget ger två användbara exempel för att bättre förstå skillnaden mellan den nya get_debug_type()-funktionen och gettype(). Det första exemplet visar hur gettype fungerar:

$bar = [1,2,3];

if (!($bar instanceof Foo)) { 
	throw new TypeError('Expected ' . Foo::class . ', got ' . (is_object($bar) ? get_class($bar) : gettype($bar)));
}

Med PHP 8 kan vi använda get_debug_type istället:

if (!($bar instanceof Foo)) { 
	throw new TypeError('Expected ' . Foo::class . ' got ' . get_debug_type($bar));
}

Följande tabell visar returvärden för get_debug_type och gettype

:

Value gettype() get_debug_type()
1 integer int
0.1 double float
true boolean bool
false boolean bool
null NULL null
”WordPress” string string
[1,2,3] array array
En klass med namn ”Foo\Bar” object Foo\Bar
En anonym klass object class@anonymous

Ytterligare RFC

Vid skrivande stund finns flera RFC för PHP 8 fortfarande i utkast och/eller väntar på implementering. Vi lägger till dem så snart deras status ändras till ”implementerad”.

Här är en snabb lista över ytterligare godkända förbättringar som kommer att vara en del av PHP 8:

  1. Strängbart gränssnitt: denna RFC introducerar ett Strängbart gränssnitt som automatiskt läggs till i klasser som implementerar __to String()-metoden. Huvudmålet här är att använda unionstypen string|Stringable.
  2. Nya DOM Living Standard-API:er i ext/dom: denna RFC föreslår att implementera den nuvarande DOM Living Standarden till PHP DOM-tillägget genom att introducera nya gränssnitt och offentliga egendomar.
  3. Returtypen Static: PHP 8 introducerar användningen av static som returtyp bredvid self och parent-typerna.
  4. Variabel Syntax-justeringar: denna RFC löser vissa kvarvarande inkonsekvenser i PHP:s variabla syntax.
PHP 8 kommer senare i år och det kommer att medföra massor av förändringar och förbättringar. 🚀 Kolla in vår djupdykning in de nya funktionerna!Click to Tweet

Sammanfatting

Snacka om imponerande! I det här inlägget täckte vi alla viktiga förändringar och förbättringar som kan förväntas med utgåvan av PHP 8. Den mest efterlängtade är garanterat Just in Time-kompilatorn, men det finns så mycket mer på gång med PHP 8.

Se till att bokmärka detta blogginlägg eftersom vi lägger till våra favoriter i listan så snart de är godkända. 🤓

Nu är det din tur: är du redo att testa de kommande PHP-funktionerna? Vilken är din favorit? Skriv en rad i kommentarfältet nedan.


Om du tyckte om den här artikeln, då kommer du att älska Kinsta´s hosting-plattform. Effektivisera din hemsida och få support dygnet runt från vårt rutinerade team på WordPress. Vår Google Cloud-drivna infrastruktur fokuserar på auto-skalning, prestanda och säkerhet. Lås oss visa dig skillnaden med Kinsta! Kolla in våra paket