PHP 7.4, nästa mindre utgåva av PHP 7 släpptes för allmän tillgänglighet 28 November 2019. Så det är dags för oss att dyka in i några av de mest spännande tilläggen och nya funktioner som kommer att ha gjort PHP snabbare och mer tillförlitligt.

Uppdatering: PHP 8.1 (officiell release) finns nu tillgänglig för alla Kinsta-kunder. PHP 7.4 stöds inte längre hos Kinsta. Observera att vi stöder PHP-versionerna 8.0, 8.1, 8.2 och 8.3.

Även om PHP 7.4 väsentligt ökar prestanda och förbättrar kodläsbarheten, kommer PHP 8 att vara den verkliga milstolpen för PHP-prestanda, eftersom förslaget till JIT-inkludering redan har godkänts.

Hur som helst, idag går vi igenom några av de mest intressanta funktionerna och förändringarna vi kan förvänta oss från PHP 7.4. Så, innan du läser det här inlägget, se till att spara följande datum:

  • 6 juni, 2019: PHP 7.4 Alpha 1
  • 18 juli, 2019: PHP 7.4 Beta 1 – Funktionsfrysning
  • 28 november, 2019: PHP 7.4 Allmänt släpp

Du kan kolla in den fullständiga listan över funktioner och tillägg på den officiella RFC-sidan.

Vad är nytt i PHP med PHP 7.4?

I det här inlägget täcker vi flera ändringar och funktioner som borde läggas till språket för den slutliga utgåvan av PHP 7.4:

Glöm array_merge: PHP 7.4 tar in Spread Operator i array-uttryck

Tillgänglig sedan PHP 5.6; argument-uppackning är en syntax för uppackning av arrayer och Traversables i argumentlistor. För att packa upp en array eller en Traversable måste den förberedas med … (3 punkter), som visas i följande exempel:

function test(...$args) { var_dump($args); }
test(1, 2, 3);

Nu föreslår denna PHP 7.4 RFC att utöka denna funktion till array-definitioner:

$arr = [...$args];

Den första uttalade fördelen med Spread Operator i array-uttryck handlar om prestanda. I själva verket säger RFC-dokumentet:

Spread Operator bör ha bättre prestanda än array_merge. Det är inte bara för att spread operatorn är en språkstruktur medan array_merge är en funktion, men också för att kompilerad tidsoptimering kan vara performant för konstanta arrayer.

En betydande fördel med Spread operator är att den stöder alla förflyttbara objekt, medan array_merge-funktionen endast stöder arrayer.

Här är ett exempel på argument-uppackning i array-uttryck:

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
var_dump($fruits);

Om du kör den här koden i PHP 7.3 eller tidigare, ger PHP ett Parse-fel:

Parse error: syntax error, unexpected '...' (T_ELLIPSIS), expecting ']' in /app/spread-operator.php on line 3

Istället skulle PHP 7.4 returnera en array:

array(5) {
	[0]=>
	string(6) "banana"
	[1]=>
	string(6) "orange"
	[2]=>
	string(5) "apple"
	[3]=>
	string(4) "pear"
	[4]=>
	string(10) "watermelon"
}

RFC säger att vi kan expandera samma array flera gånger. Dessutom kan vi använda Spread Operator syntax överallt i arrayen, eftersom normala element kan läggas till före eller efter spread operator. Så följande kod kommer att fungera som vi kan förvänta oss:

$arr1 = [1, 2, 3];
$arr2 = [4, 5, 6];
$arr3 = [...$arr1, ...$arr2];
$arr4 = [...$arr1, ...$arr3, 7, 8, 9];

Det är också möjligt att packa upp arrayer som returneras av en funktion direkt i en ny array:

function buildArray(){
	return ['red', 'green', 'blue'];
}
$arr1 = [...buildArray(), 'pink', 'violet', 'yellow'];

PHP 7.4 matar ut följande array:

array(6) {
	[0]=>
	string(3) "red"
	[1]=>
	string(5) "green"
	[2]=>
	string(4) "blue"
	[3]=>
	string(4) "pink"
	[4]=>
	string(6) "violet"
	[5]=>
	string(6) "yellow"
}

Vi kan också använda generatorsyntaxen:

