20
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FuelPHPメモ

Last updated at Posted at 2016-02-04

バリデーションの表示言語を日本語に設定する

1.classes/lang/以下にjaというフォルダを作成する
2.jaの中にvalidation.phpというファイルを作成する
3.fuel/app/config/config.phpでバリデーションの文字を日本語に設定

fuel/app/config/config.php
/**
 * Localization & internationalization settings
 */
'language'           => 'ja', // ここがデフォルトではenなのでjaに設定(1.で作ったフォルダ名と同じならじゃなくても良い)
// 'language_fallback'  => 'en', // Fallback language when file isn't available for default language
// 'locale'             => 'en_US', // PHP set_locale() setting, null to not set

4.以下のように出力したいバリデーションメッセージを設定

classes/lang/ja/validation.php
<?php

return array(
	'required'        => ' :label 欄は必須です。',
	'min_length'      => ' :label 欄は :param:1 文字以上にしてください。',
	'max_length'      => ' :label 欄は :param:1 文字を超えないようにしてください',
	'exact_length'    => 'The field :label must contain exactly :param:1 characters.',
	'match_value'     => 'The field :label must contain the value :param:1.',
	'match_pattern'   => 'The field :label must match the pattern :param:1.',
	'match_field'     => 'The field :label must match the field :param:1.',
	'valid_email'     => 'The field :label must contain a valid email address.',
	'valid_emails'    => 'The field :label must contain a list of valid email addresses.',
	'valid_url'       => 'The field :label must contain a valid URL.',
	'valid_ip'        => 'The field :label must contain a valid IP address.',
	'numeric_min'     => 'The minimum numeric value of :label must be :param:1',
	'numeric_max'     => 'The maximum numeric value of :label must be :param:1',
	'numeric_between' => 'The field :label must contain a numeric value between :param:1 and :param:2',
	'valid_string'    => 'The valid string rule :rule(:param:1) failed for field :label',
	'required_with'   => 'The field :label must contain a value if :param:1 contains a value.',
	'valid_date'      => 'The field :label must contain a valid formatted date.',
);

CSRF対策

データを送信するformに以下を記述する

<?php echo Form::csrf(); ?>

POST値取得側でtokenのチェックを行う

if ( !Security::check_token() ) {
    echo "ページ遷移が不正です";
}

例外を自分で設定する

FuelPHPには404 Not Found用 HttpNotFoundExceptionクラスと500エラー用のHttpServerErrorExceptionクラスがある
自作のエラー処理クラスを作成したい場合はHttpExceptionクラスを継承する

1.自作エラー処理関数を作成

classes/myexception.php
class MyHttpException extends HttpException
{
    public function response()
    {
        return \Request::forge('error/invalid')->execute([$this->getMessage()])->response();
    }
}

2.エラー表示画面の作成

classes/controller/error.php
class Controller_Error extends \Controller_Template
{
    public function action_invalid($message = null)
    {
        if ( $message === null ) {
            return '不正なデータです';
        } else {
            return e($message);
        }
    }
}

3.自作エラー処理を使う

どこかのController
    throw new MyHttpException('正しいページ遷移で来てください');

これはFuelPHPのHMVCという機能を使用したパターンです
自分のアクション以外のアクション結果を返せます
1.のforgeで使用するページを指定します ('error/invalid') invalidへのルーティングが必要な時は追加しておきましょう
executeで'正しいページ遷移で来てください'というメッセージを引数にとってinvalidにリクエストを送ります
その結果をresponseで取得し表示します

modules以下のclassesのパスについて

modules/user/classes/controller
                    /model
                    /view
modules/user/classes/

一番下に記述しているclasses直下にファイルを作成した時
checkvalidate.phpとかを作成した場合

テストに記述するパスは
user\CheckValidateになる

異なるフォームの値が同じかどうかのバリデーションを掛けたい時

add_ruleでmatch_fieldを使う

// メールアドレス入力
$val->add('email', 'email')
    ->add_rule('required')
    ->add_rule('match_field', 'confirm_email');

// 確認用メールアドレス入力
$val->add('confirm_email', 'confirm_email')
    ->add_rule('required');

emailとconfirm_emailの入力が一致していない場合は警告が出る

カスタム(独自)バリデーションの作成

作成手順

  1. カスタム(独自)バリデーションクラスの作成
  2. Validation::forgeのadd_rulesメソッドでカスタムバリデーションを追加
  3. 2.で追加したバリデーションにaddcallableメソッドでカスタムバリデーションクラスを追加
  4. lang/~/validation.phpにバリデーション追加
    の手順

