サイト管理人Blog

cloudfreeで「さぁ始めましょう♪」

Laravelの更新分ファイルを自動抽出してサーバへあげる(リスト編)

2024-01-05 記載
概要 : Laravelの更新分ファイルを自動選択してサーバへあげる(リスト編)
Keyword : Laravel, FTP, PHP, 更新リスト,

WordPressはサーバで更新して、必要とあらばローカルにクローンを作成して、テスト動作を確認しています。これに対して最近始めたLaravelプロジェクトはartisanの処理がローカルでしか行えないので、ローカルで開発をすすめてサーバへあげる形になります。
データベースに関しては更新内容によってケースバイケースになるでしょう。これも migrate reset が可能な操作になりますので、サーバのデータを取り込んで更新をかけてまた戻す、という流れがの基本です。

とりあえず更新のあったファイルを抽出する処理をPHP+FTP関数で作成しましtあ。以前Wordpressのときに書いたコードがだいたいそのまま使えました。

phpのFTP関数でローカルファイルをサーバと同じにする処理を走らせる

ftp_mlsdがやはり強力で、ここでも頼りの綱です。
ところで、ディレクトリの更新日時というのは基本書き換えできないんですね。この処理を書いていて初めて知りました。しかしFTPソフトでタイムスタンプが揃っているの見たことあるようなないような。