function generator() {
	for ($i = 3; $i <= 5; $i++) {
		yield $i;
	}
}
$arr1 = [0, 1, 2, ...generator()];

Men vi får inte packa upp arrays som skickas som referens. Överväg följande exempel:

$arr1 = ['red', 'green', 'blue'];
$arr2 = [...&$arr1];

Om vi skulle försöka packa upp en array genom referens, ger PHP följande Parse-fel:

Parse error: syntax error, unexpected '&' in /app/spread-operator.php on line 3

Hur som helst, om elementen i den första arrayen lagras som referens, lagras de också som referens i den andra arrayen. Här är ett exempel:

$arr0 = 'red';
$arr1 = [&$arr0, 'green', 'blue'];
$arr2 = ['white', ...$arr1, 'black'];

Och här är vad vi får med PHP 7.4:

array(5) {
	[0]=>
	string(5) "white"
	[1]=>
	&string(3) "red"
	[2]=>
	string(5) "green"
	[3]=>
	string(4) "blue"
	[4]=>
	string(5) "black"
}

Förslaget om Spread Operator antogs med 43-1 röster.

Pilfunktioner 2.0 (Korta stängningar)

I PHP anses anonyma funktioner vara ganska omständliga och svåra att genomföra och underhålla. Denna RFC föreslår införandet av kortare och tydligare syntax av pilfunktionerna (eller korta stängningar), som bör göra det möjligt för oss att rensa upp betydligt i vår PHP-kod.

Överväg följande exempel:

function cube($n){
	return ($n * $n * $n);
}
$a = [1, 2, 3, 4, 5];
$b = array_map('cube', $a);
print_r($b);

PHP 7.4 gör det möjligt att använda en mer kortfattad syntax, och funktionen ovan kan skrivas om enligt följande:

$a = [1, 2, 3, 4, 5];
$b = array_map(fn($n) => $n * $n * $n, $a);
print_r($b);

För närvarande kan anonyma funktioner (stängningar) ärva variabler som definieras i den överordnade omfattningen tack vare språkkonstruktionen use, som visas nedan:

$factor = 10;
$calc = function($num) use($factor){
	return $num * $factor;
};

Men med PHP 7.4, fångas variabler som definieras i den överordnade omfattningen implicit av värde (implicit av-värde scopebindning). Så vi kan skriva hela funktionen som ses ovan på en enda rad:

$factor = 10;
$calc = fn($num) => $num * $factor;

Variabeln som definieras i den överordnade omfattningen kan användas i pilfunktionen precis som om vi använde use($var), och det är inte möjligt att ändra en variabel från den överordnad omfattningen.

Den nya syntaxen är en stor förbättring av språket eftersom det tillåter oss att bygga mer läsbar och underhållbar kod. Vi kan också använda parametrar och return-typer, standardvärden, variabellängdsargumentlistor (variadiska funktioner), vi kan skicka och returnera via referens etc. Slutligen kan korta stängningar också användas i klassmetoder, och de kan använda sig av $this-variabeln precis som vanliga stängningar.

Denna RFC har godkänts med 51 mot 8 röster, så vi kan förvänta oss att det kommer vara en del av tilläggen till PHP-7.4.

Null Coalescing Tilldelningsoperator

Tillagd med PHP 7, coalesce-operatorn (??) kommer väl till pass när vi behöver använda en ternär operator i samband med isset(). Den returnerar den första operanden om den finns och inte är NULL. Annars returnerar den andra operanden. Här är ett exempel:

$username = $_GET['user'] ?? 'nobody';

Vad den här koden gör är ganska enkelt: den hämtar förfrågningsparametern och ställer in ett standardvärde om den inte finns. Betydelsen av den raden är tydlig, men vad händer om vi hade mycket längre variabelnamn som i det här exemplet från RFC?

$this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ?? 'value';

På lång sikt kan denna kod vara lite svår att underhålla. Så, med syfte att hjälpa utvecklare att skriva mer intuitiv kod, föreslår denna RFC införandet av null coalescing tilldelningsoperator (??=). Så istället för att skriva den tidigare koden kan vi skriva följande:

$this->request->data['comments']['user_id'] ??= 'value';

Om värdet på den vänstra parametern är null, används värdet på den högra parametern.
Observera att medan coalesce-operatorn är en jämförelseoperator, är ??= en tilldelningsoperator.

