London, United Kingdom

(+44) 07788377460 [email protected]

PHP to Kotlin: A Developer’s Crash Course

Welcome to the “other side,” my friend. If you’re coming from PHP, you’re used to the “Wild West” (in the best way possible)—dynamic typing, shared-nothing architecture, and a “just make it work” philosophy.

Kotlin is going to feel like putting on a tailored suit. It’s structured, incredibly safe, and runs on the JVM (Java Virtual Machine). But don’t worry, it’s not the verbose Java of 2005. It’s modern, expressive, and honestly, a lot of fun.

Here is your survival guide for the PHP-to-Kotlin transition.

What Kotlin is (from a PHP brain)

Kotlin is:

  • A statically typed, null-safe language
  • Runs mainly on the JVM (Java ecosystem)
  • Concise like modern PHP, but stricter and safer
  • First-class citizen for Android, also great for backend (Spring), CLI tools, and more

If PHP feels like “pragmatic scripting that grew up,” Kotlin feels like “Java went to therapy.”

Static vs. Dynamic

  • Val vs. Var: Kotlin prefers immutability.
    • val is a constant (like const or a read-only property). Use this by default.
    • var is a mutable variable. Use this only if you must.
  • Type Inference: You don’t always have to declare the type, but once the compiler figures it out, it’s locked in.
val name = "Gemini" // The compiler knows this is a String
// name = "New Name" // Error! val cannot be reassigned

Variables & types

PHP

$name = "Alice";
$age = 30;

Kotlin

val name: String = "Alice"
var age: Int = 30

Key differences:

  • val = immutable (like final)
  • var = mutable
  • Types are usually inferred
val name = "Alice" // String inferred

Prefer val. Kotlin gently judges you when you overuse var.


Control flow is an expression

val status = if (age >= 18) "adult" else "minor"
when (status) {
    "active" -> println("Go")
    "paused" -> println("Wait")
    else -> println("Stop")
}

Say Goodbye to null Nightmares

You know the Fatal error: Uncaught Error: Call to a member function... on null? Kotlin virtually eliminates this with Null Safety.

In Kotlin, types are non-nullable by default. If a variable can be null, you must explicitly mark it with a ?.

FeaturePHPKotlin
Nullable Declaration?string $nameval name: String?
Safe Call$obj?->method()obj?.method()
Elvis Operator$name ?? 'Guest'name ?: "Guest"
// PHP
$user = findUser();
echo $user->name; // hope for the best
echo $user?->name; // null safe

// Kotlin
val user: User? = findUser()

That ? means nullable. You now have to be explicit:

println(user?.name)      // safe call
println(user!!.name)     // YOLO (throws if null)

Or properly handle it:

val name = user?.name ?: "Guest"

Functions: No More function Keyword

Kotlin makes programming… fun, right? Also, notice the parameter syntax: it’s name: Type, not Type $name.

// PHP
function greet(string $name): string {
    return "Hello, $name";
}

// Kotlin
fun greet(name: String): String {
    return "Hello, $name" // No semicolon required!
}

Pro tip: For simple functions, use Expression Body syntax:

// PHP
function add(int $a, int $b): int {
    return $a + $b;
}
fn add(int $a, int $b): int => $a + $b;

// Kotlin
fun add(a: Int, b: Int): Int {
    return a + b
}
fun add(a: Int, b: Int) = a + b

Classes and Attributes

PHP 8.x gave us Constructor Property Promotion, which was a huge win. Kotlin has had this since day one via Data Classes. This one feature replaces your boilerplate getters, setters, __toString(), and jsonSerialize().

class Car(var brand: String, var model: String, var year: Int) {
  fun name(): String {
    return "$brand $model ($year)".trimMargin()
  }
}

fun main() {
  val c1 = Car("Ford", "Mustang", 1969)
  val c2 = Car("BMW", "X5", 1999)
  val c3 = Car("Tesla", "Model S", 2020)

  var cars = arrayOf(c1.name(), c2.name(), c3.name())

  println("Car Shop:")
  println(cars.joinToString())
}

> Classes & constructor

// PHP
class User {
    public function __construct(
        public string $name,
        public int $age
    ) {}
}

// Kotlin
data class User(
    val name: String,
    val age: Int
)

That’s it. You automatically get:

  • constructor
  • getters
  • equals, hashCode
  • toString
  • copy()

> Properties (no getters/setters noise)

// PHP
$user->getName();
// Kotlin
user.name

Behind the scenes, getters/setters exist—but you don’t care. However, you can customise them:

var age: Int = 0
    set(value) {
        field = maxOf(value, 0)
    }

Collections: Beyond the Associative Array

In PHP, the array is the Swiss Army knife. In Kotlin, we are more specific. We distinguish between List, Set, and Map, and whether they are Mutable or Immutable.

  • listOf("A", "B") — Read-only.
  • mutableListOf("A", "B") — You can add/remove items.
  • mapOf("key" to "value") — This is your associative array equivalent.
// PHP
$names = array_map(fn ($u) => $u->name, $users);
// Kotlin
val names = users.map { it.name }

Common ones:

filter { }
map { }
firstOrNull()
any { }
all { }

it = implicit variable. Clean and expressive.


10. Exceptions

try {
    riskyCall()
} catch (e: Exception) {
    println(e.message)
}

11. Dependency management

PHP → Composer
Kotlin → Gradle (or Maven)

You’ll hate Gradle for a week. Then tolerate it forever.


“So Where is my index.php?”

This is the biggest hurdle. PHP follows a “request-response” lifecycle where everything dies after the script finishes. Kotlin applications (usually using frameworks like Spring Boot or Ktor) are long-lived processes.

  • Memory: Objects stay in memory between requests. You have to be mindful of state.
  • Concurrency: Instead of spinning up a new OS process for every request, Kotlin uses Coroutines—lightweight threads that handle thousands of concurrent tasks without breaking a sweat.

Mental model for a PHP dev

PHPKotlin
php index.php./gradlew run
Source = runtimeSource → compiled
No build stepBuild is mandatory
Deploy sourceDeploy artifacts (JAR)

Once you accept the build step, everything else gets calmer.

Android is special

On Android:

  • You never call kotlinc yourself
  • Android Studio + Gradle handles everything
  • Output becomes DEX, not a JAR

(Separate universe, same language.)


TL;DR

  • Real projects./gradlew build
  • Learning / tiny appskotlinc Main.kt -d app.jar
  • Runjava -jar app.jar
  • Kotlin always compiles before it runs

12. Kotlin vs PHP: quick gut comparison

ConceptPHPKotlin
TypingDynamicStatic
NullsRuntime painCompile-time enforced
OOPFlexibleStructured
VerbosityMediumLow
SafetyOptionalBuilt-in
IDE relianceHelpfulEssential

13. How to learn efficiently as a PHP dev

  1. Don’t learn Java first (tempting, unnecessary)
  2. Write small console apps
  3. Let the compiler annoy you—it’s teaching
  4. Read Kotlin code more than tutorials
  5. Embrace immutability early

Final thought

If PHP is a sharp multitool, Kotlin is a precision instrument. You trade a bit of freedom for a lot of confidence.

Once Kotlin “clicks,” going back to unchecked nulls feels… unsafe 😄


Your First “To-Do” List

  1. Install IntelliJ IDEA: It’s made by JetBrains (the same people who made Kotlin and PhpStorm). The integration is flawless.
  2. Try the Koans: Visit the Kotlin Koans for bite-sized coding challenges.
  3. Think in Expressions: In Kotlin, if and try are expressions—they return values.
    • val status = if (isUp) "Online" else "Offline"