膨大なファイル群のvenderを省いたり、キャッシュやtestは無視したりと、Laravelに特化したコードになりました。
処理はリストを作成するところまでです。そのリストに応じてのファイル転送はどうするかはまたの宿題。
当面はデバッグと勉強を兼ねて、リスト見ながらFileZillaで手作業です。

  mb_language('Japanese');
  mb_internal_encoding('UTF-8');
  date_default_timezone_set("Asia/Tokyo");
  setlocale(LC_ALL, 'ja_JP.UTF-8');

  $sJobkey = $_GET['jobkey'] ?? 'nop';

  $cParam = array();
  $cParam['dryrun'] = 'no';

  if ($sJobkey === 'nop') {
  } elseif ($sJobkey === 'makelist_update_server_laravel') {
  //FTPサーバ接続情報 
    $cParam['base_path_src'] = '/cfsid.cloudfree.jp/public_html/mywordpress/';
    $cParam['base_path_dest'] = 'c:/home/cfsid/cfsid.cloudfree.jp/public_html/mywordpress/';
    //ftp-cloudfree
    $ftp_cloudfree = getftp('svXX.cloudfree.ne.jp/cfsid_ftpuser@cfsid.cloudfree.jp/password');
    ftp_chdir($ftp_cloudfree, $cParam['base_path_src']);
    //ftp-local
    $ftp_local = getftp('localhost/ftpuser/password');
    ftp_chdir($ftp_local, '/cloudfree_home/cfsid/cfsid.cloudfree.jp/public_html/mywordpress/');

    //初期化
    $cParam['list'] = [];
    $cParam['except_folder'] = [];
    $cParam['except_list_preg_grep'] = [];

    //設定
    $cParam['subfolder'] = 'yes';
    //?jobkey=makelist_update_server_laravel&mode=scanall_setting2_setting3
    $cParam['scanall'] = (strpos($sMode, 'scanall') === false) ? 'no': 'yes';
    $cParam['except_folder'] += ['vendor/', 'tests/', 'storage/framework/', 'bootstrap/cache/'];
    $cParam['except_list_preg_grep'] += ['/^\.env/', '/storage\/logs\/laravel\.log/'];

    //サーバに更新をかけるファイルリスト作成
    MakeList_NotEqual_MDTM($ftp_local, $ftp_cloudfree, '', $cParam);
    echo '<hr>';
    foreach ($cParam['list'] as $item) {
      echo $item."<br>\n";
    }

    //$ftp 後始末
    ftp_close($ftp_cloudfree);
    ftp_close($ftp_local);
  }

  //$cParam['list'] 結果をここへ追加格納
  //$cParam['subfolder']='yes'ならサブフォルダも対象とし再帰関数として作動する
  function MakeList_NotEqual_MDTM($ftp_src, $ftp_dest, $sFolder, $cParam) {

    $aList = ftp_mlsd($ftp_src, $sFolder);

    //※ サーバにフォルダごと存在しない場合は 
    //   ftp_mlsd($ftp_dest, $sFolder)はfalseを返し、GetDic_mdtmは、[]を返す
    //   それで foreach内の $fExist は falseになるのでOK
    $aList_dest_mdtm = GetDic_mdtm(ftp_mlsd($ftp_dest, $sFolder));

    foreach($aList as $item) {
      if ($item['type'] == 'dir' && $cParam['subfolder'] == 'yes') {
        if ($cParam['scanall'] === 'yes' || !in_array($sFolder.$item['name'].'/', $cParam['except_folder'])) {
          //種類=フォルダで、サブフォルダ含めるで、除外フォルダの対象でない場合
          MakeList_NotEqual_MDTM($ftp_src, $ftp_dest, $sFolder.$item['name'].'/', $cParam);
        }
      } else if ($item['type'] == 'file') {
        $fExist = key_exists($item['name'], $aList_dest_mdtm);
        //除外ファイルの対象でないかを確認
        if ($cParam['scanall'] !== 'yes') {
          foreach ($cParam['except_list_preg_grep'] as $pattern) {
            if (preg_match($pattern, $sFolder.$item['name'])) {
              if ($fExist) unset($aList_dest_mdtm[$item['name']]);
              continue 2;
            }
          }
        }
        $src_mdtm = explode('.', $item['modify'])[0];
        if (!$fExist) {
          //Serverにはないファイル
          $sLine = '[NEW_SRC]';
        } elseif ($src_mdtm > $aList_dest_mdtm[$item['name']]) { 
          $sLine = '[UPD_SRC]';
        } elseif ($src_mdtm < $aList_dest_mdtm[$item['name']]) { 
          $sLine = '[UPD_DST_!?!]';
        } else {
          //更新日時が同一
          $sLine = '';
        }
        if (strpos($sLine, ']')) {
          $sLine .= $sFolder.$item['name'];
          echo $sLine."<br>\n";
          $cParam['list'][] = $sLine;
        }
        if ($fExist) unset($aList_dest_mdtm[$item['name']]);
      }
    }
    //サーバのみあるファイルに対して
    foreach(array_keys($aList_dest_mdtm) as $key) {
      $sLine = '[DEL_DST]'.$sFolder.$key;
      echo $sLine."<br>\n";
      $cParam['list'][] = $sLine;
    }
  }

  //FTPサーバへの接続
  function getftp($sServerVal) {
    $asServerVal = explode('/', $sServerVal);
    $ftp = ftp_connect($asServerVal[0]) or die("Couldn't connect to $asServerVal[0]");
    ftp_login($ftp, $asServerVal[1], $asServerVal[2]) or die("Couldn't login");
    return $ftp;
  }

  // 最終更新日時を'Y-m-d H:i:s'文字列として取得
  // "20230401235900"->"2023-04-01 23:59:00"
  function date_mdtm($sYmdHis) {
    $sYmdHis = explode('.', $sYmdHis)[0];
    return DateTime::createFromFormat('YmdHis', $sYmdHis, new DateTimeZone('UTC'))->format('Y-m-d H:i:s');
  }

  //※2023-12-24版より一部変更しました
  //ローカルファイルの最終更新日時をファイル名をkeyに取得する連想配列を返す
  // echo Dic_mdtm['index.html']; // '20230401235900' 
  function GetDic_mdtm($aList_dest) {
    $ret = [];
    if ($aList_dest) {
      // $aList_dest がfalse(null)になるのは フォルダごと存在しない場合
      foreach($aList_dest as $item) {
        if ($item['type'] === 'file') {
          $ret[$item['name']] = $item['modify'];
        }
      }
    }
    return $ret;
  }

投稿へのコメントは コチラ(掲示板) へお願いします。

サイト管理人Blog