質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

5回答

1907閲覧

PHPのアクセサメソッドの意義と必要性とは何でしょうか?

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

3クリップ

投稿2018/02/26 01:44

PHPにアクセサメソッドというものがあると思いますが、その意義がわかりません。

一般的な解説には「プロパティのアクセス修飾子をprivateにすると、不正なデータは外部から格納できなくなり安全ですが、そのプロパティに対して外部からデータを入出力できるようにする必要があります。」という文章があります。

そもそも外部から不正なデータを遮断することで安全性を確保するためのprivateなのに、「そのプロパティに対して外部からデータを入出力できるようにする」ことができてしまうと、意味がないように思えるのです。

なぜprivateにする必要があるのか。そして、どうしてprivateを使えば安全にデータを読み書きできるのかを教えてください。

よろしくお願い致します!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2018/02/26 01:57

ソースは提示できますか?
退会済みユーザー

退会済みユーザー

2018/02/26 02:12

phpの、ってついてるけど、他の言語処理系にもある一般的な概念に関する質問と捉えていいんじゃないですか?
guest

回答5

0

プロパティが public ですと、どんなデータでも直接入れることができます。
これに対して private でアクセサメソッドを経由する場合、特に set する場合において、チェックをすることができます。
つまり、「受け入れることのできるデータだけを確実に通す」ためにアクセサメソッドを使えるのです。

例えばテストの点数であれば、どんなに小さくてもマイナスにはならないはずですし、最高点は100ないし200(TOEIC の900というのもありますが)などになります。
ですからsetするアクセサメソッドは、セットしようとする値が「0~最高点の間」であるかどうかチェックして、変なデータを混入させないようにできるわけです。

また、private なプロパティに対して、「読み取るだけ」のアクセサメソッドを作ることで、データは見せるけど更新はできない、といったこともできます。

投稿2018/02/26 08:38

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ゲッターの必要性:データ読み出し時に何らかの処理を行えること。
セッターの必要性:データ書き込み時に何らかの処理を行えること。

特にセッターは意図しない不正なデータの書き込みを許さないよう
与えられたデータの検証を行うために使うことが多いです。
例えば PHP 7.2リリース&PHPのアクセス修飾子、アクセサメソッド、カプセル化、コンストラクタ:Web業界で働くためのPHP入門(14) - @IT の事例では、
本来数字データを格納するべきところに文字列データが来ないように、
さらには数字データとして望ましくない範囲外データを拒否できるように、
セッターで入力データを検証できるようになります。

ゲッターに関しては
例えば読み出された回数を記録できるとか、
デバッグ出力(今読み出されました、を出力)に応用するとか、
そんなところでしょうか。
(実用的に使う場面が、個人的にも今ひとつ思い浮かばない。)

複数人が関わるプロジェクトなどで、
クラスの応用の解釈が揺らがないよう仕様管理していくのでしょうが、
他人が設計・実装したクラスをうっかり間違って使うこともありうるため、
こういう仕組みで防ぐというのもありますし、
ひいてはシステムの脆弱性をついた攻撃に備えることにもつながるかと思われます。

投稿2018/02/26 10:29

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/02/26 11:32

回答ありがとうございます。とてもわかりやすい解説で助かりました。 セッターについては不正な値を書き込みさせないという目的があって腹落ちするのですが、やはりゲッターの必要性がどうしてもわかりづらいですね…。 実用的に使う場面がなくても、実務ではセッターは頻繁に使うものなのでしょうか?もしおわかりでしたらご回答いただけますと幸いです。
退会済みユーザー

退会済みユーザー

2018/02/26 12:45

(入力パラメータを格納する動作としては同じなのでしょうが、) クラスの外側でデータチェックして格納するよりも、 クラスの内側でデータチェックして格納するほうが、 外側で同じようなデータチェックのコードを(2度も3度も)書くことを省くという意味で クラスを利用する側(外側)のコード量が減らせる芽があるので、 セッターは重要だし頻繁に使用すると思います。 ゲッターも、格納しているデータをただ返すだけなら要らないかもしれませんが、 リアルタイムにデータベースやプロセス間通信や他ホストへの問い合わせによる 結果を返す必要がある場合はゲッター必要になります。 必要な事例と考えられば採用して実装すればよろしいかと思います。 必須である、必要であると考えられない場合は、 無駄にコーディング量を増やさずに省いても良いと思います。
tacsheaven

2018/02/26 13:29

ゲッターに関して言えば、例えば画像ファイルを扱うクラスを考えるとわかりやすいかも知れません。画像ファイルをロードしたら、その縦横サイズは固定されます(ベクターデータでなければ)。ファイルがロードされた時点で、private なプロパティにその内容を格納しておいて、public なゲッターでそのファイルの縦横サイズを返します。 ※むろん、画像データを private でもっていて、ゲッターの中で画像データから算出してもよいのですが、毎回算出したらバカバカしいですよね?
guest

