発行元
Publisherライブラリは、堅牢な検出とエラーチェックを使用してプロジェクト内のファイルをコピーする手段を提供します。
ライブラリの読み込み
Publisherインスタンスは、そのソースと宛先に固有であるため、このライブラリはServices
経由では使用できませんが、直接インスタンス化または拡張する必要があります。例:
<?php
$publisher = new \CodeIgniter\Publisher\Publisher();
概念と使用方法
Publisher
は、バックエンドフレームワークで作業する場合のいくつかの一般的な問題を解決します。
バージョン依存関係を持つプロジェクトアセットをどのように維持しますか?
ウェブアクセスが必要なアップロードやその他の「動的」ファイルをどのように管理しますか?
フレームワークまたはモジュールが変更された場合、プロジェクトをどのように更新しますか?
コンポーネントが既存のプロジェクトに新しいコンテンツをどのように注入できますか?
最も基本的なレベルでは、公開はファイルまたはファイルをプロジェクトにコピーすることに相当します。Publisher
はFileCollection
を拡張して、流暢なスタイルのコマンドチェーンを使用して入力ファイルを読み取り、フィルタリング、処理し、次にそれらをターゲットの宛先にコピーまたはマージします。Publisher
は、コントローラーまたはその他のコンポーネントでオンデマンドで使用できます。または、クラスを拡張し、spark publish
を使用してその検出を活用することで、公開を準備できます。
オンデマンド
クラスの新しいインスタンスをインスタンス化することで、Publisher
に直接アクセスします。
<?php
$publisher = new \CodeIgniter\Publisher\Publisher();
デフォルトでは、ソースと宛先はそれぞれROOTPATH
とFCPATH
に設定され、Publisher
はプロジェクトから任意のファイルを取得してウェブアクセス可能にすることができます。あるいは、コンストラクターに新しいソース、またはソースと宛先を渡すこともできます。
<?php
use CodeIgniter\Publisher\Publisher;
$vendorPublisher = new Publisher(ROOTPATH . 'vendor');
$filterPublisher = new Publisher('/path/to/module/Filters', APPPATH . 'Filters');
// Once the source and destination are set you may start adding relative input files
$frameworkPublisher = new Publisher(ROOTPATH . 'vendor/codeigniter4/codeigniter4');
// All "path" commands are relative to $source
$frameworkPublisher->addPath('app/Config/Cookie.php');
// You may also add from outside the source, but the files will not be merged into subdirectories
$frameworkPublisher->addFiles([
'/opt/mail/susan',
'/opt/mail/ubuntu',
]);
$frameworkPublisher->addDirectory(SUPPORTPATH . 'Images');
すべてのファイルが準備できたら、出力コマンド(**copy()**または**merge()**)のいずれかを使用して、準備されたファイルを宛先に処理します。
<?php
// Place all files into $destination
$frameworkPublisher->copy();
// Place all files into $destination, overwriting existing files
$frameworkPublisher->copy(true);
// Place files into their relative $destination directories, overwriting and saving the boolean result
$result = $frameworkPublisher->merge(true);
使用可能なメソッドの完全な説明については、ライブラリリファレンスを参照してください。
自動化と検出
アプリケーションのデプロイまたは保守の一部として、定期的な公開タスクを含めることができます。Publisher
は強力なAutoloader
を活用して、公開のために準備された子クラスを探します。
<?php
use CodeIgniter\CLI\CLI;
use CodeIgniter\Publisher\Publisher;
foreach (Publisher::discover() as $publisher) {
$result = $publisher->publish();
if ($result === false) {
CLI::error(get_class($publisher) . ' failed to publish!', 'red');
}
}
デフォルトでは、discover()
はすべての名前空間で「Publishers」ディレクトリを検索しますが、別のディレクトリを指定することもでき、その場合は見つかった子クラスを返します。
<?php
use CodeIgniter\Publisher\Publisher;
$memePublishers = Publisher::discover('CatGIFs');
ほとんどの場合、独自の検出を処理する必要はありません。提供されている「publish」コマンドを使用してください。
php spark publish
デフォルトでは、クラス拡張publish()
は$source
からすべてのファイルを追加し、それらを宛先にマージし、衝突時には上書きします。
セキュリティ
モジュールがプロジェクトに悪意のあるコードを注入するのを防ぐために、Publisher
には、宛先として許可されるディレクトリとファイルパターンを定義する設定ファイルが含まれています。デフォルトでは、ファイルはプロジェクトにのみ公開できます(ファイルシステムの残りの部分へのアクセスを防ぐため)、そして**public/**フォルダ(FCPATH
)は次の拡張子を持つファイルのみを受け取ります。
ウェブアセット:css、scss、js、map
実行不可のウェブファイル:htm、html、xml、json、webmanifest
フォント:ttf、eot、woff、woff2
画像:gif、jpg、jpeg、tif、tiff、png、webp、bmp、ico、svg
プロジェクトのセキュリティを追加または調整する必要がある場合は、**app/Config/Publisher.php**内のConfig\Publisher
の$restrictions
プロパティを変更してください。
例
いくつか使用例とその実装を以下に示します。公開を開始するのに役立ちます。
ファイル同期例
ホームページに「今日の写真」画像を表示したいとします。毎日の写真フィードがありますが、プロジェクトの参照可能な場所にある**public/images/daily_photo.jpg**に実際のファイルを取得する必要があります。カスタムコマンドを設定して、毎日実行することで、これを処理できます。
<?php
namespace App\Commands;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\Publisher\Publisher;
use Throwable;
class DailyPhoto extends BaseCommand
{
protected $group = 'Publication';
protected $name = 'publish:daily';
protected $description = 'Publishes the latest daily photo to the homepage.';
public function run(array $params)
{
$publisher = new Publisher('/path/to/photos/', FCPATH . 'assets/images');
try {
$publisher->addPath('daily_photo.jpg')->copy(true); // `true` to enable overwrites
} catch (Throwable $e) {
$this->showError($e);
}
}
}
これでspark publish:daily
を実行すると、ホームページの画像が最新の状態に保たれます。写真が外部APIから取得されている場合はどうでしょうか?addPath()
の代わりにaddUri()
を使用して、リモートリソースをダウンロードして公開することができます。
<?php
$publisher->addUri('https://example.com/feeds/daily_photo.jpg')->copy(true);
アセット依存関係の例
フロントエンドライブラリ「Bootstrap」をプロジェクトに統合したいが、頻繁なアップデートのために最新の状態を維持するのが面倒です。プロジェクトでPublisher
を拡張して、プロジェクトに公開定義を作成することで、フロントエンドアセットを同期できます。そのため、**app/Publishers/BootstrapPublisher.php**は次のようになるかもしれません。
<?php
namespace App\Publishers;
use CodeIgniter\Publisher\Publisher;
class BootstrapPublisher extends Publisher
{
/**
* Tell Publisher where to get the files.
* Since we will use Composer to download
* them we point to the "vendor" directory.
*
* @var string
*/
protected $source = VENDORPATH . 'twbs/bootstrap/';
/**
* FCPATH is always the default destination,
* but we may want them to go in a sub-folder
* to keep things organized.
*
* @var string
*/
protected $destination = FCPATH . 'bootstrap';
/**
* Use the "publish" method to indicate that this
* class is ready to be discovered and automated.
*/
public function publish(): bool
{
return $this
// Add all the files relative to $source
->addPath('dist')
// Indicate we only want the minimized versions
->retainPattern('*.min.*')
// Merge-and-replace to retain the original directory structure
->merge(true);
}
}
注記
ディレクトリ$destination
は、コマンドを実行する前に作成する必要があります。
Composer経由で依存関係を追加し、spark publish
を呼び出して公開を実行します。
composer require twbs/bootstrap
php spark publish
…すると、次のようになります。
public/.htaccess
public/favicon.ico
public/index.php
public/robots.txt
public/
bootstrap/
css/
bootstrap.min.css
bootstrap-utilities.min.css.map
bootstrap-grid.min.css
bootstrap.rtl.min.css
bootstrap.min.css.map
bootstrap-reboot.min.css
bootstrap-utilities.min.css
bootstrap-reboot.rtl.min.css
bootstrap-grid.min.css.map
js/
bootstrap.esm.min.js
bootstrap.bundle.min.js.map
bootstrap.bundle.min.js
bootstrap.min.js
bootstrap.esm.min.js.map
bootstrap.min.js.map
モジュール展開例
人気の認証モジュールを使用する開発者が、マイグレーション、コントローラー、モデルのデフォルト動作を拡張できるようにしたいとします。アプリケーションで使用するためにこれらのコンポーネントを注入する独自のモジュール「publish」コマンドを作成できます。
<?php
namespace Math\Auth\Commands;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\Publisher\Publisher;
use Throwable;
class AuthPublish extends BaseCommand
{
protected $group = 'Auth';
protected $name = 'auth:publish';
protected $description = 'Publish Auth components into the current application.';
public function run(array $params)
{
// Use the Autoloader to figure out the module path
$source = service('autoloader')->getNamespace('Math\\Auth')[0];
$publisher = new Publisher($source, APPPATH);
try {
// Add only the desired components
$publisher->addPaths([
'Controllers',
'Database/Migrations',
'Models',
])->merge(false); // Be careful not to overwrite anything
} catch (Throwable $e) {
$this->showError($e);
return;
}
// If publication succeeded then update namespaces
foreach ($publisher->getPublished() as $file) {
// Replace the namespace
$contents = file_get_contents($file);
$contents = str_replace('namespace Math\\Auth', 'namespace ' . APP_NAMESPACE, $contents);
file_put_contents($file, $contents);
}
}
}
これで、モジュールユーザーがphp spark auth:publish
を実行すると、プロジェクトに以下が追加されます。
app/Controllers/AuthController.php
app/Database/Migrations/2017-11-20-223112_create_auth_tables.php.php
app/Models/LoginModel.php
app/Models/UserModel.php
ライブラリリファレンス
注記
Publisher
はFileCollectionの拡張なので、ファイルの読み取りとフィルタリングのためのすべてのメソッドにアクセスできます。
サポートメソッド
[static] discover(string $directory = ‘Publishers’): Publisher[]
指定された名前空間ディレクトリ内のすべてのPublisherを検出し、返します。たとえば、**app/Publishers/FrameworkPublisher.php**と**myModule/src/Publishers/AssetPublisher.php**の両方が存在し、Publisher
を拡張している場合、Publisher::discover()
はそれぞれのインスタンスを返します。
publish(): bool
完全な入力-処理-出力チェーンを処理します。デフォルトでは、addPath($source)
とmerge(true)
を呼び出すことと同等ですが、子クラスでは通常、独自のインプリメンテーションを提供します。spark publish
を実行すると、検出されたすべてのPublisherでpublish()
が呼び出されます。成功または失敗を返します。
getScratch(): string
一時ワークスペースを返し、必要に応じて作成します。一部の操作では、ファイルをステージングし、変更するために中間ストレージを使用します。これは、一時的な書き込み可能なディレクトリのパスを提供し、必要に応じて使用できます。
getErrors(): array<string, Throwable>
最後の書き込み操作からのエラーを返します。配列のキーはエラーの原因となったファイルであり、値はキャッチされたThrowableです。Throwableに対してgetMessage()
を使用すると、エラーメッセージを取得できます。
addPath(string $path, bool $recursive = true)
相対パスで示されたすべてのファイルを追加します。パスは、$source
に対する実際のファイルまたはディレクトリへの参照です。相対パスがディレクトリを解決する場合、$recursive
にはサブディレクトリが含まれます。
addPaths(array $paths, bool $recursive = true)
相対パスで示されたすべてのファイルを追加します。パスは、$source
に対する実際のファイルまたはディレクトリへの参照です。相対パスがディレクトリを解決する場合、$recursive
にはサブディレクトリが含まれます。
addUri(string $uri)
CURLRequest
を使用してURIの内容をスクラッチワークスペースにダウンロードし、結果のファイルをリストに追加します。
addUris(array $uris)
CURLRequest
を使用してURIの内容をスクラッチワークスペースにダウンロードし、結果のファイルをリストに追加します。
注記
行われるCURLリクエストは単純なGET
であり、ファイルの内容にはレスポンスボディが使用されます。一部のリモートファイルは、適切に処理するためにカスタムリクエストが必要になる場合があります。
ファイルの出力
wipe()
$destination
からすべてのファイル、ディレクトリ、およびサブディレクトリを削除します。
重要
賢く使いましょう。
copy(bool $replace = true): bool
すべてのファイルを$destination
にコピーします。ディレクトリ構造は再作成されません。そのため、現在のリストのすべてのファイルは同じ宛先ディレクトリに配置されます。$replace
を使用すると、既に存在するファイルがある場合にファイルが上書きされます。成功または失敗を返します。getPublished()
とgetErrors()
を使用して、失敗のトラブルシューティングを行います。重複したbasenameの衝突(例:同じ名前のファイルが複数ある場合)に注意してください。
<?php
use CodeIgniter\Publisher\Publisher;
$publisher = new Publisher('/home/source', '/home/destination');
$publisher->addPaths([
'pencil/lead.png',
'metal/lead.png',
]);
// This is bad! Only one file will remain at /home/destination/lead.png
$publisher->copy(true);
merge(bool $replace = true): bool
すべてのファイルを適切な相対サブディレクトリ内の$destination
にコピーします。$source
と一致するファイルは、$destination
の同等のディレクトリに配置され、「ミラー」または「rsync」操作が効果的に作成されます。$replace
を使用すると、既に存在するファイルがある場合にファイルが上書きされます。ディレクトリがマージされるため、これは宛先内の他のファイルには影響しません。成功または失敗を返します。getPublished()
とgetErrors()
を使用して、失敗のトラブルシューティングを行います。
例
<?php
use CodeIgniter\Publisher\Publisher;
$publisher = new Publisher('/home/source', '/home/destination');
$publisher->addPaths([
'pencil/lead.png',
'metal/lead.png',
]);
// Results in "/home/destination/pencil/lead.png" and "/home/destination/metal/lead.png"
$publisher->merge();
ファイルの修正
replace(string $file, array $replaces): bool
バージョン4.3.0の新機能。
$file
の内容を置き換えます。2番目のパラメーター$replaces
配列は、検索文字列をキーとして、置換文字列を値として指定します。
<?php
use CodeIgniter\Publisher\Publisher;
$source = service('autoloader')->getNamespace('CodeIgniter\\Shield')[0];
$publisher = new Publisher($source, APPPATH);
$file = APPPATH . 'Config/Auth.php';
$publisher->replace(
$file,
[
'use CodeIgniter\Config\BaseConfig;' . "\n" => '',
'class App extends BaseConfig' => 'class App extends \Some\Package\SomeConfig',
]
);
addLineAfter(string $file, string $line, string $after): bool
バージョン4.3.0の新機能。
特定の文字列$after
を含む行の後に$line
を追加します。
<?php
use CodeIgniter\Publisher\Publisher;
$source = service('autoloader')->getNamespace('CodeIgniter\\Shield')[0];
$publisher = new Publisher($source, APPPATH);
$file = APPPATH . 'Config/App.php';
$publisher->addLineAfter(
$file,
' public int $myOwnConfig = 1000;', // Adds this line
'public bool $CSPEnabled = false;' // After this line
);
addLineBefore(string $file, string $line, string $after): bool
バージョン4.3.0の新機能。
特定の文字列$after
を含む行の前に$line
を追加します。
<?php
use CodeIgniter\Publisher\Publisher;
$source = service('autoloader')->getNamespace('CodeIgniter\\Shield')[0];
$publisher = new Publisher($source, APPPATH);
$file = APPPATH . 'Config/App.php';
$publisher->addLineBefore(
$file,
' public int $myOwnConfig = 1000;', // Add this line
'public bool $CSPEnabled = false;' // Before this line
);