Detta förslag har godkänts med 37 mot 4 röster.

Typade Egenskaper 2.0

Argumenttyp-deklarationer, eller type hints, gör det möjligt att ange vilken typ av variabel som förväntas överföras till en funktion eller en klassmetod. Type hints är en funktion som är tillgänglig sedan PHP 5, och sedan PHP 7.2 kan vi använda dem med objekt-datatypen. Nu för PHP 7.4 type hinting ett steg framåt genom att lägga till stöd för första klassens egenskapstyp-deklarationer. Här är ett mycket grundläggande exempel:

class User {
	public int $id;
	public string $name;
}

Alla typer stöds, med undantag fö void och callable:

public int $scalarType;
protected ClassName $classType;
private ?ClassName $nullableClassType;

RFC förklarar anledningen till att void och callable inte stöds:

Void-typen stöds inte, eftersom den inte är användbar och har oklar semantik.

Callable-typen stöds inte, eftersom dess beteende är kontextberoende.

Så kan vi säkert använda boolintfloatstringarrayobjectiterableselfparent, alla klass eller gränssnittsnamn, och ogiltiga typer (?type).

Typer kan användas på statiska egenskaper:

public static iterable $staticProp;

De är också tillåtna med var notation:

var bool $flag;

Det är möjligt att ställa in standardegenskapsvärden, vilka naturligtvis måste matcha den deklarerade egenskapstypen, men endast ogiltiga egenskaper kan ha ett standard null-värde:

public string $str = "foo";
public ?string $nullableStr = null;

Samma typ gäller för alla egenskaper i en enda deklaration:

public float $x, $y;

Vad händer om vi gör ett fel på egenskapstypen? Betrakta följande kod:

class User {
	public int $id;
	public string $name;
}

$user = new User;
$user->id = 10;
$user->name = [];

I koden ovan deklarerade vi en string-egenskapstyp, men vi anger en array som egenskapsvärde. I ett sådant scenario får vi följande Allvarliga fel:

Fatal error: Uncaught TypeError: Typed property User::$name must be string, array used in /app/types.php:9

Denna RFC har godkänts med 70 mot 1 röster.

WeakReferences

Med denna RFC introducerar PHP 7.4 WeakReference-klassen, vilket gör det möjligt för programmerare att behålla en referens till ett objekt som inte hindrar själva objektet från att förstöras.

För närvarande stöder PHP Weak References genom att använda ett tillägg som pecl-weakref. Hur som helst, det nya API:t skiljer sig från den dokumenterade WeakRef -klassen.

Här är ett exempel från författaren till detta förslag, Nikita Popov:

$object = new stdClass;
$weakRef = WeakReference::create($object);

var_dump($weakRef->get());
unset($object);
var_dump($weakRef->get());

Den förstavar_dump skriver ut object(stdClass)#1 (0) {}, medan den andra var_dump skriver u NULL, eftersom det refererade objektet har förstörts.

Denna RFC godkändes med 28 mot 5 röster.

Covariant Returer och Contravariant Parametrar

Varians är en egenskap hos klasshierarkier som beskriver hur typerna av en typkonstruktör påverkar undertyper. I allmänhet kan en typkonstruktör vara:

  • Invariant: om typen av supertypen begränsar typen av subtypen.
  • Covariant: om ordning av typer bevaras (typer ordnas från mer specifika till mer generiska).
  • Contravariant: om det vänder ordningen (typer ordnas från mer generisk till mer specifik).

För närvarande har PHP mestadels invarianta parameter och returtyper, med få undantag. Denna RFC föreslår att tillåta covariance och contravariance på parametertyper och returtyper, och ger också flera exempel på kod.

Här är ett exempel på covariant returtyp:

interface Factory {
	function make(): object;
}

class UserFactory implements Factory {
	function make(): User;
}

Och här är ett exempel på contravariant parametertyp:

interface Concatable {
	function concat(Iterator $input); 
}
 
class Collection implements Concatable {
	// accepts all iterables, not just Iterator
	function concat(iterable $input) {/* . . . */}
}

Se RFC för en närmare titt på covariance och contravariance i PHP 7.4.

Denna RFC godkändes med 39 mot 1 röster.

Preloading

