>백엔드 개발 >PHP 튜토리얼 >PHP Yii Framework_php 스킬의 속성(Property)에 대한 심층 설명

PHP Yii Framework_php 스킬의 속성(Property)에 대한 심층 설명

WBOY
WBOY원래의
2016-05-16 19:56:281051검색

PHP에서는 클래스의 멤버 변수를 속성이라고도 합니다. 이는 클래스 정의의 일부이며 인스턴스의 상태를 나타내는 데 사용됩니다(즉, 클래스의 다른 인스턴스를 구별하기 위해). 특정 실습에서는 속성을 읽고 쓰기 위해 약간 특별한 방법을 사용하려는 경우가 많습니다. 예를 들어, label 속성에 대해 매번 트림 작업을 수행해야 하는 경우 다음 코드를 사용하여 이를 수행할 수 있습니다.

$object->label = trim($label);

위 코드의 단점은 label 속성이 수정될 때마다 Trim() 함수를 다시 호출해야 한다는 것입니다. 앞으로 첫 글자를 대문자로 표기하는 등 label 속성을 다른 방식으로 처리해야 한다면 label 속성에 값을 할당하는 코드를 모두 수정해야 할 것입니다. 이러한 코드 중복은 버그로 이어질 수 있으므로 가능하면 이러한 관행을 피해야 합니다.

이 문제를 해결하기 위해 Yii는 클래스 내 getter 및 setter(리더 및 세터) 메서드를 기반으로 속성 정의를 지원하는 yiibaseObject라는 기본 클래스를 도입합니다. 클래스가 이 기능을 지원해야 하는 경우 yiibaseObject 또는 해당 하위 클래스만 상속하면 됩니다.

보충: Yii 프레임워크의 거의 모든 핵심 클래스는 yiibaseObject 또는 해당 하위 클래스에서 상속됩니다. 즉, 핵심 클래스에서 getter 또는 setter 메서드를 볼 때마다 이를 속성처럼 호출할 수 있습니다.
Getter 메서드는 이름이 get으로 시작하는 메서드이고, setter 메서드 이름은 set으로 시작하는 메서드입니다. 메소드 이름에서 get 또는 set 뒤의 부분이 속성의 이름을 정의합니다. 다음 코드에서 볼 수 있듯이 getter 메서드 getLabel() 및 setter 메서드 setLabel()은 label 속성에 대해 작동합니다.

namespace app\components;

use yii\base\Object;

class Foo extend Object
{
  private $_label;

  public function getLabel()
  {
    return $this->_label;
  }

  public function setLabel($value)
  {
    $this->_label = trim($value);
  }
}

(설명: getter 및 setter 메소드는 label이라는 속성을 생성합니다. 이 경우에는 개인 내부 속성인 _label을 가리킵니다.)

getter/setter로 정의된 속성은 클래스 멤버 변수와 동일한 방식으로 사용됩니다. 둘 사이의 주요 차이점은 이 속성을 읽을 때 해당 getter 메서드가 호출되고 속성에 값이 할당되면 해당 setter 메서드가 호출된다는 것입니다. 예:

// 等效于 $label = $object->getLabel();
$label = $object->label;

// 等效于 $object->setLabel('abc');
$object->label = 'abc';

getter만 정의하고 setter는 정의하지 않는 속성은 읽기 전용 속성입니다. 이러한 속성에 할당을 시도하면 yiibaseInvalidCallException(잘못된 호출) 예외가 발생합니다. 마찬가지로, getter 메서드 없이 setter 메서드만 사용하여 정의된 속성은 쓰기 전용 속성이며, 이러한 속성을 읽으려고 하면 예외가 발생합니다. 쓰기 전용 속성을 사용하는 경우는 거의 없습니다.

getter 및 setter를 통해 정의된 속성에는 몇 가지 특별한 규칙과 제한 사항도 있습니다.

