ショートコードの属性に関する処理を集めたユーティリティクラス

ショートコードの属性に関する処理を集めたユーティリティクラスについて、PHPソースコードを解説しています。

このユーティリティクラスには、ShortcodeAttributeクラスのインスタンスを作成するstaticメソッドが、あります。

ShortcodeAttributeクラスは、ショートコードの各属性を保持するクラスです。

ショートコードの属性に関するユーティリティクラスを用意することで、
全てのソースコードの中から、ショートコードの属性に関する処理を見つけやすくなっています。

ショートコードの各属性を保持するShortcodeAttributeクラスのインスタンスを作成する

class ShortcodeAttributeUtils {

	public static function makeShortcodeAttribute($operation, $searchIndex, 
	$keyword, $numberToDisplay, 
	$itemTitleLength, $itemReviewLength): ShortcodeAttribute {

		中略

		$shortcodeAttribute = new ShortcodeAttribute ();
		$shortcodeAttribute->setOperation ( $operation );
		$shortcodeAttribute->setSearchIndex ( $searchIndex );
		$shortcodeAttribute->setKeyword ( $keyword );
		$shortcodeAttribute->setNumberToDisplay ( $numberToDisplay );
		$shortcodeAttribute->setItemTitleLength ( $itemTitleLength );
		$shortcodeAttribute->setItemReviewLength ( $itemReviewLength );

		return $shortcodeAttribute;
	}

以下省略

上記ソースコードのmakeShortcodeAttribute()関数は、ShortcodeAttributeクラスのインスタンスを作成します。

ショートコードの各属性の値が、ShortcodeAttributeクラスのインスタンス変数$shortcodeAttributeに対して、設定されます。

例えば、以下のショートコードの場合、

[goodsmemo_affiliate service="amazon" keyword="WordPress 開発" number="1"]

ShortcodeAttributeクラスのインスタンス変数$shortcodeAttributeには、以下の値が設定されます。

$shortcodeAttribute->setKeyword()に、"WordPress 開発"が設定される。
$shortcodeAttribute->setNumberToDisplay()に、1が設定される。

最後に、インスタンス変数$shortcodeAttributeは、return文によって返されます。

※関連記事:アフィリエイト商品表示・WordPressプラグイン、ショートコードの属性

特定の対象に関する処理を集めたクラス、ユーティリティクラス

Java言語でプログラミングしていた時期から、ユーティリティクラスを利用するようになりました。

ユーティリティクラスとは、ざっくり言うと、特定の対象に関する処理を集めたクラスです。

ShortcodeAttributeUtilsクラスの場合、ショートコードの属性に関する処理だけを集めたクラスになります。

ユーティリティクラスは、 staticメソッドだけがあります。
ユーティリティクラスのインスタンスを、作ることはありません。

例えば
$utl = new Utils();
という使い方はしません。

今後のプログラミングにおいて、もしもショートコードの属性に関する処理を新規作成する場合、
ShortcodeAttributeUtilsクラスに対して、メソッドを新規作成することになります。

ショートコードの属性に関する処理は、ShortcodeAttributeUtilsクラスにだけ存在しています。

よって、全てのソースコードの中から、ショートコードの属性に関する処理を見つけやすくなっています。
特定の処理を見つけやすいソースコードは、わかりやすいソースコードにつながります。

data, process, utilityという役割に分けて、クラスを作るプログラミング

たぶん1998年頃に、Javaのクラス設計に関するウェブサイトの記事を読んでいました。

どこかのソフトウェア開発会社のウェブサイトの記事だった、と思います。
そのソフトウェア会社の社員の方が、当時、Java World雑誌に連載記事を執筆していました。

そのウェブサイトの記事では、Javaのクラスを

  1. データ
  2. プロセス
  3. ユーティリティ

という三つの役割に分けて作成しましょう、と解説されていました。

その当時、オブジェクト指向やクラスを使用するプログラミングについて、よくわからない点がありました。

なので一時期、クラスに対して、データ、プロセス、ユーティリティという役割を与えて、プログラミングしていました。

その時の影響によって、ワードプレスプラグインを作成するPHPプログラミングにおいても、ユーティリティクラスを作っています。

ちなみに、ユーティリティクラスについてネットで調べたところ、

ユーティリティクラスを使ってはいけない、という意見がありました。

もしかしたら近年のオブジェクト指向プログラミングでは、ユーティリティクラスを使用しないのかもしれません。

業務データ、業務フロー、業務フローで利用する処理みたいな感じ?

あと、先ほどのデータ、プロセス、ユーティリティという役割について、ざっくり言うと、