Detta förslag från Dmitry Stogov är en av våra favoriter eftersom det borde ge en betydande ökning av prestanda. Preloading är processen att ladda bibliotek och ramar i OPCache vid modulinitiering (Läs mer om PHP livscykel).

PHP livscykel
PHP livscykel (bildkälla: PHP Internals)

Så här fungerar Preloading enligt Dmitry:

Vid serverstart – innan någon applikationskod körs – kan vi ladda en viss uppsättning PHP-filer till minnet – och göra deras innehåll ”permanent tillgängligt” för alla efterföljande förfrågningar som kommer att serveras av den servern. Alla funktioner och klasser som definieras i dessa filer kommer att vara tillgängliga för förfrågningar direkt, precis som interna enheter.

Dessa filer laddas vid serverstart, exekveras innan något program och är tillgängliga för eventuella framtida förfrågningar. Det är jättebra när det gäller prestanda.

Preloading styrs av ett specifikt php.ini-direktiv: opcache.preload. I detta direktiv specificeras ett PHP-skript som ska sammanställas och exekveras vid serverstart. Den här filen kan användas för att förinstallera ytterligare filer, antingen inkludera dem eller via opcache_compile_file()-funktionen (läs mer i PHP-dokumentationen).

Men det finns en nackdel. I själva verket anger RFC uttryckligen:

Preloaded files förblir cachade i opcache-minne för alltid. Ändring av deras motsvarande källfiler kommer inte att ha någon effekt utan en annan server-omstart.

Alla funktioner som definieras i preloaded files kommer dock att laddas permanent i PHP funktions och klasstabeller och förbli tillgängliga för varje framtida förfrågan. Detta kommer att leda till goda prestandaförbättringar, även om dessa förbättringar skulle kunna variera avsevärt.

Du kan läsa mer om begränsningar och undantag för preload på den officiella Preloading RFC-sidan.

Nytt anpassat objekt serialiseringsmekanism

Detta är ett annat förslag från Nikita Popov som godkändes med stor majoritet.

För närvarande har vi två olika mekanismer för anpassad serialisering av objekt i PHP:

  • De magiska metoderna __sleep() och __wakeup()
  • Serialized gränssnitt

Enligt Nikita har båda dessa alternativ problem som leder till komplex och opålitlig kod. Du kan dyka djupt in i detta ämne i RFC. Här nämner jag bara att den nya serialiseringsmekanismen bör förhindra dessa problem genom att tillhandahålla två nya magiska metoder, __serialize() och __unserialize(), som kombinerar de två befintliga mekanismerna.

Detta förslag antogs med 20-7 röster.

Avvecklingar

Följande funktioner/funktionaliteter kommer att avvecklas med PHP 7.4. För en mer omfattande lista över avvecklingar, kolla in PHP 7.4 Upgrade Notes.

Ändra den sammanlänkade operatörens företräde

I PHP gäller för närvarande att de aritmetiska operatörerna ”+” och ”-” strängoperatören ”.” är associativa och har samma företräde (Läs mer om Operatörsföreträde).

Som ett exempel, överväg följande rad:

echo "sum: " . $a + $b;

I PHP 7.3 producerar denna kod följande varning:

Warning: A non-numeric value encountered in /app/types.php on line 4

Detta är för att sammanslagningen utvärderas från vänster till höger. Det är samma som att skriva följande kod:

echo ("sum: " . $a) + $b;

Denna RFC föreslår att ändra företräde för operatörer, ge ”.” ett lägre företräde än ”+” och ”-”-operatörer, så att additioner och subtraktioner alltid skulle utföras innan strängsammanslagningen. Denna kod bör motsvara följande:

echo "sum: " . ($a + $b);

Detta är ett förslag i två steg:

  • Från och med version 7.4 bör PHP avge ett avvecklingsmeddelande när det stöter på ett uttryck med”+”, ”-” och ”.” utan parenteser.
  • Den faktiska förändringen av företräde för dessa operatörer bör läggas till med PHP 8.

Båda förslagen har godkänts med stor majoritet.

Avveckla vänster-associativ ternär operator

I PHP är den ternära operatören, till skillnad från många andra språk, vänster-associativ. Enligt Nikita Popof kan detta vara förvirrande för programmerare som byter mellan olika språk.

För närvarande är följande kod i PHP korrekt:

