異なるスコープからのi18nオブジェクトへのアクセス


10

私はMVCパターンを学ぶ方法として始まった私の個人的なフレームワークを構築していて、今ではほとんどのフレームワークよりも好きなものに進んでいます(これはおそらく私が好きなものを追加して、私がしないものを変更したためです)好きではありませんが、それにもかかわらず)良いか悪いかにかかわらず、私はいくつかのプロジェクトでそれを使用しています。

私が現在抱えている問題は、i18n機能にアクセスするための適切な方法を思い付かないことです(これは実際にはi18nではなく、単なる翻訳であり、完全なi18nサポートは含まれていません)。

それが機能する方法は、構成ファイルを言語ファイルとして使用することです。Configフレームワークでは構成ファイルが動的にロードされるため、クラスを使用してそれらをロードするのが非常に便利だと考えたため、必要でない限りここで一目で把握できます。

class Config {

    private static $settings = array();

    private function __construct() {

    }

    public static function load($file) {
        $path = PROJECT_PATH . '/config/' . $file . '.php';
        if (is_file($path)) {
            $settings = require($path);
        } else {
            throw new Exception('Configuration file [' . $file . '] doesn\'t exist', 500);
        }

        self::$settings[$file] = $settings;
        return true;
    }

    public static function get($file = null) {
        if ($file === null) {
            return self::$settings;
        } elseif (isset(self::$settings[$file]) || self::load($file)) {
            return self::$settings[$file];
        }
    }
}

単一の構成ファイルは次のようになります

<?php return array(
    'setting0' => 'value',
    'setting1' => 'value',
    ....
);

これにより、PHPがこれらのファイルをキャッシュし、ロードが非常に高速になります。

今度は翻訳について説明します。これらはと名付けられた別のディレクトリにある構成ファイルですが、翻訳にアクセスする必要があるたびlangに呼び出しを回避することはできないConfig::get('lang/en/myLangFile')ため、Translationsクラスを発明しました(発明しました)単一の翻訳ファイル

class Translations {

    protected $data = [];

    public function __construct(array $translations) {
        $this->data = $translations;
    }

    public function __get($name) {
        return isset($this->data[$name]) ? $this->data[$name] : $name;
    }

}

今では翻訳にアクセスするのがとても便利で美しいです

$t = new Translations([...]);

echo $t->translationKey;

私が持っているLang私は私のファクトリとしてそれを使用と考えましたので、他のほとんどのものの間でユーザーの優先言語を設定するために使用されるクラスTranslationsのクラスを

class Lang {

    public static function get($file) {
        return new Translations(Config::get('lang/' . self::$lang . '/' . $file));
    }

}

だから今私がいくつかの翻訳をつかむためにしなければならないすべては

$t = Lang::get('myLangFile');

echo $t->translationKey;

これらのクラスがインスタンス化されても意味がなく、シングルトンデザインパターンが好きではないため、なぜ静的なものがたくさんあるのか疑問に思われる場合は、PHPでサポートされていなくても「静的クラス」を使用することをお勧めします。 (まだ?)

これまでのところ、私は翻訳を行っていますが、問題を解決します(ついに)。

ビューがレンダリングされると、ユーザーにテキストを出力する可能性が最も高く、そのために内部で翻訳オブジェクトを使用できるようにする必要がありますが、それをコントローラーから渡さなければならないので、非常に不便です。各メソッドにそれを置くと、それは地獄です、さらに私がそうした場合、他のコントローラが正しいビューを呼び出さずに同じビューを呼び出すと、オブジェクトが壊れてしまいます。

これまで私がしてきたことは、翻訳オブジェクトを作成するすべてのビューの一番上にあります

<?php $t = Lang::get('myLangFile') ?>

<div><?= $t->helloWorld ?></div>

これは機能し、私のビューは呼び出し元に関係なく機能することを保証します。Translationsコンストラクタのコードは単なる割り当てであるため、変更を導入しない限り、インスタンス化は情報を含む配列をコピーしないため、基本的にパフォーマンスの点でほとんど何もかかりません。それで問題ないと思いますが、それは正しいことではないという理由で私を悩ませているだけです。

さらにTranslations、モデルまたはバリデーターでクラスを時々使用する必要があり、そこでもインスタンス化する必要があるため、1回の実行で同じTranslationsオブジェクトを複数回インスタンス化している可能性があります。この問題を解決するには、これらのオブジェクトをレジストリに追加する必要があります。

私は自分自身のようなものに目がくらむ可能性があり、おそらくいくつかの有用なアドバイスやものを得ることができるので、このアプローチについてのいくつかの考えは何ですか?私の問題に時間を費やすことを選んだ人に前もって感謝します!

回答:


0

<?php $t = Lang::get('myLangFile') ?>

<div><?= $t->helloWorld ?></div>

これは機能し、私のビューは呼び出し元に関係なく機能することを保証します。コンストラクタのコードは単なる割り当てであるため、変更が導入されない限り、Translationsのインスタンス化は情報を含む配列をコピーしないため、基本的にパフォーマンスの点でほとんど何もかかりません、それで問題ないと思いますが、それは正しいことではないという何らかの理由で私を悩ませているだけです。

どういう意味かわかります...
言語ファイルの読み込みの責任をビューに追加することで、コントロール反転デザインパターンを壊すことになるのではないかと思います。
たとえば、 'myLangFile'が大きくなりすぎて、2つの個別のファイルに分割したい場合は、ビューコードを変更しないと実行できません。
どう思いますか?


1
まさに、それは絶対に正当な理由です。
php_nub_qq

1
本当に?言語ファイル自体に他のファイルを含めることはできませんか?またはデータベースから読み取りますか?
svidgen 2017年

@svidgenは設計が非常に悪い
php_nub_qq
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.