이러한 속성의 이름은 대소문자를 구분하지 않습니다. 예를 들어 $object->label과 $object->Label은 동일한 속성입니다. PHP 메소드 이름은 대소문자를 구분하지 않기 때문입니다.
그러한 속성의 이름이 클래스 멤버 변수의 이름과 동일하면 후자가 우선합니다. 예를 들어, 위의 Foo 클래스에 label 멤버 변수가 있고 $object->label = 'abc'에 값을 할당하면 setter setLabel() 메서드 대신 멤버 변수에 할당된다고 가정합니다.
이 유형의 속성에는 가시성(액세스 제한)이 지원되지 않습니다. 속성의 getter 및 setter 메서드가 공개, 보호 또는 비공개인지 여부는 속성의 가시성에 영향을 주지 않습니다.
이러한 속성의 getter 및 setter 메서드는 비정적으로만 정의할 수 있습니다. 정적 메서드(정적)로 정의하면 동일한 방식으로 처리되지 않습니다.
처음에 언급한 질문으로 돌아가면, 이제 모든 곳에서 Trim() 함수를 호출하는 대신 setter setLabel() 메서드 내에서 한 번만 호출하면 됩니다. 레이블의 첫 글자를 대문자로 써야 하는 새로운 요구 사항이 생기면 다른 코드를 건드리지 않고 setLabel() 메서드만 수정하면 됩니다.

속성 구현 단계

객체의 존재하지 않는 멤버 변수를 읽고 쓸 때 __get() __set()이 자동으로 호출된다는 것을 알고 있습니다. Yii는 이를 활용하여 속성에 대한 지원을 제공합니다. 위 코드에서 객체의 특정 속성에 액세스하면 Yii가 getpropertyname()이라는 함수를 호출하는 것을 볼 수 있습니다. 예를 들어 SomeObject->Foo는 자동으로 SomeObject->getFoo()를 호출합니다. 속성이 수정되면 해당 setter 함수가 호출됩니다. 예를 들어 SomeObject->Foo = $someValue는 자동으로 SomeObject->setFoo($someValue)를 호출합니다.

따라서 속성을 구현하려면 일반적으로 세 단계가 필요합니다.

  • yiibaseObject에서 상속됩니다.
  • 이 속성을 저장하는 데 사용되는 전용 멤버 변수를 선언하세요.
  • 위에 언급된 비공개 멤버 변수에 액세스하고 수정하기 위한 getter, setter 함수 또는 둘 다를 제공하세요. getter만 제공되면 속성은 읽기 전용이고, setter만 제공하면 속성은 쓰기 전용입니다.

다음 Post 클래스는 읽기 및 쓰기 가능한 속성 제목을 구현합니다.

class Post extends yii\base\Object  // 第一步:继承自 yii\base\Object
{
  private $_title;         // 第二步:声明一个私有成员变量

  public function getTitle()    // 第三步:提供getter和setter
  {
    return $this->_title;
  }

  public function setTitle($value)
  {
    $this->_title = trim($value);
  }
}

이론적으로 비공개 $_title을 공개 $title로 작성하면 $post->title을 읽고 쓸 수도 있습니다. 하지만 이는 좋은 습관이 아니며 그 이유는 다음과 같습니다.

클래스 캡슐화가 손실되었습니다. 일반적으로 말해서, 멤버 변수를 외부 세계에 보이지 않게 만드는 것은 좋은 프로그래밍 방법입니다. 여기에서는 보이지 않을 수도 있지만 언젠가 사용자가 제목을 수정하는 것을 원하지 않는다면 어떻게 변경합니까? 코드에서 제목이 직접 수정되지 않도록 하는 방법은 무엇입니까? setter가 제공되는 경우 setter가 삭제되는 동안 헤더에 정리되지 않은 쓰기가 있으면 예외가 발생합니다. public $title 메소드를 사용하는 경우 private $title로 변경하여 쓰기 예외를 확인할 수 있지만 읽기도 금지됩니다.
제목 작성 시 공백을 제거하고 싶습니다. setter 메소드를 사용하면 위의 코드와 같이 이곳에서 Trim()만 호출하면 됩니다. 그러나 공개 $title 메서드를 사용하면 모든 write 문에서 Trim()이 호출된다는 데는 의심의 여지가 없습니다. 누락된 것이 없다고 보장할 수 있나요?
따라서 public $title을 사용하는 것은 빠르고 간단해 보이지만 앞으로 수정하기가 번거로울 것입니다. 악몽이라고 할 수 있습니다. 이것이 소프트웨어 엔지니어링의 의미이며, 특정 방법을 통해 코드를 쉽게 유지하고 수정할 수 있도록 합니다. 언뜻 불필요해 보일 수도 있지만, 실제로 손실을 입었거나 고객의 상사로부터 이전 프로그래머가 작성한 코드를 수정하도록 강요당하고 친척들에게 인사를 한 친구들은 모두 이것이 매우 필요하다고 느낄 것입니다.