$b = $a == 1 ? 'one' : $a == 2 ? 'two' : $a == 3 ? 'three' : 'other';

Det tolkas som:

$b = (($a == 1 ? 'one' : $a == 2) ? 'two' : $a == 3) ? 'three' : 'other';

Och detta kan leda till fel eftersom det kanske inte är vad vi tänkt göra. Så denna RFC föreslår att avveckla och ta bort användningen av vänster-associativitet för ternära operatörer och tvinga utvecklare att använda parenteser.

Detta är ytterligare ett förslag i två steg:

  • Från och med PHP 7.4 kommer kapslade ternärer utan uttrycklig användning av parenteser att skapa en avvecklingsvarning.
  • Från och med PHP 8.0 kommer det att bli ett ’compile runtime error’.

Detta förslag har godkänts med 35 mot 10 röster.

Vad betyder PHP 7.4 för WordPress-användare?

PHP är det mest använda programmeringsspråket på serversidan på webben. Enligt W3Techs, räknat 2 December 2019, används PHP av 78.9% av alla webbplatser vars serverprogrammeringsspråk de kan upptäcka.

PHP-användning (December 2019)
PHP-användning (December 2019)

Tyvärr används PHP 5 fortfarande av 44.0% av alla webbplatser med ett känt serverprogrammeringsspråk. Om du lägger till antalet användare som fortfarande använder PHP 7.0 och 7.1, visar det sig att en stor majoritet av webbplatser kör versioner av PHP som inte stöds.

Supported PHP Versions for WordPress
Stödda PHP-versioner (Bildkälla: Supported Versions)

Enligt den officiella WordPress statistik-sidan, kör i skrivande stund 64% av alla WordPress-webbplatser av PHP som inte längre stöds. Endast lite över 13% använder: PHP 7.3. Och den senaste versionen, PHP 7.4, dyker inte ens upp ännu. Du kan se att en stor majoritet av användarna, över 23%, fortfarande kör PHP 5.6.

WordPress PHP versionsstatistik
WordPress PHP versionsstatistik

Vi rekommenderar starkt att du ber din värd om en version av PHP som stöds, helst enligt WordPress officiella krav. I skrivande stund, maj 2019, kräver WordPress:

  • PHP-version 7.3 eller senare.
  • MySQL-version 5,6 eller senare ELLER MariaDB-version 10.1 eller högre.
  • HTTPS-stöd

PHP 7 Prestanda

Siffrorna ovan är särskilt avskräckande från en prestandasynpunkt, eftersom PHP 7 har visat sig vara betydligt snabbare. Här är lite statistik:

  • Officiella PHP-riktmärken visar att PHP 7 tillåter systemet att utföra dubbelt så många förfrågningar per sekund jämfört med PHP 5.6, med nästan hälften så mycket latens.
  • Christian Vigh publicerade också en PHP prestandajämförelse där han fann att PHP 5.2 var 400% långsammare än PHP 7.
  • Andrei Avram såg snabbare exekveringstider och mindre minnesanvändning i PHP 7.4 jämfört med PHP 7.3
  • Phoronix körde några tidiga benchmarktester med PHP 7.4 Alpha och såg att det var något snabbare än PHP 7.3.

Vi körde våra egna PHP prestanda-benchmarks med PHP 7.3. Vi såg att WordPress 5.0 på PHP 7.3 kunde utföra nästan tre gånger så många transaktioner (förfrågningar) per sekund jämfört med PHP 5.6. Vi kommer att släppa våra PHP 7.4 benchmarks snart!

WordPress 5.0 PHP benchmarks
WordPress 5.0 PHP benchmarks
  • WordPress 5.0 PHP 5.6 benchmark: 91.64 förfrågningar/s
  • WordPress 5.0 PHP 7.0 benchmark-resultat: 206.71 förfrågningar/s
  • WordPress 5.0 PHP 7.1 benchmark-resultat: 210.98 förfrågningar/s
  • WordPress 5.0 PHP 7.2 benchmark-resultat: 229.18 förfrågningar/s
  • WordPress 5.0 PHP 7.3 benchmark-resultat: 253.20 förfrågningar/s 🏆

Många är långsamma att uppdatera helt enkelt på grund av den tid som är involverad i att testa nya alla sina tredjeparts plugins och teman för att säkerställa att de fungerar korrekt. Men många gånger, handlar det om att de helt enkelt inte satt igång.