0

  • PHPにおいては,プロパティに型は指定できない一方,メソッドの引数には**「代入可能な型の制御」** **「代入可能なタイミングの制御」**を課すことができる。この時点でまず public ではなく protected または private を採用するメリットがある。
  • ファクトリクラス・コンフィグクラス・シングルトンクラス等の一部のユースケースを除き,一般的にオブジェクトはイミュータブルであるほうが望ましいとされるため,Setterはむしろ使わないほうがいい。この考えに則る場合は,プロパティに設定すべき内容はSetterではなくConstructorで渡すようにする。後からプロパティを変更したい場合は, setXXX の代わりに withXXX という命名を使って,返り値に変更を反映した新しいオブジェクトを返すようにする。
  • もしPHPにおいて,プロパティにJavaのfinal(Constructorでのみ代入を認めてそれ以降の変更は認めない)相当の制約を課すことが可能であるなら,public final で宣言すればGetterは無くても済むが,そのような機能はないため結局のところ多くの場合はGetterが必要になる。また,取得のたびにリアルタイムな値を使って再計算するような場合もGetterが必要。

要するに,protectedなプロパティとGetterをベースにして,Setterはどうしても必要なときだけ使う,が正解です。イミュータブルにしてもコーディングの生産性が落ちない(むしろ分かりやすくなって上がる)場合はイミュータブルを採用しましょう。

(備考)privateprotected

  • ライブラリを作る際,高度なユーザによるカスタマイズを認める場合は private よりも protected のほうが望ましい。また,テストのしやすさを考えても protected のほうが望ましい。本当に private が求められるケースはあまりない。

投稿2018/02/26 18:08

編集2018/02/26 18:12
mpyw

総合スコア5223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

私もオブジェクト指向はあまり好きではなく、そういった疑問を持っておりました。

結局のところ、業務についてもプロパティと言うものに外部からの値を入れることはあまりなく、
どちらかと言うとそのクラス内で生成した値や、インスタンスなどを格納していることばかりです。

そもそも、同じことを考えている人は多く、「Tell, Don't Ask.」という言葉ができる次第です。

基本getter setterは使わないほうが吉、ということですね。
使うのであれば、本当に必要なのかを再度考え、入れれる値の制約をsetterでかけておくのが良いでしょう。

投稿2018/02/26 08:39

編集2018/02/26 08:40
nnahito

総合スコア2004

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

たとえば日付を表す DateTime クラスなど考えて見てください。
日には普通1から31以外の値を設定できませんが、2月の場合は28または29が最大になります。
ですからsetterではチェックを正確に行うため、年・月・日をまとめてセットする方式が採用されています。
またtime()関数で得られるUNIXタイムスタンプ値を使ってセットすることもできます。
このようにsetter, getter が必ずしもクラスの中のデータと1対1であるとは限らず、必要に応じて複数の出入り口を設けることもあるでしょう。

またいちどnew で生成したら二度と値を再設定できないgetterのみのクラス(Immutableなクラス)もあります。
この要件に応えるため、php5.5でわざわざDateTimeの変更不可なバージョンが登場しています。
http://php.net/manual/ja/class.datetimeimmutable.php

phpが特異なのは、他のJavaやC#などで記述されたアプリと違って、
ユーザからHTTPリクエストを受けてレスポンスを返却すると言う、数秒程度しかデータを保持する期間が無いことです。(ratchetなどは別として)
仮に途中でおかしなデータが混入したとしてもすぐに自然解消します。
タイマーや別スレッドの存在も意識する必要がありません。
このあたりgetterの必然性が感じにくいかもしれませんね。

getterが有意義な例としては、何らかの内部データを返すような処理で、
元データが未定(null)だった時などはExceptionを発生したりWarningを記録させられます。
エラーログを取っていれば読み出し元を知ることができるので、そのような不適切なタイミングでのアクセスを早期発見できます。

またphp7からは関数では public function getDay(): int のように 戻り値の型を記述できます

エディタに何を使用しているかわかりませんが、高機能なIDEでは戻り値の型が分かると、
$ret->など入力すると、続きでメソッドが候補表示され絞り込みもかかります。
書いている途中で人間ではなく機械が型チェックをし、ケアレスミスが防ぐと言うのが最近のプログラミングの流れですから、そう言う書き方に慣れておくことが長期的に見て生産性が上がるのでは無いかと思います。
(この考え方では __get()__set() などマジックメソッドは、IDEの推測機能を妨害するので避けた方が良いということでもあります)
phpDocでドキュメント化する場合もこの限りではありません。

投稿2018/03/06 09:39

TakeoSaki

総合スコア97

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問