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

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

ただいまの
回答率

90.52%

  • PHP

    20302questions

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

  • アルゴリズム

    408questions

    アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

php 独自のルールを基に配列の並び替えを行いたい。

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 372

kuzurotto

score 388

自作FW的なものを作っているのですが、ファイルの読み込み順に問題があり、配列の順番を変えたいのですが、これになかなか苦戦しています。

2018-06-25 00:40:22: array(5)
Array
(
    [0] => /core/classes/controller/base/baseAdminController.php
    [1] => /core/classes/controller/base/baseController.php
    [2] => /core/classes/model/baseModel.php
    [3] => /core/classes/object/baseObject.php
    [4] => /core/classes/repository/baseRepository.php
)

ファイルの命名ルールを決めていて、以下になります。

  • 管理画面で使うcontrollerの親classのファイル名は、adminとbaseという文字列が入ってなければなりません。
  • フロント画面で使うcontrollerの親classのファイル名は、frontとbaseという文字列が入ってなければなりません。
  • 親classの親class(基底class)のファイル名は、baseという文字列が入ってなければなりません。

手動なら問題ないんですが、scandir関数で指定したディレクトリ配下のファイルを取得する関数を作ってファイル取ってきているので、上記の形式で先にbaseAdminController.phpがくるんですね。

baseAdminController.phpはbaseController.phpを継承しているのでforeachでincludeするとbaseControllerは存在しないってエラーがでるんですね。

その措置として、上記ファイル配列の順番を変更する必要があります。

wordpressなんですけど、is_adminで管理画面じゃなければbaseAdminController.phpじゃなくてbaseFrontController.phpを取得してきます。
人間がわかるように説明すると、
ファイル名に((Admin か Front) と Base)を含んでいるファイルは、
ファイル名に(Admin か Front)を含まずBaseを含んでいるファイルよりも先に存在してはいけない。
です。

単なるsortではなく、システム固有のルールがあるのでそんな関数はないので自作しないとってところなんですが、このロジックが思い浮かばずです。

条件はわかっているのですが、単に「いるファイル、いらないファイル」なら条件に応じてcontinue$files[] = $crrentFileでいいのですが、並び替えなのでちょっと苦戦しています。詰めるところをどうするかです。

とりあえず書いていったらifififififとかなりそうで相談がてら投稿しました。
以下、作りかけです。

    /*
     * 親classを継承しているclassファイルが先に読み込まれないように配列の順番を変更する。
     *
     * @param    array   $fullPathFiles
     *
     * @return   array
     */
    public static function changingTheOrderOfCoreFiles($fullPathFiles)
    {
        if (!is_array($fullPathFiles)) {
            return false;
        }
        $getFiles  = array();
        $loopCount = 0;
        $previousIndexName = '';
        foreach ($fullPathFiles as $index => $fullPathFile) {

            if (!$loopCount) {
                continue;
            }

            // 前回のファイル名。
            $previousFileName = mb_strtolower(self::getFileName($fullPathFiles[$previousIndexName]));
            // 現在のファイル名。
            $currentFileName  = mb_strtolower(self::getFileName($fullPathFile));


            // 前回のファイル名に'Front or Admin' と 'Base'が含まれているか?
            if (
                (strpos($previousFileName, mb_strtolower(self::FRONT_IDENTIFIER)) !== false ||
                 strpos($previousFileName, mb_strtolower(self::ADMIN_IDENTIFIER)) !== false
                )
                && strpos($previousFileName, mb_strtolower(self::BASE_IDENTIFIER)) !== false
            ) {

                // 現在のファイル名に'Front or Admin' と 'Base'が含まれているか?
                if (
                    (strpos($currentFileName, mb_strtolower(self::FRONT_IDENTIFIER)) !== false ||
                     strpos($currentFileName, mb_strtolower(self::ADMIN_IDENTIFIER)) !== false
                    )
                    && strpos($currentFileName, mb_strtolower(self::BASE_IDENTIFIER)) !== false
                ) {



                }


            }

            ++$loopCount;
            $previousIndexName = $index;
        }
        return $getFiles;
    }