  • データは、業務データ
  • プロセスは、業務フロー
  • ユーティリティーは、業務フローで利用する処理

みたいな感じだった、と思います。

Webアプリケーションのログイン処理で言うと、

LoginDataクラスで、ユーザーのIDやパスワードというデータを保持します。

LoginProcessクラスでは、ユーザーのIDやパスワードを検査して、正しいユーザーなら次の画面に遷移する処理をします。

LoginUtilsクラスでは、ユーザーのログイン処理に関係ある処理、
例えば、パスワードが正しいかどうかを判断するstaticメソッドなどを、用意します。

なお、LoginUtilsクラスのようなユーティリティクラスは、作成不要となる場合もありました。
必ず存在するクラスというわけでは、ないようです。

クラスのインスタンスを作るなら、makeでなくcreateが良いらしいです

makeShortcodeAttribute()関数では、ShortcodeAttributeクラスのインスタンスを作成します。

この記事を書いている時、プログラミングにおけるmakeとcreateの違いについて、ネット記事をちょっと調べてみました。

クラスのインスタンスを作るなら、makeでなくcreateが良いらしいです。

その意見を参考にすると、createShortcodeAttribute()関数というメソッド名が良いことになります。

createの意味は、創造する。何もないところから生み出す。
makeの意味は、材料から作り出す。

上記の意味を参考にしたら、

$shortcodeAttribute = new ShortcodeAttribute ();

このようにインスタンスを作るのは、クリエイトすることになるようです。

今まで、makeとcreateの使い分けを意識せずにプログラムを記述してきました。
過去に記述したソースコードについては、makeやcreateに関する修正を諦めました。時間と負担がかかるからです。

必須項目だから、ショートコードの検索キーワード属性が存在するか、確認する

if (trim ( $keyword ) === "") { // 0と””を区別するには ===(厳密な比較) を使います。
	throw new IllegalArgumentException ( "検索キーワードが空です:[" . $keyword . "] number:[" . $numberToDisplay . "]" );
}

ショートコードの検索キーワード属性は、必須項目です。
なので、キーワード文字列が存在するか、確認します。

検索キーワードがない場合、アフィリエイト商品を表示するHTMLを作れないからです。

ショートコードの検索キーワード属性が未指定の場合、
検索キーワードが空文字です、という例外を通知しています。

比較演算子 === について、当初、よくわかりませんでした…

上記ソースコードのif文では、厳密な比較を行う比較演算子 === を用いて、空文字の判定をしています。

このイコール文字が三つ連なる演算子について、当初、よくわかりませんでした。

PHPでif文の条件文を書くのは、なんだか難しい、と今でもたまに思います。

任意項目だから、ショートコードの「商品名の表示文字数」属性が空文字なら、次の処理に移る

if (trim ( $keyword ) === "") { // 0と””を区別するには ===(厳密な比較) を使います。
	throw new IllegalArgumentException ( "検索キーワードが空です:[" . $keyword . "] number:[" . $numberToDisplay . "]" );
}

if (trim ( $itemTitleLength ) === "") { // 0と””を区別するには ===(厳密な比較) を使います。
	; // 任意指定の属性なので、正しい
} else {
	ShortcodeAttributeUtils::isZeroOrMore ( $itemTitleLength, "無効な商品名の表示文字数" );
}

ショートコードの「商品名の表示文字数」属性は、任意項目です。

なので、$itemTitleLength変数が空文字であることは、未設定を意味します。
これは正しいです。

$itemTitleLength変数が空文字である場合、

何もせず、商品名の表示文字数が0以上か検査せず、次の処理に移ります。

if文では、肯定的な条件分岐を優先する書き方をしています

$itemTitleLength変数に関するif文では、肯定的な条件分岐を優先する書き方をしています。

肯定的な条件が成り立った場合、何もしません。
よって、; セミコロンだけ記述しています。

無駄と思える ; セミコロンを記述するわけは、

if文の条件において、「何々である」と、肯定文で条件を判断したいからです。

「何々でない」という否定文で条件を判断するのは、ちょっとわかりにくいです。
なので使いたくない、と考えています。

※関連記事:Javaソースコードにおいて、if文で肯定的な条件分岐を優先する書き方

表示する商品数や文字数が0以上か、検査する

private static function isZeroOrMore($valueText, string $errorMessage) {

	if (is_numeric ( $valueText ) && $valueText >= 0) { // ゼロ以上とした
		; // is関数だから、本来は return true;。以下で例外通知しているので、何もしないことにした。
	} else {
		throw new IllegalArgumentException ( $errorMessage . ":" . $valueText ); // 本来は、return false;
	}
}

isZeroOrMore()関数は、引数の$valueText変数が0以上か、検査します。
$valueText変数が0以上の数字でない場合、例外を通知します。

引数の$valueText変数の中身は、以下のショートコードの属性です。