그러나 이 세상에 절대적인 것은 없습니다. __get() 및 __set()은 모든 멤버 변수를 탐색하므로 일치하는 멤버 변수가 없는 경우에만 호출됩니다. 따라서 멤버 변수를 사용하는 것보다 효율성이 본질적으로 낮습니다. 데이터 구조, 데이터 컬렉션 등이 표현되고 읽기/쓰기 제어가 필요하지 않은 일부 간단한 상황에서는 멤버 변수를 속성으로 간주하여 효율성을 높일 수 있습니다.

효율성을 높이는 또 다른 작은 요령은 $pro = $object->pro 대신 $pro = $object->getPro()를 사용하고 $ object- 대신 $objcect->setPro($value)를 사용하는 것입니다. >프로 = $값 . 이는 정확히 동일한 기능적 효과를 가지지만 순회 프로세스를 우회하는 것과 동일한 __get() 및 __set() 사용을 방지합니다.

누군가가 나를 꾸짖어야 한다고 생각합니다. Yii는 개발자의 편의를 위해 마침내 속성 메커니즘을 구현했지만 소위 효율성을 향상시키기 위해 원래 방법을 사용하는 방법을 가르치기 위해 왔습니다. 글쎄요, 실제로 개발 편의성과 높은 실행 효율성 사이에는 일정한 모순이 있습니다. 내 개인적인 관점은 편의를 최우선으로 생각하고 Yii가 우리에게 제공하는 편리한 조건을 잘 활용하는 경향이 있습니다. 효율성에 관해서는 프레임워크 자체에 더 많은 주의를 기울여야 합니다. 추가 코드를 작성하지 않는 한 괜찮을 것입니다.

하지만 Yii 프레임워크에서는 $app->request와 같은 코드가 거의 나타나지 않고 대신 $app->getRequest()가 사용되므로 안심하셔도 됩니다. 즉 프레임워크 자체는 효율성에 각별히 신경을 쓰고, 편의성은 개발자에게 맡긴다는 것이다. 요컨대, 사용 여부와 사용 방법은 전적으로 귀하에게 달려 있습니다.

주목할 만한 점:

존재하지 않는 멤버 변수에 접근할 때만 __get() __set() 자동 호출 타이밍이 발생하기 때문입니다. 따라서 멤버변수 public $title을 정의하면 getTitle(), setTitle()을 정의하더라도 호출되지 않는다. $post->title은 pulic $title을 직접 가리키기 때문에 __get() __set()은 호출되지 않습니다. 뿌리부터 잘렸네요.
PHP는 클래스 메소드에서 대소문자를 구분하지 않기 때문에 $post->getTitle() 및 $post->gettitle()은 동일한 함수를 호출합니다. 따라서 $post->title과 $post->Title은 동일한 속성입니다. 즉, 속성 이름도 대소문자를 구분하지 않습니다.
__get()과 __set()은 모두 공개이므로 getTitle(), setTitle()이 공개, 비공개 또는 보호로 선언되었는지는 의미가 없습니다. 또한 외부에서도 액세스할 수 있습니다. 따라서 모든 속성은 공개됩니다.
__get() __set() 모두 정적이 아니므로 정적 속성을 사용할 방법이 없습니다.
Object

의 기타 속성 관련 메서드

