Functions
Functions เป็นบล็อกของโค้ดที่ทำงานเฉพาะอย่าง สามารถเรียกใช้ซ้ำได้ ในบทนี้เราจะเรียนรู้การสร้างและใช้งาน functions ใน PHP 8.4+
การสร้าง Function
Section titled “การสร้าง Function”<?php// Function พื้นฐานfunction sayHello() { echo "Hello, World!";}
sayHello(); // "Hello, World!"
// Function พร้อม return valuefunction getGreeting() { return "Hello!";}
$message = getGreeting();echo $message; // "Hello!"
// Function พร้อม parametersfunction greet($name) { return "Hello, $name!";}
echo greet("John"); // "Hello, John!"
// หลาย parametersfunction add($a, $b) { return $a + $b;}
echo add(5, 3); // 8Function Naming Rules
Section titled “Function Naming Rules”<?php// ชื่อ function ที่ถูกต้องfunction my_function() {} // snake_casefunction myFunction() {} // camelCase (แนะนำ)function _privateFunction() {} // ขึ้นต้นด้วย _function function123() {} // มีตัวเลขได้
// ชื่อที่ผิด// function 123function() {} // ขึ้นต้นด้วยตัวเลขไม่ได้// function my-function() {} // ใช้ - ไม่ได้
// function names เป็น case-insensitivefunction SayHi() { echo "Hi!";}sayhi(); // ทำงานได้ (แต่ไม่แนะนำ)SAYHI(); // ทำงานได้Parameters และ Arguments
Section titled “Parameters และ Arguments”Required Parameters
Section titled “Required Parameters”<?phpfunction divide($a, $b) { return $a / $b;}
echo divide(10, 2); // 5// divide(10); // Error: Too few argumentsDefault Values
Section titled “Default Values”<?phpfunction greet($name, $greeting = "Hello") { return "$greeting, $name!";}
echo greet("John"); // "Hello, John!"echo greet("John", "Hi"); // "Hi, John!"echo greet("John", "Welcome"); // "Welcome, John!"
// Default values ต้องอยู่หลัง required parameters// ❌ ผิด// function wrong($a = 1, $b) {} // Deprecated ใน PHP 8.0+
// ✅ ถูกfunction correct($b, $a = 1) {}Nullable และ Optional Types
Section titled “Nullable และ Optional Types”<?php// PHP 8.0+: Nullable typesfunction findUser(?int $id): ?array { if ($id === null) { return null; } return ["id" => $id, "name" => "User $id"];}
findUser(1); // ["id" => 1, "name" => "User 1"]findUser(null); // null
// Optional parameters (มี default)function search(string $query, int $limit = 10): array { // ค้นหา... return [];}
search("php"); // limit = 10search("php", 20); // limit = 20Named Arguments (PHP 8.0+)
Section titled “Named Arguments (PHP 8.0+)”<?phpfunction createUser( string $name, string $email, int $age = 18, bool $isActive = true, ?string $avatar = null) { return compact('name', 'email', 'age', 'isActive', 'avatar');}
// Positional arguments (วิธีเดิม)$user = createUser("John", "john@example.com", 25, true, "avatar.jpg");
// Named arguments (PHP 8.0+)$user = createUser( name: "John", email: "john@example.com", age: 25, isActive: true, avatar: "avatar.jpg");
// ข้าม default parameters ได้$user = createUser( name: "Jane", email: "jane@example.com", avatar: "jane.jpg" // ข้าม age และ isActive);
// สลับ order ได้$user = createUser( email: "bob@example.com", name: "Bob");
// ผสม positional และ named (positional ต้องมาก่อน)$user = createUser( "Alice", // positional email: "alice@example.com" // named);Variadic Parameters (…)
Section titled “Variadic Parameters (…)”<?php// รับ arguments ไม่จำกัดจำนวนfunction sum(...$numbers) { return array_sum($numbers);}
echo sum(1, 2, 3); // 6echo sum(1, 2, 3, 4, 5); // 15echo sum(); // 0
// พร้อม type hintfunction sumIntegers(int ...$numbers): int { return array_sum($numbers);}
// Variadic ต้องเป็น parameter สุดท้ายfunction format(string $template, mixed ...$values): string { return sprintf($template, ...$values);}
echo format("Name: %s, Age: %d", "John", 25);// "Name: John, Age: 25"
// Spread operator (กลับด้าน)$numbers = [1, 2, 3, 4, 5];echo sum(...$numbers); // 15
$args = ["John", 25];echo format("Name: %s, Age: %d", ...$args);Return Types
Section titled “Return Types”Basic Return Types
Section titled “Basic Return Types”<?php// Return type declarationfunction getAge(): int { return 25;}
function getName(): string { return "John";}
function isActive(): bool { return true;}
function getScores(): array { return [85, 90, 78];}
// Nullable returnfunction findById(int $id): ?string { return $id > 0 ? "User $id" : null;}Union Types (PHP 8.0+)
Section titled “Union Types (PHP 8.0+)”<?phpfunction parse(string $input): int|float { return is_numeric($input) ? (strpos($input, '.') !== false ? (float)$input : (int)$input) : 0;}
echo parse("42"); // int(42)echo parse("3.14"); // float(3.14)void และ never
Section titled “void และ never”<?php// void - ไม่ return อะไรfunction logMessage(string $message): void { echo "[LOG] $message\n"; // return; // OK (implicit void) // return null; // Error!}
// never - ไม่ return (exit, throw, หรือ loop forever)function redirect(string $url): never { header("Location: $url"); exit;}
function throwError(string $message): never { throw new RuntimeException($message);}mixed และ static
Section titled “mixed และ static”<?php// mixed - ยอมรับทุก type (PHP 8.0+)function log(mixed $data): void { print_r($data);}
// static - return instance ของ class ปัจจุบัน (late binding)class Builder { public static function create(): static { return new static(); }}
// self vs staticclass ParentClass { public static function createSelf(): self { return new self(); }
public static function createStatic(): static { return new static(); }}
class ChildClass extends ParentClass {}
ChildClass::createSelf(); // ParentClass instanceChildClass::createStatic(); // ChildClass instanceStrict Types
Section titled “Strict Types”PHP สามารถบังคับ strict type checking:
<?php// ไม่มี strict types (default)function addNumbers(int $a, int $b): int { return $a + $b;}
echo addNumbers("5", "3"); // 8 (strings ถูกแปลงเป็น int)
// เปิด strict types (ต้องอยู่บรรทัดแรก)declare(strict_types=1);
function addNumbersStrict(int $a, int $b): int { return $a + $b;}
echo addNumbersStrict(5, 3); // 8// echo addNumbersStrict("5", "3"); // TypeError!Variable Scope
Section titled “Variable Scope”Local Scope
Section titled “Local Scope”<?phpfunction myFunction() { $localVar = "I'm local"; echo $localVar; // OK}
myFunction();// echo $localVar; // Error: undefined variableGlobal Scope
Section titled “Global Scope”<?php$globalVar = "I'm global";
function myFunction() { // ต้องใช้ global keyword global $globalVar; echo $globalVar; // "I'm global"
// หรือใช้ $GLOBALS echo $GLOBALS['globalVar']; // "I'm global"}
myFunction();
// ❌ ไม่แนะนำให้ใช้ global มาก// ✅ ส่งผ่าน parameter แทนfunction betterFunction(string $value) { return $value;}Static Variables
Section titled “Static Variables”<?phpfunction counter() { static $count = 0; // เก็บค่าระหว่างการเรียก return ++$count;}
echo counter(); // 1echo counter(); // 2echo counter(); // 3
// ใช้สำหรับ cachingfunction fibonacci(int $n): int { static $cache = [];
if ($n <= 1) return $n;
if (!isset($cache[$n])) { $cache[$n] = fibonacci($n - 1) + fibonacci($n - 2); }
return $cache[$n];}Anonymous Functions (Closures)
Section titled “Anonymous Functions (Closures)”Basic Closures
Section titled “Basic Closures”<?php// Anonymous function$greet = function($name) { return "Hello, $name!";};
echo $greet("John"); // "Hello, John!"
// ใช้เป็น callback$numbers = [1, 2, 3, 4, 5];$doubled = array_map(function($n) { return $n * 2;}, $numbers);// [2, 4, 6, 8, 10]
// ใช้กับ usort$users = [ ["name" => "Charlie", "age" => 30], ["name" => "Alice", "age" => 25], ["name" => "Bob", "age" => 35],];
usort($users, function($a, $b) { return $a["age"] <=> $b["age"];});use Keyword
Section titled “use Keyword”<?php$prefix = "Mr.";
// ใช้ use เพื่อเข้าถึงตัวแปรจาก parent scope$greet = function($name) use ($prefix) { return "$prefix $name";};
echo $greet("John"); // "Mr. John"
// ต้องการแก้ไขตัวแปร ใช้ &$counter = 0;$increment = function() use (&$counter) { $counter++;};
$increment();$increment();echo $counter; // 2
// Closure ใน loop$functions = [];for ($i = 0; $i < 3; $i++) { $functions[] = function() use ($i) { return $i; };}
echo $functions[0](); // 0echo $functions[1](); // 1echo $functions[2](); // 2Arrow Functions (PHP 7.4+)
Section titled “Arrow Functions (PHP 7.4+)”Arrow functions เป็น syntax สั้นสำหรับ closures:
<?php// Closure แบบเดิม$double = function($n) { return $n * 2;};
// Arrow function (PHP 7.4+)$double = fn($n) => $n * 2;
echo $double(5); // 10
// Arrow function inherit scope โดยอัตโนมัติ (ไม่ต้อง use)$multiplier = 3;$multiply = fn($n) => $n * $multiplier;echo $multiply(4); // 12
// ใช้กับ array functions$numbers = [1, 2, 3, 4, 5];
$doubled = array_map(fn($n) => $n * 2, $numbers);$evens = array_filter($numbers, fn($n) => $n % 2 === 0);$sum = array_reduce($numbers, fn($acc, $n) => $acc + $n, 0);
// พร้อม type hints$format = fn(int $n): string => "Number: $n";
// Multi-line (ต้องใช้ closure แบบเต็ม)// Arrow function รองรับแค่ single expression$process = function($data) { $processed = transform($data); validate($processed); return $processed;};เปรียบเทียบ Closure vs Arrow Function
Section titled “เปรียบเทียบ Closure vs Arrow Function”| Feature | Closure | Arrow Function |
|---|---|---|
| Syntax | function($x) { return $x; } | fn($x) → $x |
| Multi-line | ✅ ได้ | ❌ ไม่ได้ |
| Implicit return | ❌ ต้อง return | ✅ อัตโนมัติ |
| use keyword | ✅ ต้องใช้ | ❌ ไม่ต้อง (auto) |
| Modify outer vars | ✅ use (&$var) | ❌ ไม่ได้ |
First-Class Callable (PHP 8.1+)
Section titled “First-Class Callable (PHP 8.1+)”<?php// สร้าง Closure จาก function/methodfunction multiply(int $a, int $b): int { return $a * $b;}
// PHP 8.1+: First-class callable syntax$callable = multiply(...); // Closure from function
echo $callable(3, 4); // 12
// ใช้กับ methodsclass Calculator { public function add(int $a, int $b): int { return $a + $b; }
public static function subtract(int $a, int $b): int { return $a - $b; }}
$calc = new Calculator();$addMethod = $calc->add(...);echo $addMethod(5, 3); // 8
$subtractMethod = Calculator::subtract(...);echo $subtractMethod(10, 4); // 6
// ส่งเป็น callback$numbers = [1, 2, 3, 4, 5];$results = array_map($calc->add(...), $numbers, $numbers);// [2, 4, 6, 8, 10]Recursion
Section titled “Recursion”<?php// Factorialfunction factorial(int $n): int { if ($n <= 1) { return 1; // Base case } return $n * factorial($n - 1); // Recursive case}
echo factorial(5); // 120 (5 * 4 * 3 * 2 * 1)
// Fibonacci with memoizationfunction fibonacci(int $n, array &$memo = []): int { if ($n <= 1) return $n;
if (!isset($memo[$n])) { $memo[$n] = fibonacci($n - 1, $memo) + fibonacci($n - 2, $memo); }
return $memo[$n];}
echo fibonacci(10); // 55
// Flatten nested arrayfunction flatten(array $array): array { $result = []; foreach ($array as $item) { if (is_array($item)) { $result = [...$result, ...flatten($item)]; } else { $result[] = $item; } } return $result;}
echo json_encode(flatten([1, [2, 3], [[4, 5], 6]]));// [1,2,3,4,5,6]Higher-Order Functions
Section titled “Higher-Order Functions”Functions ที่รับหรือ return functions อื่น:
<?php// Function ที่รับ function เป็น parameterfunction applyTwice(callable $func, $value) { return $func($func($value));}
$double = fn($n) => $n * 2;echo applyTwice($double, 5); // 20 (5 * 2 * 2)
// Function ที่ return functionfunction multiplier(int $factor): callable { return fn($n) => $n * $factor;}
$triple = multiplier(3);$quadruple = multiplier(4);
echo $triple(10); // 30echo $quadruple(10); // 40
// Curry functionfunction curry(callable $func): callable { $reflection = new ReflectionFunction($func); $numParams = $reflection->getNumberOfParameters();
$curried = function(...$args) use ($func, $numParams, &$curried) { if (count($args) >= $numParams) { return $func(...$args); } return function(...$more) use ($args, $curried) { return $curried(...$args, ...$more); }; };
return $curried;}
$add = curry(fn($a, $b, $c) => $a + $b + $c);echo $add(1)(2)(3); // 6echo $add(1, 2)(3); // 6echo $add(1, 2, 3); // 6Built-in Functions
Section titled “Built-in Functions”PHP มี functions ในตัวมากมาย:
<?php// String functionsstrlen("hello"); // 5strtoupper("hello"); // "HELLO"substr("hello", 0, 3); // "hel"str_replace("l", "L", "hello"); // "heLLo"
// Array functionscount([1, 2, 3]); // 3array_sum([1, 2, 3]); // 6array_map(fn($n) => $n * 2, [1, 2, 3]); // [2, 4, 6]array_filter([1, 2, 3], fn($n) => $n > 1); // [2, 3]
// Math functionsabs(-5); // 5ceil(4.3); // 5floor(4.9); // 4round(4.5); // 5max(1, 2, 3); // 3min(1, 2, 3); // 1pow(2, 3); // 8sqrt(16); // 4
// Date/Timedate("Y-m-d"); // "2024-01-15"time(); // 1705312800 (timestamp)strtotime("+1 week"); // timestamp ของสัปดาห์หน้า
// Type functionsgettype($var); // "string", "integer", etc.is_string($var); // true/falseis_array($var); // true/falseisset($var); // true/falseempty($var); // true/falseแบบฝึกหัด
Section titled “แบบฝึกหัด”แบบฝึกหัดที่ 1: Compose Functions
Section titled “แบบฝึกหัดที่ 1: Compose Functions”<?phpfunction compose(callable ...$funcs): callable { return function($value) use ($funcs) { return array_reduce( array_reverse($funcs), fn($acc, $func) => $func($acc), $value ); };}
// ใช้งาน$double = fn($n) => $n * 2;$addOne = fn($n) => $n + 1;$square = fn($n) => $n ** 2;
$composed = compose($double, $addOne, $square);echo $composed(3); // ((3^2) + 1) * 2 = 20แบบฝึกหัดที่ 2: Memoize Function
Section titled “แบบฝึกหัดที่ 2: Memoize Function”<?phpfunction memoize(callable $func): callable { $cache = [];
return function(...$args) use ($func, &$cache) { $key = serialize($args);
if (!isset($cache[$key])) { $cache[$key] = $func(...$args); }
return $cache[$key]; };}
// ใช้งาน$expensiveCalculation = memoize(function($n) { echo "Calculating $n...\n"; return $n * 2;});
echo $expensiveCalculation(5); // "Calculating 5..." → 10echo $expensiveCalculation(5); // 10 (from cache, no "Calculating")echo $expensiveCalculation(10); // "Calculating 10..." → 20แบบฝึกหัดที่ 3: Pipe Function
Section titled “แบบฝึกหัดที่ 3: Pipe Function”<?phpfunction pipe(mixed $value, callable ...$funcs): mixed { return array_reduce( $funcs, fn($acc, $func) => $func($acc), $value );}
// ใช้งาน$result = pipe( " Hello World ", fn($s) => trim($s), fn($s) => strtolower($s), fn($s) => str_replace(" ", "-", $s));
echo $result; // "hello-world"ในบทนี้เราได้เรียนรู้:
- การสร้าง functions และ naming conventions
- Parameters: required, default, nullable, variadic
- Named arguments (PHP 8.0+)
- Return types และ strict types
- Variable scope: local, global, static
- Anonymous functions และ closures
- Arrow functions (PHP 7.4+)
- First-class callables (PHP 8.1+)
- Recursion และ higher-order functions
ในบทถัดไปเราจะเรียนรู้เกี่ยวกับ Arrays ใน PHP อย่างละเอียด
เข้าสู่ระบบเพื่อดูเนื้อหาเต็ม
ยืนยันตัวตนด้วยบัญชี Google เพื่อปลดล็อกบทความทั้งหมด
Login with Google