  • 表示する商品数
  • 商品名の表示文字数
  • 商品説明の表示文字数

Boolean型の値を返さないのに、 isから始まるメソッド名になっていました

isZeroOrMore()関数については、初めの頃、Boolean型の値を返す関数でした。

ですが、false値を返す場合に例外を通知することに仕様変更したので、Boolean型の値を返さない関数になりました。

このように仕様変更したため、メソッドの名前も変えるべきだったかもしれません。

例えば、isの代わりにcheckを使った名前にした方が、良いかもしれません。

メソッド名に、checkを使った名前の例。
checkZeroOrMore()関数。

ShortcodeAttributeUtils.phpのソースコード

<?php

namespace goodsmemo\shortcode;

use goodsmemo\exception\IllegalArgumentException;

require_once GOODS_MEMO_DIR . "exception/IllegalArgumentException.php";

class ShortcodeAttributeUtils {

	public static function makeShortcodeAttribute($operation, $searchIndex, $keyword, $numberToDisplay, $itemTitleLength, $itemReviewLength): ShortcodeAttribute {

		ShortcodeAttributeUtils::isZeroOrMore ( $numberToDisplay, "無効な表示件数" );

		if (trim ( $keyword ) === "") { // 0と””を区別するには ===(厳密な比較) を使います。
			throw new IllegalArgumentException ( "検索キーワードが空です:[" . $keyword . "] number:[" . $numberToDisplay . "]" );
		}

		if (trim ( $itemTitleLength ) === "") { // 0と””を区別するには ===(厳密な比較) を使います。
			; // 任意指定の属性なので、正しい
		} else {
			ShortcodeAttributeUtils::isZeroOrMore ( $itemTitleLength, "無効な商品名の表示文字数" );
		}

		if (trim ( $itemReviewLength ) === "") { // 0と””を区別するには ===(厳密な比較) を使います。
			; // 任意指定の属性なので、正しい
		} else {
			ShortcodeAttributeUtils::isZeroOrMore ( $itemReviewLength, "無効な商品説明の表示文字数" );
		}

		$shortcodeAttribute = new ShortcodeAttribute ();
		$shortcodeAttribute->setOperation ( $operation );
		$shortcodeAttribute->setSearchIndex ( $searchIndex );
		$shortcodeAttribute->setKeyword ( $keyword );
		$shortcodeAttribute->setNumberToDisplay ( $numberToDisplay );
		$shortcodeAttribute->setItemTitleLength ( $itemTitleLength );
		$shortcodeAttribute->setItemReviewLength ( $itemReviewLength );

		return $shortcodeAttribute;
	}

	private static function isZeroOrMore($valueText, string $errorMessage) {

		if (is_numeric ( $valueText ) && $valueText >= 0) { // ゼロ以上とした
			; // is関数だから、本来は return true;。以下で例外通知しているので、何もしないことにした。
		} else {
			throw new IllegalArgumentException ( $errorMessage . ":" . $valueText ); // 本来は、return false;
		}
	}
}

【まとめ記事】へのリンク

【まとめ記事】アマゾンの商品を表示する場合、「アフィリエイト商品表示・WordPressプラグイン」のPHPソースコード解説

「アフィリエイト商品表示・WordPressプラグイン」を用いて、アマゾンの商品を表示する処理について、PHPソースコードを解説しています。

【まとめ記事】楽天市場の商品を表示する場合、「アフィリエイト商品表示・WordPressプラグイン」のPHPソースコード解説

「アフィリエイト商品表示・WordPressプラグイン」を用いて、楽天市場の商品を表示する処理について、PHPソースコードを解説しています。