__get() __set() 외에도 yiibaseObject는 속성 사용을 용이하게 하기 위해 다음 메서드도 제공합니다.

  • __isset()은 속성 값이 null이 아닌지 테스트하는 데 사용되며 isset($object->property) 시 자동으로 호출됩니다. 이 속성에는 해당 getter가 있어야 합니다.
  • __unset()은 속성 값을 null로 설정하는 데 사용되며 unset($object->property) 시 자동으로 호출됩니다. 이 속성에는 해당 setter가 있어야 합니다.
  • hasProperty()는 특정 속성이 있는지 테스트하는 데 사용됩니다. 즉, getter 또는 setter가 정의됩니다. hasProperty()의 매개 변수 $checkVars = true(기본값은 true)인 경우 동일한 이름을 가진 모든 멤버 변수도 앞에서 언급한 공개 $title과 같이 이 속성을 갖는 것으로 간주됩니다.
  • canGetProperty()는 속성을 읽을 수 있는지 테스트합니다. $checkVars 매개변수의 의미는 위와 동일합니다. getter가 정의되어 있으면 속성을 읽을 수 있습니다. 또한 $checkVars가 true인 경우. 따라서 클래스가 멤버 변수를 정의하는 한 공개, 비공개 또는 보호 여부에 관계없이 읽을 수 있는 것으로 간주됩니다.
  • canSetProperty()는 속성이 쓰기 가능한지 여부를 테스트합니다. $checkVars 매개변수의 의미는 위와 같습니다. setter가 정의되어 있으면 속성을 쓸 수 있습니다. 동시에 $checkVars는 true입니다. 그런 다음 클래스가 멤버 변수를 정의하는 한 공개, 비공개 또는 보호 여부에 관계없이 쓰기 가능한 것으로 간주됩니다.
  • 객체 및 구성요소

yiibaseComponent는 yiibaseObject를 상속하므로 속성 등 기본 기능도 갖습니다.

그러나 Component도 이벤트와 동작을 도입하므로 단순히 Object의 속성 구현 방법을 상속하는 것이 아니라 동일한 메커니즘을 기반으로 __get(), __set() 등의 함수를 오버로드합니다. 그러나 구현 메커니즘 측면에서는 동일합니다. 이는 이해에 영향을 미치지 않습니다.

앞서 언급했듯이 Yii는 공식적으로 컴포넌트 기반 프레임워크로 자리잡고 있습니다. 눈에 보이는 구성 요소의 개념은 Yii의 기초입니다. Yii의 소스 코드나 API 문서를 읽는 데 관심이 있다면 Yii의 거의 모든 핵심 클래스가 yiibaseComponent에서 파생(상속)된다는 것을 알 수 있습니다.

Yii1.1에는 이미 CComponent라는 컴포넌트가 있었습니다. Yii2는 Yii1.1의 CComponent를 yiibaseObject와 yiibaseComponent의 두 클래스로 분할합니다.

그 중 Object는 상대적으로 가볍고 getter와 setter를 통해 클래스의 속성을 정의합니다. 구성 요소는 개체에서 파생되며 이벤트와 동작을 지원합니다. 따라서 Component 클래스에는 세 가지 중요한 특성이 있습니다.

  • 재산
  • 이벤트
  • 행동

이 세 가지 기능이 수업 기능을 풍부하게 하고 확장하며 수업 행동을 변화시키는 중요한 시작점이라는 점을 어느 정도 이해하셨으리라 믿습니다. 따라서 Yii에서는 컴포넌트의 위상이 매우 높습니다.

컴포넌트는 더 많은 기능과 편의성을 제공하면서도 이벤트와 비헤이비어라는 두 가지 기능을 추가하여 어느 정도 효율성을 희생하면서도 개발을 용이하게 합니다. 일부 데이터를 나타내는 클래스 등 개발 중에 이벤트와 동작의 두 가지 기능을 사용할 필요가 없는 경우. 그런 다음 Component 대신 Object에서 상속할 수 있습니다. 일반적인 애플리케이션 시나리오는 사용자가 입력한 데이터 집합을 나타내는 경우 Object를 사용하는 것입니다. 그리고 객체의 동작과 처리에 응답할 수 있는 이벤트를 처리해야 한다면 Component를 사용해야 한다는 것은 의심의 여지가 없습니다. 효율성 측면에서는 Object가 기본 PHP 클래스에 더 가깝기 때문에 가능하면 Object를 먼저 사용해야 합니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.