1.カスタムバリデーションクラスの作成
規約としてバリデーションメソッド名は「validation」で始めないといけません

custom_validation.php
class CustomValidation
{
    // 値が5の時だけバリデーションを通す
    public static function _validation_number_five($value)
    {
        if ( $value === 5 ) return true;
        else                return false;
    }
}

2.Validation::forgeのadd_rulesメソッドでカスタムバリデーションを追加

form.php
    public function action_input_five()
    {
        $val = \Validation::forge();
        $val->add('number', '数字')
            ->add_rule('required')
            ->add_rules('number_five'); // バリデーション追加
    }

3.2.で追加したバリデーションにaddcallableメソッドでカスタムバリデーションクラスを追加

form.php
    public function action_input_five()
    {
        $val = \Validation::forge();
        $val->add('number', '数字')
            ->add_rule('required')
            ->add_rules('number_five')
            ->addcallable('CustomValidation'); // カスタムバリデーションクラスを追加 ※多分出来る
    }

4.lang/~/validation.phpにバリデーション追加

lang/~/validation.php
<?php

return array(
	'required'     => ':labelは必須です。',
	'min_length'   => ':labelは:param:1文字以上にしてください。',
	'number_five'  => ':labelは5しか認めません。', // バリデーション名とメッセージ追加
);

パッケージを読み込みたいとき

パッケージ名はpackages/ 下のフォルダ名だと思う

\Package::load('パッケージ名');

コンフィグを読み込みたいとき

\Config::load('ファイル名',true);

oil generate adminで管理画面を作成し、生成されたcontrollerをmodules以下のディレクトリに移してにlogin画面を開こうとした場合にリダイレクトループになる現象を回避する方法

ここのソースです
controllers/admin.php

admin.php
Request::active()->controller !== 'Controller_Admin' or ! in_array(Request::active()->action, array('login', 'logout'))

このコードの前で\Request::active()->controller\Request::active()->actionを出力して値を確認しましょう

もしファイルをapp/modules/mydirectory/classes/controllerディレクトリを移した場合

本来Controller_Adminという値が取得されるはずがmydirectory\Controller_Adminとなっていてif文の条件で無限にfalseと判定され続ける
ので

\Request::active()->controller !== 'Controller_Admin'

\Request::active()->controller !== 'mydirectory\Controller_Admin'

みたいに変更すればログイン画面に遷移できるはず

modulesの中のモデルのリレーションを設定したい時に、別モデルを指定する

model_toの中を単純にモデル名だけ指定すると、そんなモデルは見つからないと怒られます

'model_to' => 'Model_Category',

ので以下のようにnamespace\モデル名とする

モデル.php

    protected static $_belongs_to = array(
        'trn_faq_category' => array(
            'key_from' => 'faq_category_id',
            'model_to' => 'backend\Model_FaqCategory',
            'key_to' => 'id',
            'cascade_save' => true,
            'cascade_delete' => false,
        )
    );

モデルのリレーションにbelongを追加するときは対応するモデルにhas_oneを追加しなければいけない

モデル全体で物理削除をしたくないときはOrm\Modelを継承するのではなくOrm\Model_Softを継承する

ソフトモデル

ORMでクエリを発行した際のクエリを表示するメソッド

DB::last_query();

ORMのrelatedでjoinsしたテーブルの条件を検索条件に使う場合

 ->where('リレーション.カラム名', $val)

relationで取得したオブジェクトからjoinしたデータを取得する

$related_user = ->related('game')
$related_user->game->score;

ORMで取得するカラムを指定する場合

->select('id', 'status_type')

指定条件で1件のみデータを取得する

public static function get_first_user_by_search_criteria($search_data = [])
{
    $user_info = self::query()
                      ->related('user_status')
                      ->where($search_data)
                      ->get_one();
    
    return !empty($user_info) ? $user_info : [];
}

ORMqueryのwhereに連想配列で検索条件のカラムを入れる時のrelationしているテーブルのカラム指定方法

例えば以下の関係(親テーブルはuserとする)の時に

    $user_info = self::query()
                      ->related('user_status')
                      ->where($search_data)
                      ->get_one();

whereの条件をuser_status.birthdayとしたい場合
$search_dataに入れる時の記述方法は

    [
        `user_status.birthday` => $date
    ]

となる

もしuser_statusに関連するuser_detailのようなテーブルがあった場合
その指定方法は

    [
        `user_status.user_detail.hoby` => $hoby
    ]

のように
リレーションテーブル.その先のリレーションテーブル.カラム

となる
リレーションが深くなっても.で繋げば条件を指定できる

コアクラスを拡張する

コアクラスの拡張

