php를 이용한 프로젝트에 투입되었으며 php의 OOP에 대한 적응을 위한 간단한 기능 구현을 하려함.
<?php
interface FileUploaderInterface {
public function handleFileUpload(): string;
public function isFileNotSelected(): bool;
public function isValidExtension(string $extension): bool;
public function isValidSize(int $size): bool;
public function moveUploadedFile(string $tmp_name, string $target_dir): bool;
}
interface MessageInterface {
public function showMessage(string $message, string $color): string;
}
class BaseMessage implements MessageInterface {
protected function wrapMessage(string $message, string $color): string {
return '<p style="color: ' . $color . ';">' . $message . '</p>';
}
public function showMessage(string $message, string $color): string {
return $this->wrapMessage($message, $color);
}
}
class ErrorMessage extends BaseMessage {
// No need to override showMessage() method as it is inherited from BaseMessage
}
class SuccessMessage extends BaseMessage {
// No need to override showMessage() method as it is inherited from BaseMessage
}
class CustomFileUploader implements FileUploaderInterface {
protected $allowedExtensions;
protected $uploadDirectory;
protected $errorMessage;
protected $successMessage;
public function __construct(array $allowedExtensions, string $uploadDirectory, MessageInterface $errorMessage, MessageInterface $successMessage) {
$this->allowedExtensions = $allowedExtensions;
$this->uploadDirectory = $uploadDirectory;
$this->errorMessage = $errorMessage;
$this->successMessage = $successMessage;
}
public function handleFileUpload(): string {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return '';
}
if ($this->isFileNotSelected()) {
return $this->errorMessage->showMessage('Please choose a file!', 'red');
}
$file = $_FILES['upload'];
$file_name = $file['name'];
$file_size = $file['size'];
$file_tmp_name = $file['tmp_name'];
$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
$file_ext = strtolower($file_ext);
if (!$this->isValidExtension($file_ext)) {
return $this->errorMessage->showMessage('Invalid file type!', 'red');
}
if (!$this->isValidSize($file_size)) {
return $this->errorMessage->showMessage('File too large!', 'red');
}
$target_dir = $this->uploadDirectory . '/' . $file_name;
if (!is_dir($this->uploadDirectory)) {
mkdir($this->uploadDirectory, 0755, true);
}
if ($this->moveUploadedFile($file_tmp_name, $target_dir)) {
return $this->successMessage->showMessage('File uploaded!', 'green');
} else {
return $this->errorMessage->showMessage('Failed to move the uploaded file!', 'red');
}
}
public function isFileNotSelected(): bool {
return empty($_FILES['upload']['name']);
}
public function isValidExtension(string $extension): bool {
return in_array($extension, $this->allowedExtensions);
}
public function isValidSize(int $size): bool {
$maxSize = 1000000;
return $size <= $maxSize;
}
public function moveUploadedFile(string $tmp_name, string $target_dir): bool {
return move_uploaded_file($tmp_name, $target_dir);
}
}
$allowedExtensions = ['png', 'jpg', 'jpeg', 'gif'];
$uploadDirectory = 'uploads';
$errorMessage = new ErrorMessage();
$successMessage = new SuccessMessage();
$fileUploader = new CustomFileUploader($allowedExtensions, $uploadDirectory, $errorMessage, $successMessage);
$message = $fileUploader->handleFileUpload();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload</title>
</head>
<body>
<form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name='upload'>
<input type="submit" value="Submit" name='submit'>
</form>
<?php if (isset($message)) echo $message; ?>
</body>
</html>
<?php
interface FileUploaderInterface {
public function handleFileUpload(): string;
public function isFileNotSelected(): bool;
public function isValidExtension(string $extension): bool;
public function isValidSize(int $size): bool;
public function moveUploadedFile(string $tmp_name, string $target_dir): bool;
}
FileUploaderInterface
라는 인터페이스를 정의하는 부분입니다. 이 인터페이스는 파일 업로드와 관련된 동작을 수행하기 위한 메서드를 선언합니다.handleFileUpload(): string
: 파일 업로드를 처리하는 메서드입니다. 이 메서드는 파일 업로드 과정을 수행하고, 결과에 대한 문자열을 반환합니다.
isFileNotSelected(): bool
: 파일이 선택되지 않았는지 확인하는 메서드입니다. 파일이 선택되지 않은 경우 true를 반환하고, 선택된 경우 false를 반환합니다.
isValidExtension(string $extension): bool
: 주어진 확장자가 유효한지 확인하는 메서드입니다. 매개변수로 확장자를 받아 해당 확장자가 유효한 경우 true를 반환하고, 그렇지 않은 경우 false를 반환합니다.
isValidSize(int $size): bool
: 주어진 파일 크기가 유효한지 확인하는 메서드입니다. 매개변수로 파일 크기를 받아 해당 크기가 유효한 경우 true를 반환하고, 그렇지 않은 경우 false를 반환합니다.
moveUploadedFile(string $tmp_name, string $target_dir): bool
: 업로드된 파일을 지정된 디렉토리로 이동하는 메서드입니다. 매개변수로 임시 파일 경로(target_dir)를 받아 파일을 이동하고, 이동이 성공한 경우 true를 반환하고, 실패한 경우 false를 반환합니다.
결론 : 이 인터페이스는 파일 업로드와 관련된 클래스에서 구현될 때, 각 메서드가 정확히 어떤 동작을 수행해야 하는지를 명시하고, 타입 힌트를 통해 메서드의 매개변수와 반환 타입을 명확히 지정할 수 있도록 도와줍니다.
interface
는 클래스가 구현해야 하는 메서드의 목록을 정의하는 역할
interface
키워드를 사용하여 정의공개적으로 선언되어야 합니다.
인터페이스는 다중 상속과 유사한 효과
를 제공합니다.interface Animal {
public function makeSound();
}
class Dog implements Animal {
public function makeSound() {
echo "Woof!";
}
}
class Cat implements Animal {
public function makeSound() {
echo "Meow!";
}
}
$dog = new Dog();
$dog->makeSound(); // 출력: Woof!
$cat = new Cat();
$cat->makeSound(); // 출력: Meow!
interface MessageInterface {
public function showMessage(string $message, string $color): string;
}
class BaseMessage implements MessageInterface {
protected function wrapMessage(string $message, string $color): string {
return '<p style="color: ' . $color . ';">' . $message . '</p>';
}
public function showMessage(string $message, string $color): string {
return $this->wrapMessage($message, $color);
}
}
class ErrorMessage extends BaseMessage {
// No need to override showMessage() method as it is inherited from BaseMessage
}
class SuccessMessage extends BaseMessage {
// No need to override showMessage() method as it is inherited from BaseMessage
}
MessageInterface
는 showMessage
라는 메서드를 가지는 인터페이스입니다. 이 인터페이스는 메시지와 컬러를 매개변수로 받아서 문자열로 변환하여 반환하는 기능을 정의합니다.
BaseMessage
는 MessageInterface
를 구현한 클래스
입니다. BaseMessage는 wrapMessage라는 보호된 메서드를 가지고 있습니다. 이 메서드는 메시지와 컬러를 매개변수로 받아서 특정 형식으로 래핑된 문자열을 반환합니다. BaseMessage는 또한 MessageInterface의 showMessage 메서드를 구현하며, 내부적으로 wrapMessage 메서드를 호출하여 변환된 문자열을 반환합니다.
ErrorMessage
는 BaseMessage를 상속한 클래스입니다. ErrorMessage는 BaseMessage에서 상속받은 showMessage 메서드를 그대로 사용하며, 추가적인 메서드를 구현하지 않습니다.
SuccessMessage
도 BaseMessage를 상속한 클래스로, BaseMessage에서 상속받은 showMessage 메서드를 그대로 사용합니다.
이렇게 구현된 클래스들을 사용하면 메시지와 컬러를 전달하여 특정 형식으로 래핑된 메시지를 얻을 수 있습니다.
PHP에서는 protected
, public
, private
외에도 final
과 static
을 포함한 몇 가지 가시성 및 특성 키워드를 제공합니다.
protected:
protected 키워드는 해당 멤버(프로퍼티 또는 메서드)가 정의된 클래스 내부 및 해당 클래스를 상속받은 자식 클래스 내부에서 접근할 수 있음
을 나타냅니다.
public: public
키워드는 해당 멤버가 어디에서나 접근
할 수 있음을 나타냅니다. 즉, 클래스 내부
, 자식 클래스
, 클래스 인스턴스
등 어디서든
접근 가능합니다.
private
: private 키워드는 해당 멤버가 정의된 클래스 내부에서만
접근할 수 있음을 나타냅니다. 자식 클래스나 클래스 인스턴스에서는 접근할 수 없습니다.
final:
final 키워드는 클래스를 확장(상속)할 수 없음
을 나타냅니다. final로 선언된 클래스는 더 이상 상속할 수 없으며, 메서드를 final로 선언하면 해당 메서드를 오버라이딩할 수 없습니다.
static:
static 키워드는 클래스 레벨에 속하는 멤버(프로퍼티 또는 메서드)를 나타냅니다. static 멤버는 클래스 인스턴스를 생성하지 않고도 호출할 수 있으며, 인스턴스 간에 공유됩니다.
class CustomFileUploader implements FileUploaderInterface {
protected $allowedExtensions;
protected $uploadDirectory;
protected $errorMessage;
protected $successMessage;
public function __construct(array $allowedExtensions, string $uploadDirectory, MessageInterface $errorMessage, MessageInterface $successMessage) {
$this->allowedExtensions = $allowedExtensions;
$this->uploadDirectory = $uploadDirectory;
$this->errorMessage = $errorMessage;
$this->successMessage = $successMessage;
}
위의 코드는 CustomFileUploader 클래스의 생성자에 두 개의 인터페이스 형식의 매개변수 errorMessage와 successMessage가 추가되었습니다. 이러한 매개변수를 통해 ErrorMessage 및 SuccessMessage와 같은 메시지 클래스의 인스턴스를 주입할 수 있습니다.
기존에는 CustomFileUploader 클래스 내에서 ErrorMessage와 SuccessMessage를 직접 생성했지만, 이제는 외부에서 이러한 메시지 클래스의 인스턴스를 생성한 후에 CustomFileUploader의 생성자를 통해 주입합니다. 이는 의존성 주입(Dependency Injection) 패턴을 사용하여 클래스 간의 결합도를 낮추고 유연성을 높이는 방식입니다.
이렇게 함으로써, CustomFileUploader 클래스는 어떤 종류의 메시지 클래스도 사용할 수 있게 되며, 새로운 메시지 클래스를 만들어서 주입하는 것도 가능합니다. 이는 코드의 확장성과 유지보수성을 향상시키는 데 도움이 됩니다.
생성자의 시그니처를 변경함으로써, 이제 CustomFileUploader 클래스를 인스턴스화할 때 메시지 클래스의 인스턴스를 제공해야 합니다. 예를 들어:
$allowedExtensions = ['png', 'jpg', 'jpeg', 'gif'];
$uploadDirectory = 'uploads';
$errorMessage = new ErrorMessage();
$successMessage = new SuccessMessage();
$fileUploader = new CustomFileUploader($allowedExtensions, $uploadDirectory, $errorMessage, $successMessage);
public function handleFileUpload(): string {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return '';
}
if ($this->isFileNotSelected()) {
return $this->errorMessage->showMessage('Please choose a file!', 'red');
}
$file = $_FILES['upload'];
$file_name = $file['name'];
$file_size = $file['size'];
$file_tmp_name = $file['tmp_name'];
$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
$file_ext = strtolower($file_ext);
if (!$this->isValidExtension($file_ext)) {
return $this->errorMessage->showMessage('Invalid file type!', 'red');
}
if (!$this->isValidSize($file_size)) {
return $this->errorMessage->showMessage('File too large!', 'red');
}
$target_dir = $this->uploadDirectory . '/' . $file_name;
if (!is_dir($this->uploadDirectory)) {
mkdir($this->uploadDirectory, 0755, true);
}
if ($this->moveUploadedFile($file_tmp_name, $target_dir)) {
return $this->successMessage->showMessage('File uploaded!', 'green');
} else {
return $this->errorMessage->showMessage('Failed to move the uploaded file!', 'red');
}
}
코드의 실행 흐름은 다음과 같습니다:
$_SERVER['REQUEST_METHOD']
값을 확인하여 현재 요청이 POST
메서드인지 확인합니다. 만약 POST 메서드가 아니라면 빈 문자열을 반환하고 메서드 실행을 종료합니다.
파일이 선택되지 않았는지 확인하기 위해 $this->isFileNotSelected()
메서드를 호출합니다. 파일이 선택되지 않았다면 'Please choose a file!' 메시지와 'red' 색상을 사용하여 $this->errorMessage
객체
의 showMessage() 메서드
를 호출
하고 해당 결과를 반환
합니다.
선택된 파일이 있다면, 파일의 정보를 변수에 할당합니다. 파일 이름은 $file_name
, 파일 크기는 $file_size
, 임시 파일 경로는 $file_tmp_name
에 저장됩니다.
파일 이름으로부터 확장자를 추출
하기 위해 pathinfo()
함수를 사용하고, 추출된 확장자를 소문자로 변환
합니다.
추출된 확장자가 유효한지 확인하기 위해 $this->isValidExtension()
메서드를 호출
합니다. 유효하지 않은 경우 'Invalid file type!' 메시지와 'red' 색상을 사용하여 $this->errorMessage 객체의 showMessage() 메서드를 호출
하고 해당 결과를 반환합니다.
파일 크기가 유효한지 확인하기 위해 $this->isValidSize()
메서드를 호출
합니다. 유효하지 않은 경우 'File too large!' 메시지와 'red' 색상을 사용하여 $this->errorMessage 객체
의 showMessage()
메서드를 호출하고 해당 결과를 반환합니다.
업로드된 파일을 저장하기 위한 대상 디렉토리 경로인 $target_dir
을 생성합니다. 대상 디렉토리가 존재하지 않는 경우에는 mkdir() 함수
를 사용하여 디렉토리를 생성
합니다.
$this->moveUploadedFile()
메서드를 호출하여 업로드된 파일을 이동시킵니다. 이동에 성공한 경우 'File uploaded!' 메시지와 'green' 색상을 사용하여 $this->successMessage 객체
의 showMessage()
메서드를 호출하고 해당 결과를 반환
합니다.
이동에 실패한 경우 'Failed to move the uploaded file!' 메시지와 'red' 색상을 사용하여 $this->errorMessage 객체
의 showMessage() 메서드를 호출
하고 해당 결과를 반환합니다.
결론 : 이렇게하여 handleFileUpload()
메서드는 파일 업로드 처리 후 결과에 따라 적절한 메시지를 반환
합니다. 이 메서드는 errorMessage와 successMessage 객체를 사용하여 에러 메시지
와 성공 메시지를 생성
하며, 이전에 주입된 객체들과 협력하여 동작
합니다.
php의 built-in으로 제공되는 복합 데이터 타입은?
// 인덱스 배열
$numbers = [1, 2, 3, 4, 5];
// 연관 배열
$person = [
'name' => 'John',
'age' => 30,
'email' => 'john@example.com'
];
class Person {
public $name;
public $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
public function greet() {
echo "Hello, my name is " . $this->name . " and I'm " . $this->age . " years old.";
}
}
$person = new Person("John", 30);
$person->greet();
// 파일 핸들링 예시
$file = fopen("example.txt", "r");
// 파일 핸들 $file을 리소스로 표현
// 데이터베이스 연결 예시
$connection = mysqli_connect("localhost", "username", "password", "database");
// 데이터베이스 연결 리소스 $connection
// 함수 참조
$functionRef = 'strlen';
echo $functionRef("Hello"); // 문자열 길이 반환
// 익명 함수
$anonymousFunc = function($x, $y) {
return $x + $y;
};
echo $anonymousFunc(5, 3); // 8 반환
// 클래스의 정적 메서드
class Math {
public static function add($x, $y) {
return $x + $y;
}
}
$methodRef = [Math::class, 'add'];
echo $methodRef(4, 2); // 6 반환
// 배열을 반복 가능한 타입으로 사용
$numbers = [1, 2, 3, 4, 5];
foreach ($numbers as $number) {
echo $number . " ";
}
// 객체를 반복 가능한 타입으로 사용
class MyIterator implements Iterator {
private $position = 0;
private $data = ['A', 'B', 'C'];
public function rewind() {
$this->position = 0;
}
public function current() {
return $this->data[$this->position];
}
public function key() {
return $this->position;
}
public function next() {
++$this->position;
}
public function valid() {
return isset($this->data[$this->position]);
}
}
$myIterator = new MyIterator();
foreach ($myIterator as $key => $value) {
echo $key . ": " . $value . " ";
}
public function isFileNotSelected(): bool {
return empty($_FILES['upload']['name']);
}
isFileNotSelected
메서드는 현재 업로드된 파일이 선택되지 않은 경우를 확인하는 함수입니다.
해당 메서드는 $_FILES['upload']['name']
값을 확인하여 파일 이름이 비어있는지를 검사합니다.
$_FILES['upload']
는 PHP의 슈퍼글로벌 변수 중 하나로, 파일 업로드 시에 전송된 파일에 대한 정보를 담고 있습니다.
'name'
은 업로드된 파일의 원본 이름을 나타냅니다.
empty($_FILES['upload']['name'])
은 $_FILES['upload']['name']
값이 비어있으면 true
를 반환하고, 그렇지 않으면 false
를 반환합니다.
따라서, isFileNotSelected
메서드는 업로드된 파일이 선택되지 않은 경우 true
를 반환하고, 선택된 경우에는 false
를 반환합니다.
public function isValidExtension(string $extension): bool {
return in_array($extension, $this->allowedExtensions);
}
isValidExtension
메서드는 주어진 파일 확장자가 허용된 확장자 목록에 포함되어 있는지를 확인하는 함수입니다.
해당 메서드는 $extension 매개변수와 $this->allowedExtensions 속성을 비교하여 주어진 확장자가 허용된 확장자인지를 판별합니다.
$extension
은 확인할 파일의 확장자를 나타냅니다.
$this->allowedExtensions
는 $this 객체의 allowedExtensions 속성으로, 허용된 확장자의 배열을 나타냅니다.
in_array($extension, $this->allowedExtensions)
은 $extension
값이 $this->allowedExtensions
배열에 포함되어 있는지를 확인합니다.
in_array()
함수는 주어진 값이 배열에 존재하는지를 확인하고, 존재할 경우 true
를 반환하고, 그렇지 않을 경우 false
를 반환합니다.
따라서, isValidExtension
메서드는 주어진 확장자가 허용된 확장자 목록에 포함되어 있는 경우 true를 반환하고, 포함되지 않은 경우에는 false를 반환합니다.
public function isValidSize(int $size): bool {
$maxSize = 1000000;
return $size <= $maxSize;
}
isValidSize 메서드는 주어진 파일 크기가 유효한 크기인지를 확인하는 역할을 합니다.
매개변수로 받은 $size를 $maxSize와 비교하여 유효한 크기인지를 판단합니다. 여기서 $maxSize는 1000000로 설정되어 있습니다.
함수는 주어진 파일 크기 $size가 $maxSize 이하인 경우 true를 반환하고, 그렇지 않은 경우에는 false를 반환합니다. 이를 통해 파일 크기가 허용 범위 내에 있는지를 확인할 수 있습니다.
public function moveUploadedFile(string $tmp_name, string $target_dir): bool {
return move_uploaded_file($tmp_name, $target_dir);
}
moveUploadedFile()
함수는 업로드된 파일
을 지정된 대상 디렉토리
로 이동시키는 역할
을 합니다. 이 함수는 move_uploaded_file() 내장 함수
를 호출
하여 파일 이동을 수행합니다.
함수는 두 개
의 매개변수
를 받습니다. 첫 번째 매개변수인 $tmp_name
은 업로드된 파일의 임시 경로
를 나타내며, 두 번째 매개변수인 $target_dir
은 파일이 이동될 대상 디렉토리
를 나타냅니다.
move_uploaded_file($tmp_name, $target_dir)
함수는 업로드된 파일을 임시 경로
에서 대상 디렉토리로 이동
시킵니다. 이 과정에서 파일의 권한과 소유자도 유지
됩니다. 함수는 파일 이동에 성공하면 true를 반환하고, 파일 이동에 실패하면 false를 반환합니다.
이 코드에서는 move_uploaded_file() 함수의 반환 값을 그대로 반환하므로, 파일 이동에 성공했는지 여부를 호출한 곳에서 확인할 수 있습니다.