ちょっとだけ近づいてきたけどこれじゃ無限ループになってしまう。。。
プロパティーにflag的なものは持たせたくない。

    public static function changingTheOrderOfCoreFiles($fullPathFiles)
    {
        $getFiles = array();
        foreach ($fullPathFiles as $fullPathFile) {

            $fileName  = mb_strtolower(self::getFileName($fullPathFile));
            // ファイル名に'Front or Admin' が含まれておらず、 'Base'は含まれているか?
            if (
                (strpos($fileName, mb_strtolower(self::FRONT_IDENTIFIER)) === false ||
                 strpos($fileName, mb_strtolower(self::ADMIN_IDENTIFIER)) === false
                )
                && strpos($fileName, mb_strtolower(self::BASE_IDENTIFIER)) !== false
            ) {
                $getFiles[] = $fullPathFile;
            }
            // ファイル名に'Front or Admin' が含まれいて、 'Base'も含まれているか?
            if (
                (strpos($fileName, mb_strtolower(self::FRONT_IDENTIFIER)) !== false ||
                    strpos($fileName, mb_strtolower(self::ADMIN_IDENTIFIER)) !== false
                )
                && strpos($fileName, mb_strtolower(self::BASE_IDENTIFIER)) !== false
            ) {
                $getFiles = array_merge($getFiles, self::changingTheOrderOfCoreFiles(array($fullPathFile)));
            }
        }
        return $getFiles;
    }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2018/06/25 10:29

    「自作FW的なもの」と「wordpress」はどのような関係性なのでしょうか。

    キャンセル

  • kuzurotto

    2018/06/25 21:23

    リリースまで乞うご期待!!!

    キャンセル

  • mts10806

    2018/06/25 21:59

    あいえ。申し訳ないけどそういう興味はないので。

    キャンセル

回答 4

+2

条件だけ見ると「Admin か Front」を含むファイルを、配列の最後にもっていくだけで良い気がします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+1

私もタイトルだけ見て、usortだなと思って↓みたいのを書いてみました。

<?php
$list = [
    "/core/classes/controller/base/baseAdminController.php",
    "/core/classes/controller/base/baseController.php",
    "/core/classes/model/baseModel.php",
    "/core/classes/object/baseObject.php",
    "/core/classes/repository/baseRepository.php",
];

usort($list, function (string $a, string $b) {
    $fnameA = strtolower(basename($a));
    $fnameB = strtolower(basename($b));
    $priorA = (strpos($fnameA, "base") !== false && (strpos($fnameA, "admin") !== false || strpos($fnameA, "front") !== false)) ? -1 : 0;
    $priorB = (strpos($fnameB, "base") !== false && (strpos($fnameB, "admin") !== false || strpos($fnameB, "front") !== false)) ? -1 : 0;
    if($priorA === $priorB) { return $fnameA - $fnameB; }
    return ($priorA > $priorB) ? -1 : 1;
});
var_export($list);
/*
array (
  0 => '/core/classes/model/baseModel.php',
  1 => '/core/classes/controller/base/baseController.php',
  2 => '/core/classes/object/baseObject.php',
  3 => '/core/classes/repository/baseRepository.php',
  4 => '/core/classes/controller/base/baseAdminController.php',
)
*/

無名関数のところを適宜かえていけば、まあ色々とやれるのではないかとは思います。

ただ、フレームワークを意図しているのだとしたら、ファイル名もそうですが、ディレクトリの階層とかで制御したほうがいいようにも思いました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/25 21:26

    質問に合わせたサンプルがあって非常に良い回答であるといえます。
    ありがとございます。

    キャンセル

+1

リストからふたつを取り出して比較、前にあるか後ろにあるかを判別するだけで良い場合

function cmp($a, $b) {
    //条件
}
usort($fullPathFiles,"cmp");


PHP: usort - Manual

 比較結果が等しくなる二つの要素があった場合、ソートした配列におけるそれらの並び順は不定となります。 

とあるので、順番を極力維持したままソートしたい場合はforeach等を使う必要があります。

恐らくusortで事足りると思うので簡単な説明に留めますが、
for i=0 リストの0番目から最後まで
for j=i+1 リストのi+1番目から最後まで(i+1が範囲を超える時は実行しない)
// iよりもjの方を前に置きたい時は入れ替え
とすることで順番を維持したままソートは出来ます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/25 03:26

    以下のindex 0と1を入れ替えたい場合はどうなりますか?

    [0] => /core/classes/controller/base/baseAdminController.php
    [1] => /core/classes/controller/base/baseController.php
    [2] => /core/classes/model/baseModel.php
    [3] => /core/classes/object/baseObject.php
    [4] => /core/classes/repository/baseRepository.php

    キャンセル

+1

ちょっとぶち壊しな提案をしちゃいますが、
もしクラスの依存関係云々で読み込みの順番を調整したいってことなら
単純にspl_autoload_registerを使用することを提案します

autoload_functionで管理画面であるか否かによって
読みこむファイルを切り替えれば、
フロントと管理画面で使うクラスを切り替えることも簡単でしょう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    20302questions

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

  • アルゴリズム

    408questions

    アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。