Kontrollera Din PHP-Version

Inte säker på vilken version av PHP du kör? Ett av de enklaste sätten att kontrollera är att använda ett verktyg som Pingdom eller Google Chrome Devtools. Den första HTTP-rubriken visar vanligtvis versionen.

Kontrollera PHP-versionen i Pingdom
Kontrollera PHP-versionen i Pingdom

Detta bygger på att värden inte ändrar X-Powered-By-rubrikvärdet. Men många gör så på grund av säkerhetsskäl (inklusive Kinsta). Om så är fallet kanske du inte ser din PHP-version. I så fall, om du kör WordPress 5.2 eller högre, finns det ett nytt Webbplatshälsoverktyg du kan använda. Gå över till ”Verktyg” → ”Webbplatshälsa” → ” Info” och under avsnittet ”Server” hittar du serverns PHP-version.

Kontrollera PHP-versionen med WordPress webbplatshälsoverktyg
Kontrollera PHP-versionen med WordPress webbplatshälsoverktyg

Alternativt kan du installera ett gratis plugin som Version Info som visar dig grundläggande serverinformation i sidfoten på din WordPress-panel. Några andra sätt att se din PHP-version inkluderar att ladda upp en fil via FTP, eller helt enkelt fråga din värd.

Uppdatering till PHP 7.4

The final version of PHP 7.4 is available right now at Kinsta. Alternativt kan du testa din WordPress webbplats lokalt eller kontrollera dina skript i en miljö som Docker, vilket gör att du kan testa olika versioner av PHP från kommandoraden.

Det enklaste sättet att börja testa är att skapa en staging miljö eftersom detta kommer att likna din levande produktionsplats. I mykinsta-instrumentpanelen klickar du på din webbplats och ändrar miljön till staging.

Skapa WordPress staging miljö
Skapa WordPress staging miljö

Sedan under menyn” Verktyg ” ändra din PHP-motor över till PHP 7.4. Du kan sedan börja testa för att säkerställa kompatibiliteten hos din kod, tredjepartsinsticksprogram och teman.

Precis som i tidigare versioner av PHP har vår självläkande PHP-funktion fullt stöd för PHP 7.4. Om PHP av någon anledning går ner, kommer vi automatiskt att starta om det. Om omstarten inte löser problemet kommer vårt övervakningssystem att varna vårt sysadmin-team som undersöker orsaken till problemet.

Byt till PHP 7.4
Byt till PHP 7.4

Se detaljer om PHP 7.4 på Kinsta.

Installera och köra PHP 7.4 på Docker

Vill du testa på Docker? Lyckligtvis behöver du inte kompilera och konfigurera PHP 7.4 manuellt. Om du redan har Docker installerat på ditt system behöver du bara installera den inofficiella PHP-FPM 7.4 Docker Image och köra dina test från kommandoraden på några sekunder.

Installera Nginx Docker Image
Installera Nginx Docker Image

Om du föredrar att köra din PHP 7.4-kod i din webbläsare måste du också installera en Nginx eller Apache-image Men inga problem. Följ bara utvecklarens anvisningar. Kopiera och klistra in kommandona från Docker Image-sidan till ditt kommandoradsverktyg, och du är redo att sätta igång.

Sammanfattning

I det här inlägget täckte vi ett stort antal ändringar och tillägg som vi kan förvänta oss med utgåvan av PHP 7.4. Om du letar efter en fullständig lista över funktioner, tillsammans med den officiella RFC-dokumentationen, kolla in följande resurser:

Vi kommer att hålla dig uppdaterad med all den senaste informationen om PHP 7.4. Om du är en Kinsta-klient kan du redan börja flytta dina WordPress-webbplatser till den senaste versionen.

Är du redo att installera och testa de kommande PHP-funktionerna? Vilken är din favorit? Dela dina tankar med oss i kommentarerna nedan.

Carlo Daniele Kinsta

Carlo is a passionate lover of webdesign and front-end development. He has been playing with WordPress for more than 20 years, also in collaboration with Italian and European universities and educational institutions. He has written hundreds of articles and guides about WordPress, published both on Italian and international websites, as well as on printed magazines. You can find him on LinkedIn.