コアクラスを継承する時は同じクラス名で継承した後、fuel/app/bootstrap.phpのAutoloaderに継承したファイルを追記しなければならない

例えばCryptクラスを拡張したいとして

fuel/app/classes/mycrypt.phpを作成したとする

fuel/app/classes/mycrypt.php
<?php

// Cryptという同じ名前で継承
class Crypt extends \Fuel\Core\Crypt
{

    // 追加した関数
    public static function ee($str)
    {
        echo $str . "\n";
    }

}

eeというメソッドを追加しました(適当
クラスの拡張は済んだので次はbootstrap.phpの編集

fuel/app/bootstrap.php
\Autoloader::add_classes(array(
	// Add classes you want to override here
	// Example: 'View' => APPPATH.'classes/view.php',
	
    // ここに追記
    // '拡張クラス名' => 
    'Crypt' => APPPATH.'classes/mycrypt.php',
));

これで

Crypt::ee("拡張成功");

とかすればeeメソッドが使用できると思います

元のCryptクラスを使いたい場合は

\Fuel\Core\Crypt::encode("~~");

みたいにパスを指定してあげれば使えます

ViewでCSSや画像の読み込み

Assetクラスを使う
public/asset以下のファイルを読み込む場合は

<?php echo Asset::css("bootstrap.min.css"); ?>

のようにAsset::cssを使う

public/css/css2/以下のファイルを読み込む場合は

<?php echo Asset::css("css2/bootstrap.min.css"); ?>

ディレクトリを追加しましょう

Authコマンドの実行

oil console
>>> Auth::create_user('admin', 'password', 'example@co.jp', 100);

既にログインしている状態なので未ログイン時に見せるページを表示させたくない場合

例えばログインしていない時に見せたいページhttps://myservice/notloginにログインしているユーザが遷移してきた場合、ログイン状態の初期ページに飛ばしたい
https://myservice/topとか

// redirectでtopに飛ばす
\Auth::check() and \Response::redirect('top');

Modelでsaveした時の挙動

$user = Model::forge();
$user->name = 'バイバイまさや選手権';

$res = $user->save()

var_dump($res);
var_dump($user);

ここの$resはbool型でinsertに成功しかたの結果を返します。
次に$userはそのモデルのプロパティが入ります、idがauto_incrementだったら勝手にidが入ってくれます。

DBトランザクションを実現する

try
{
    DB::start_transaction();

    // 何らかのクエリ...

    DB::commit_transaction();
    // クエリの結果を返す
}
catch (Exception $e)
{
    // 未決のトランザクションクエリをロールバックする
    DB::rollback_transaction();
    throw $e;
}

トレイトを使用する

手順は

  1. トレイトを定義する
  2. bootstrap.phpにロードするファイルを追記
  3. 実際に使う

modules下とかclasses下のモデルで定義する場合によって微妙に変わるかもしれませんが
今回はfuel/app/classes/model/model_base.phpにトレイトクラスを定義しました

1.トレイトを定義する

fuel/app/classes/model/model_base.php
<?php

trait ModelBase
{

    public function getValue($column)
    {
        return $this->$column;
    }

    public function setValue($column, $value)
    {
        $this->$column = $value;
    }
    
}

2.bootstrap.phpにロードするファイルを追記

fuel/app/bootstrap.php
<?php
// Bootstrap the framework DO NOT edit this
require COREPATH.'bootstrap.php';

\Autoloader::add_classes(array(
	// Add classes you want to override here
));

// Register the autoloader
\Autoloader::register();

\Fuel::load(APPPATH.DS.'classes/model/model_base.php');

3.実際に使う

トレイトのメソッドを使いたいクラス内で使えるように宣言します

fuel/app/classes/model/hogemodel.php
<?php

class Model_Hoge extends \Orm\Model
{

    // 使うトレイトを宣言
    use \ModelBase;

}

$hoge = Hoge()::forge();
$hoge->getValue('name');

moduleのconfig下にコンフィグファイルを置いてそれを読み込みたい場合の設定

fuel/app/config/config.phpalways_loadconfigに読み込ませたいmoduleとconfigファイルを指定する

fuel/app/config/config.php
'always_load'  => array(
    'config' => array(
        'app',
        'const',
        'CustomModule::customauth' => 'customauth', // ここがコンフィグ読み込ませる設定
    ),
),

\Config::getで使う場合は

\Config::get('customauth.~~~')

のように使える

FuelPHP で modules 利用時の config 設定について整理

Sessionの有効期限を設定しているファイルと変数

まずファイルは
fuel/core/config/session.php

fuel/core/config/session.php
// 変数はこれ
    // session expiration time, <= 0 means 2 years! (optional, default = 2 hours)
    'expiration_time' => 7200,

秒単位での設定なのでセッションを3秒で切りたいときは3、1時間に設定したいときは3600とかに設定しましょう

ローカルでは動作していたが、検証用サーバーに持っていくとクラスが見つからないという旨のメッセージを受けた場合

その呼び出し元PHPファイル名に大文字が入っていないか見る

FuelPHPのファイル名は全て小文字だが、大文字小文字を解決できるファイルシステムだと大文字でも通ってしまって本番などにあげたときに動かなくなることがある

Undefined variable: titleのようなエラー

上記のようなエラーが出て、エラー箇所が$this->template->titleみたいなテンプレート関連だったら
まずはそのコントローラがController_Templateなどを継承しているか確認する
templateが使えないので使えるようにしていけば良い

Controller_Templateを継承したクラスを継承してコントローラを実装した場合before()などでparent::before();などをするように

1つのルーティングされているアクションで2つのルーティングされていないアクションを呼び出す

例えば1つのルーティングだけどログイン状態によって表示したいViewや処理を変更したい時に、全ての処理を1つのアクション内に突っ込むのはダサいので違うアクションを呼んで表示項目を変更しようという目的

ルーティングの設定

routing.php
    '_root_' => 'top/index'

ユーザーがアクセスするルーティングされているアクション

Controller_Top.php
    public action_index()
    {
        if ( self::isLogin() ) {
            // forgeにfalseをつけることでルーティングに設定されていないアクションを呼び出せる
            // その時の指定パスはルーティング定義の'' => 'こっちに書く方' を指定する
            $this->template->content = \Request::forge('top/top', false)->execute()->response();
        } else {
            $this->template->content = \Request::forge('guest/top', false)->execute()->response();
        }
    }

2つのルーティングされていないアクション

Controller_Top.php
    public function action_top()
    {
        $values = [
            'posts' => [],
            'errors' => [],
        ];
        $this->template->title = 'あなたはログインしていますね。';
        $this->template->content = \View::forge('top/index', $values);
    }
Controller_Guest.php
    public function action_top()
    {
        $values = [
            'posts' => [],
            'errors' => [],
        ];
        $this->template->title = 'あなたはログインしていません。';
        $this->template->content = \View::forge('guest/index', $values);
    }

1つ目のアクションは別々のアクションを呼び出すための振分け役で、他のルーティングされていないアクションが表示する本体
ルーティングされていないアクションはURLからはアクセス出来ない

URLからアクセスさせないようにするのはルーティングに書かないのが一番いいが、\Request::is_hmvc()という関数を使えばURLからアクセスされた場合とアクションから呼び出された場合の処理を振分けることが出来る

    if(\Request::is_hmvc())
    {
        // HMVCだった場合の処理
    }
    else
    {
        // それ以外
    }

TESTを実行するときにCould not find asset: bootstrap.cssのようなエラーを吐く場合の対策

解決策としてはfuel/app/config/以下にasset.phpを配置して'fail_silently' => true,を記述する

※module用の設定ファイルはfuel/app/モジュール名/asset.php

fuel/app/config/asset.php
return [
    'fail_silently' => true, // Test時のファイル名解決できない問題を解消する
];

TESTクラスに自作のメソッドをtraitで追加したい時

  1. Traitを作成
  2. クラスの外でuse宣言
  3. テストメソッド内でtraitのメソッドを使う

2.の宣言方法はこんな感じ
useをクラス内で宣言出来なかった

use path\MyTestTrait as MyTestTrait;
class ~~~~_Test extends \TestCase
{
    public function test_myprocedure()
    {
        MyTestTrait::originalMethods();
    {
}

Fuel標準ではないモジュールをcomposerインストールした時のクラスの使い方

composer updateした後にvendor下に指定のライブラリが入っていることを確認する
基本的に外部ライブラリは使うときにuseなどで読み込む必要な無い

new \GuzzleHttp\Client([みたいに

fuel/coreを削除したコミットをして、その後にcomposer.phar updateをかけるが上手くファイルが落ちてこない時の確認項目とその後のインストール

まずfuel/corefuel/package下の各ディレクトリが空になっていないか確認する
ここにディレクトリが存在しているとcomposer.phar updateなどをした時にディレクトリが存在すると勘違いされその下のファイルが入ってこない
ので

rm -rm fuel/core
rm -rm fuel/package/~~~

を実行してから
ファイルを取得するために

php ./composer.phar install

これで無くなったファイルが再び入ってくる

20
20
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?