- 投稿日:2020-11-20T19:54:42+09:00
Laravel の FormRequest を全体的に、実態に近く自動テストする
はじめに
Laravel の FormRequest のテストの話は rules() のテストだけなのが多いので、rules() 以外も含む FormRequest 全体を、より実態に近くテストする話をする
テスト
以降は次を use する前提
use App\Http\Requests\HogeRequest; use Illuminate\Http\Request; use Illuminate\Validation\ValidationException;全体なので FormRequest の passedValidation() や failedValidation() の実装の影響を受ける
以降はこれらがデフォルトの実装の前提。上書くときはその処理に従う。成功することをテストする
FormRequest がサービスコンテナによる解決によって効果を得ることをテストする
public function testPass() { $attributes = ['key' => 'value']; // FormRequest が依存する Request に入力値をセット $this->app->make(Request::class)->replace($attributes); // Controller で DI するのと同じ効果を得る $request = $this->app->make(HogeRequest::class); // risky になるので assert $this->assertInstanceOf(HogeRequest::class, $request); }失敗することをテストする
public function testFail() { $attributes = ['key' => null]; // FormRequest が依存する Request に入力値をセット $this->app->make(Request::class)->replace($attributes); // Controller で DI すると例外が投げられるのと同じ効果を得る $this->expectException(ValidationException::class); $this->app->make(HogeRequest::class); }おわりに
サービスコンテナによる解決によって、rules() 以外も含む FormRequest 全体を、より実態に近くテストできる
- 投稿日:2020-11-20T17:15:56+09:00
Read DoubleのComposerでLaravelインストールで躓いたところ
Read DoubleのComposerでLaravelインストールで躓いたところ
プログラミング学習歴1年未満の初心者がLaravelをインストールするまでの道のり。
laravel公式(日本語ver)と言われるRead Doubleだけではわからなかったため途中、調べたところを追加。使用環境(動作環境)
- windows10Home(COREi7)
- xampp7.3.18
Composerシステム全体のvendor/binディレクトリを$PATHへ登録してくださいって何?
$PATHへ登録する=PATHを通す=環境変数(環境パス)に登録する
環境パスのことすらわからなかった(多分これまでも環境構築で設定してきたはず)PATHを通すとは
特定のプログラムを「プログラム名だけで実行できるようにする」こと。
もっと言うと、プログラム名だけで実行できるようにするために、PATH という環境変数(設定の一種)に「このプログラムも名前だけで実行できるようにしてください」という値を追加すること。
「PATHを通す」の意味をできるだけわかりやすく説明する試み
もっとわかりやすく言うと、拡張子が「.exe」のファイルの実行を簡単にするための手段みたいだね。
環境パスはどこで設定するの?
コントロールパネル → システムとセキュリティ → システム → システムの詳細設定(ちなみにコントロールパネルはwindowsシステムツールの中にあるよ!)
環境変数を押すと以下の画面の「システム環境変数」の「Path」をクリック → 「編集」 → 「新規」で「%USERPROFILE%\AppData\Roaming\Composer\vendor\bin」を追加
(ここの%USERPROFIEL%は「C:\Users\ユーザーネーム」みたいな感じ)
これでComposerシステム全体のvendor/binディレクトリを$PATHへ登録が完了。
次に躓いたのはpublicディレクトリの設定
ドキュメントルートがpublicディレクトリになるように設定してくださいということなんだけどそもそもドキュメントルートって何?状態。
ドキュメントルート(DocumentRoot)とはWeb上に公開することのできるディレクトリのルートのことです。
設定方法としては,見せたいディレクトリのパスを指定をします。すると,そのディレクトリ配下のファイルへすべてアクセスができるようになります。
たとえば,DocumentRoot直下にfoo.htmlというファイルを配置をします。するとhttp://servername/foo.html
というURLで対象のファイルにアクセスをすることができます。
第8回 知っておきたいapacheの基礎知識 その4つまりたくさんディレクトリ(フォルダ)があるんだけど、ドキュメントルートとして設定したディレクトリの中身が公開されますよということ。
この設定方法にはいろいろあるんだけど私は次の方法でドキュメントルートをLaravelプロジェクトの中のpublicに変更しました。
(ちなみに今回紹介する方法ではLaravelプロジェクトごとに(イメージとしてはアプリを作るごと)ドキュメントルートの設定を変えることになります。どうやらlocalhost名?をプロジェクトごとに設定したりもできる(いちいちプロジェクトごとにドキュメントルートを変更しなくても良い)方法があるみたいなのですが私にはまだわかりません;;)Laravelプロジェクトのpublicをドキュメントルートに設定する方法~apache下で使用
今回はxampp内のhtdocs内にLaravelプロジェクトを生成しています。(推奨されていないようですが)
ファイル操作します
「XAMPP」 → 「apache」 → 「conf」の中の「httpd.conf」を設定変更
このときhttpd.confファイルはコピーしてhttpd_backup.confなどに名前変更してバックアップを保存しておいてください。httpd.confファイルを開いたら、「DocumentRoot "C:/xampp/htdocs"」という行を探す
変更前:DocumentRoot "C:/xampp/htdocs"
変更後:C:/xampp/htdocs/Laravelプロジェクト作成時の名前/public
- 次に「ブロック」を探す (2か所あるのですが2か所とも変更で良いのかどなたか教えていただけると助かります)
変更前:
\<Directory "C:/xampp/htdocs"> ... \</Directory>変更後:
\<Directory "C:/xampp/htdocs/Laravelプロジェクト作成時の名前/public"> ... \</Directory>(xamppのドキュメントルートは「htdocs」フォルダ)
(ちなみにxamppの中にはapacheが入っているよ)
- この2点をLaravelのプロジェクトが変わるごとに変えるという方法です。 (少し手間はかかるし同時にプロジェクトを進行しにくいのであまり良い方法ではないかもしれません。)
その次に躓いたのはディレクトリパーミッションの設定
どうやらフォルダへのアクセス権限を変更せよということらしい。
聞いたところ、Macだとエラーが出て設定が必要になることがあるのだけれど、windowsだとエラーが出ず、設定が必要ないかもしれないとのこと。
以上、躓きまくりましたがなんとかLaravelをインストールできた。
そしたらなんと、Laravel 8.11.2をインストールしていたので再インストールを検討中...おまけ
virtual hostの設定もしたのでそれについては別記事にまとめたいと思っています。
- 投稿日:2020-11-20T17:14:35+09:00
【PHP】単数系の英語を複数形に直す
PHPの初学者です。
作ったコードをQiitaに書く様にしていきたいと思います。
・末尾がs, sh, ch, o, x である場合英単語の末尾にesを付ける
・末尾がf, fe のいずれかである英単語の末尾の f, fe を除き、末尾に ves を付ける
・末尾の1文字がyで、末尾から2文字目がa, i, u, e, oのいずれでもない英単語の末尾の y を除き、末尾に ies を付ける
・上4つに当てはまらないものにはsを付けるfunction SingularToPlural($in) { //不規則変換用の辞書 $dictionary = [ 'child' => 'children', 'crux' => 'cruces', 'foot' => 'feet', 'knife' => 'knives', 'leaf' => 'leaves', 'louse' => 'lice', 'man' => 'men', 'medium' => 'media', 'mouse' => 'mice', 'oasis' => 'oases', 'person' => 'people', 'phenomenon' => 'phenomena', 'seaman' => 'seamen', 'snowman' => 'snowmen', 'tooth' => 'teeth', 'woman' => 'women', ]; //先に不規則変換をチェックしてから変換を行う if (array_key_exists($in, $dictionary)) { return $dictionary[$in]; } else { $Singular = $in; $Singular = preg_replace("/(s|sh|ch|o|x)$/", "$1es", $Singular); $Singular = preg_replace("/(f|fe)$/", "ves", $Singular); $Singular = preg_replace("/(a|i|u|e|o)y$/", "$1ys", $Singular); $Singular = preg_replace("/y$/", "ies", $Singular); if (!preg_match("/s$/", $Singular)) { $Singular = $Singular . "s"; } return $Singular; } } //単語毎に改行してある入力を想定、それをループ処理で取得する while ($line = fgets(STDIN)) { $array[] = trim($line); } foreach ($array as $row) { } foreach ($array as $value) { echo SingulartoPlural($value) . "\n"; } ?>
- 投稿日:2020-11-20T16:45:42+09:00
ffmpegで動画を連結する備忘録
PHPから実行した際の備忘録。
連結する全動画の画角、コーデックが同じであること。file_list.txtfile '/var/***/1.mp4' file '/var/***/2.mp4' file '/var/***/3.mp4' file '/var/***/4.mp4' file '/var/***/5.mp4'# 動作確認済み $cmd = "ffmpeg -f concat -safe 0 -i {file_list_path} -c copy {output_local_path}.mp4"; system($cmd); # こっちは未テスト $cmd = "ffmpeg -f concat -safe 0 -i {file_list_path} -c:v copy c:a copy {output_local_path}.mp4"; system($cmd);
- -f concat
- 連結指示
- -safe 0
- file_list.txt 内でファイルパスを絶対パスで指定する際に必要とのこと
- {file_list_path}
- 連結するファイルのパスを書いたテキストファイルパス
- -c copy
- オリジナルのコーデックを再エンコードしない(無劣化)
- -c:v copy
- ビデオコーデックを再エンコードしない(無劣化)
- -c:a copy
- オーディオコーデックを再エンコードしない(無劣化)
- 投稿日:2020-11-20T16:45:42+09:00
ffmpegで動画を連結する
PHPから実行した際の備忘録。
連結する全動画の画角、コーデックが同じであること。file_list.txtfile '/var/***/1.mp4' file '/var/***/2.mp4' file '/var/***/3.mp4' file '/var/***/4.mp4' file '/var/***/5.mp4'# 動作確認済み $cmd = "ffmpeg -f concat -safe 0 -i {file_list_path} -c copy {output_local_path}.mp4"; system($cmd); # こっちは未テスト $cmd = "ffmpeg -f concat -safe 0 -i {file_list_path} -c:v copy c:a copy {output_local_path}.mp4"; system($cmd);
- -f concat
- 連結指示
- -safe 0
- file_list.txt 内でファイルパスを絶対パスで指定する際に必要とのこと
- {file_list_path}
- 連結するファイルのパスを書いたテキストファイルパス
- -c copy
- オリジナルのコーデックを再エンコードしない(無劣化)
- -c:v copy
- ビデオコーデックを再エンコードしない(無劣化)
- -c:a copy
- オーディオコーデックを再エンコードしない(無劣化)
- 投稿日:2020-11-20T15:14:18+09:00
Laravel 6 画像のアップロード
環境
・Laravel 6.18.43
・PHP 7.3.11
・ブラウザ:クローム画面構成
フォーム
ファイルと商品名を入力します。
確認画面
確認画面を表示します。
input->confirmの際に一度Storage/app/public内のtempディレクトリに仮保存し、
confirm->completeの際にStorage/app/public内のproductImageディレクトリに移動します。
完了画面
完了画面です。
ソース
まずはルーティングを作成。
web.phpRoute::get('/image_input', 'ImageController@getImageInput'); Route::post('/image_confirm', 'ImageController@postImageConfirm'); Route::post('/image_complete', 'ImageController@postImageComplete');続いてフォームの作成。
formタグ内でenctype="multipart/form-dataを記述する必要があるようです。imege_input.blade.php<form action="image_confirm" method="post" enctype="multipart/form-data" id="form"> @csrf <p>ファイル:</p> <input type="file" name="imagefile" value=""/><br /><br /> <p>商品名:</p><br /> <input type="text" name="product_name" size="50" value="{{ old('name') }}"/><br /><br /> <input type="submit" name="confirm" id="button" value="確認" /> </form>確認画面
image_comfirm.blade.php<form action="image_complete" method="post"> @csrf <table border="1"> <tr> <td>画像</td> <td><img src="{{ $data['read_temp_path'] }}" width="200" height="130"></td> </tr> <tr> <td>商品名</td> <td>{{ $data['product_name'] }}</td> </tr> </table> <input type="submit" name="action" value="送信" /> </form>完了画面
image_complete.blade.php<p>商品のアップロードが完了しました</p> <img src="{{ $product->path }}" width="200" height="130">また、DBは次のmigrationファイルを基にして作り、Modelも作成しておきます。
xxxx_xx_xx_xxxxxx_create_products_table.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateProductsTable extends Migration { public function up() { Schema::create('products', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('path'); $table->string('product_name'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('products'); } }コントローラー
フォームから画像と名前を受け取って、画像には一意のファイル名としてtempディレクトリに保存します。
また、sessionに保存して、confirm画面から読み込めるようにします。
useの記述漏れに注意。imageController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Product; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage; class ImageController extends Controller { public function getImageInput(){ return view('image_input'); } public function postImageConfirm(Request $request){ $post_data = $request->except('imagefile'); $imagefile = $request->file('imagefile'); $temp_path = $imagefile->store('public/temp'); $read_temp_path = str_replace('public/', 'storage/', $temp_path); //追加 $product_name = $post_data['product_name']; $data = array( 'temp_path' => $temp_path, 'read_temp_path' => $read_temp_path, //追加 'product_name' => $product_name, ); $request->session()->put('data', $data); return view('image_confirm', compact('data') ); } public function postImageComplete(Request $request) {//getをpostに変更 $data = $request->session()->get('data'); $temp_path = $data['temp_path']; $read_temp_path = $data['read_temp_path']; $filename = str_replace('public/temp/', '', $temp_path); //ファイル名は$temp_pathから"public/temp/"を除いたもの $storage_path = 'public/productimage/'.$filename; //画像を保存するパスは"public/productimage/xxx.jpeg" $request->session()->forget('data'); Storage::move($temp_path, $storage_path); //Storageファサードのmoveメソッドで、第一引数->第二引数へファイルを移動 $read_path = str_replace('public/', 'storage/', $storage_path); //商品一覧画面から画像を読み込むときのパスはstorage/productimage/xxx.jpeg" $product_name = $data['product_name']; $product = new Product; $product->path = $read_path; $product->product_name = $product_name; $product->save(); return view('image_complete', compact('product')); } }シンボリックリンク
Laravel で作ったアプリケーションが公開されるとき、公開されるのは一番上の階層にある public ディレクトリのみです。public ディレクトリにファイルや処理のすべてが集約されています。なので、保存した画像も public ディレクトリ内に存在しないとアクセスすることができません。そこでシンボリックリンクを利用して storage ディレクトリにアクセスできるようにします。
Laravelの場合、画像を読み込むディレクトリはpublic/storageディレクトリです。
なのでpublic/storageから、storage/app/public内を読み込めるよう(シンボリックリンクを張る)にします。
保存:storage/app/public
読込:public/storageシンボリックリンクは Artisan コマンドで作成できます。
php artisan storage:linkこれで、storage/app/public内を覗けるようになりました。
参考サイト
- 投稿日:2020-11-20T15:12:00+09:00
laravel/ui リダイレクト先変更方法
特に解説はありません。
app/Providers/RouteServiceProvider.phpを開き
HOMEプロパティに格納している値を変更
RouteServiceProvider.php..... class RouteServiceProvider extends ServiceProvider { /** * This namespace is applied to your controller routes. * * In addition, it is set as the URL generator's root namespace. * * @var string */ protected $namespace = 'App\Http\Controllers'; /** * The path to the "home" route for your application. * * @var string */ public const HOME = 'HOME';#<=任意のリダイレクト先に変更 /** .....例
homeからwelcame画面にしたい場合RouteServiceProvider.phppublic const HOME = '/';
- 投稿日:2020-11-20T15:12:00+09:00
laravel/ui ログイン後のリダイレクト先変更方法
特に解説はありません。
app/Providers/RouteServiceProvider.phpを開き
HOMEプロパティに格納している値を変更
RouteServiceProvider.php..... class RouteServiceProvider extends ServiceProvider { /** * This namespace is applied to your controller routes. * * In addition, it is set as the URL generator's root namespace. * * @var string */ protected $namespace = 'App\Http\Controllers'; /** * The path to the "home" route for your application. * * @var string */ public const HOME = 'HOME';#<=任意のリダイレクト先に変更 /** .....例
homeからwelcame画面にしたい場合RouteServiceProvider.phppublic const HOME = '/';
- 投稿日:2020-11-20T12:21:00+09:00
Local by flywheel で、admin押したらThis site can’t be reachedが出て管理画面が出ない
現在存在するwordpressのローカル環境構築方法で一番簡単なのは、Local by flywheelだと思うのですが、手持ちのMac(OS 10.13.6)だと、This site can’t be reachedというエラーが出てしまって、管理画面にもサイト画面にもアクセス不可の状態でした。
Local by flywheelはまだ新しいからか、ネット上にある解決方法も少なめ。
検索能力が低めなので、ググってもしても、Local by flywheelのおすすめ記事にしか到達できず、質問コミュニティでヘルプを求めたところ、色々なアドバイスをいただいた。
結果的には、PC再起動で直りました
しかし、そこにたどり着くまでにプログラミング初心者の自分にはとても思いつかないようなファイルなどをチェックしたので、今後サーバー関連で問題が起こった時はどこをチェックすればいいのかの記録を残したいと思います。
環境
・MacOS 13.10.6 High Sierra
やった事① etc/hosts を確認
って思ったので、とりあえずそのままにググる。
「ホスト名とIPアドレスを対応させるためのファイル」らしい。Macの場合はterminalを開いて、以下コマンドを実行すれば中身が見れる
$cat /private/etc/hosts
その中に以下のようなLocal by Flywheelの表記があればhosts の更新はできているらしい。
# Local by Flywheel - Start ## ::1 testsitecom.local #Local Site 127.0.0.1 testsitecom.local #Local Site ::1 www.testsitecom.local #Local Site 127.0.0.1 www.testsitecom.local #Local Siteやった事② MAMP, XAMMPなどのApacheサーバーと衝突していないか確認
私の場合は、上述したような表記があったので、hostsの更新ができている状態だった。
とすれば考えられるのは、別ツールで作ったApacheと衝突しているかもとのことで、こちらも助言をいただいた通りにチェックしてみた。①Local を終了
②アクティビティモニタ (Applications -> Utilities) を開いて Process Name のなかにapache か nginx, httpdがあれば x ボタンで止める。(検索ボタンがあるので、それらを検索してなければok)
私の場合は、それもありませんでした。
やった事③ Localの古いバージョンをインストールしてみる
こちらのサイト様のローカル開発環境 Local by Flywheel エラー検証「Missing hosts entry…」を参考に、古いLocalのバージョンをインストールしてみました。
古いバージョンのインストールはこちら
が、This site can’t be reachedが出るのは変わらず..。
*備考 : ちなみに上記サイトの既存サイトをLocal by Flywheelでローカル開発環境へインポート とかの記事もすごく勉強になります。
やった事④ping testsitecom.localの応答を確認
teminal.$ping testsitecom.local #コマンド実行で以下のような応答があればok. 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.064 ms 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.069 ms 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.093 ms 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.102 msわたしの場合は、これはきちんと応答があったので問題なかったらしい。
やった事⑤ logの確認
Localの画面左側の testsite.com を control + click で Reveal in Finder とするとapp, conf, logsなどのフォルダが開ける。
この logs/nginx/error.log もしくはapache/error.logにはエラーの記録が残ってないか確認わたしの場合は、apache/error.logの中に以下のような記述があった
apache/error.loglogs/apache/error.log↓ AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using MacBook.local. Set the 'ServerName' directive globally to suppress this message [日付など〜] [mpm_event:notice] [pid 91617:tid 16桁の数字] 〜Local by flywheelのエラーログってこうやって見ればいいのか..
PC本体を再起動する
前述したように、最終的にはこんな簡単な手段で直りました。
サーバー関連は、再起動を一度してみるといいらしいです。
その際こちらのLocalについて書いてある海外サイトのリンクをいただきました。今回わたしも質問サイトで調べる前に結構ググったのですが、何日かけても答えにたどり着けなかったのにも関わらず、質問サイトの回答者さんは1日もかからずにこのサイトにたどり着き解決まで導いてくださいました。
プログラミングをしていると、こういったエラーは頻繁に起こります。ネットでググって答えにたどり着ける力をもっとつけないとなと思いました。
- 投稿日:2020-11-20T12:21:00+09:00
Local by flywheel で、admin押したらThis site can’t be reachedが出る。
現在存在するwordpressのローカル環境構築方法で一番簡単なのは、Local by flywheelだと思うのですが、手持ちのMac(OS 10.13.6)だと、This site can’t be reachedというエラーが出てしまって、管理画面にもサイト画面にもアクセス不可の状態でした。
Local by flywheelはまだ新しいからか、ネット上にある解決方法も少なめ。
検索能力が低めなので、ググってもしても、Local by flywheelのおすすめ記事にしか到達できず、質問コミュニティでヘルプを求めたところ、etc/hostsファイルをチェックしろとの助言をいただいた。
結論: PC再起動で直った
再起動で直りました。しかし、そこにたどり着くまでに色々なステップを踏みました。今後サーバー関連で問題が起こった時はどこをチェックすればいいのかの記録を残したいと思います。
やった事① etc/hosts を確認
って思ったので、とりあえずそのままにググる。
「ホスト名とIPアドレスを対応させるためのファイル」らしい。Macの場合はterminalを開いて、以下コマンドを実行すれば中身が見れる
$cat /private/etc/hosts
その中に以下のようなLocal by Flywheelの表記があればhosts の更新はできているらしい。
# Local by Flywheel - Start ## ::1 testsitecom.local #Local Site 127.0.0.1 testsitecom.local #Local Site ::1 www.testsitecom.local #Local Site 127.0.0.1 www.testsitecom.local #Local Siteやった事② MAMP, XAMMPなどのApacheサーバーと衝突していないか確認
私の場合は、上述したような表記があったので、hostsの更新ができている状態だった。
とすれば考えられるのは、別ツールで作ったApacheと衝突しているかもとのことで、こちらも助言をいただいた通りにチェックしてみた。①Local を終了
②アクティビティモニタ (Applications -> Utilities) を開いて Process Name のなかにapache か nginx があれば x ボタンで止める。しかし私の場合は、それもなかった。。
やった事③ Localの古いバージョンをインストールしてみる
こちらのサイト様のローカル開発環境 Local by Flywheel エラー検証「Missing hosts entry…」を参考に、古いLocalのバージョンをインストールしてみました。
古いバージョンのインストールはこちら
が、This site can’t be reachedが出るのは変わらず..。
やった事④PC本体を再起動する
サーバー関連は、再起動を一度してみるといいらしいです。
その際こちらのLocalについて書いてある海外サイトのリンクをいただきました。今回わたしも質問サイトで調べる前に結構ググったのですが、何日かけても答えにたどり着けなかったのにも関わらず、質問サイトの回答者さんは1日もかからずにこのサイトにたどり着き解決まで導いてくださいました。
プログラミングをしていると、こういったエラーは頻繁に起こります。ネットでググって答えにたどり着ける力をもっとつけないとなと思いました。
*備考 : ちなみに上記サイトの既存サイトをLocal by Flywheelでローカル開発環境へインポート とかの記事もすごく勉強になります。
- 投稿日:2020-11-20T12:10:36+09:00
Laravel8 CRUD処理を使った投稿アプリを作成する その10 URLをリンク化する
目的
- 投稿内容の文字列中にURLがあったときにリンク化する方法をまとめる
実施環境
- 筆者の実施環境を記載する。
- ハードウェア環境
項目 情報 OS macOS Catalina(10.15.5) ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) プロセッサ 2 GHz クアッドコアIntel Core i5 メモリ 32 GB 3733 MHz LPDDR4 グラフィックス Intel Iris Plus Graphics 1536 MB
- ソフトウェア環境
項目 情報 備考 PHP バージョン 7.4.8 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする Laravel バージョン 8.6.0 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 前提条件
- 下記の記事の作業が完了していること。
前提情報
- 作成するアプリ名は「laravel8_crud」とする。
- 作成するMySQLのデータベース名は「laravel8_crud_DB」とする。
- 下記に今回の作業のあとのソースコードのリモートリポジトリのリンクを記載する。
- 「http」か「https」から始まるURLをリンク化する。URLと通常文字列の区切りは、全半角スペースと改行とする。
概要
- ビューファイルの編集
- 確認
詳細
ビューファイルの編集
laravel8_crudディレクトリで下記コマンドを実行してビューファイルを開く。
$ vi resources/views/contents/output.blade.php下記のように編集する。
laravel8_crud/resources/views/contents/output.blade.php@extends('layouts.app') @section('content') <h1>output</h1> @foreach ($items as $item) <hr> @if (isset($item['file_path'])) <img src="{{asset('storage/' . $item['file_path'])}}" alt="{{asset('storage/' . $item['file_path'])}}"> @endif {{-- 下記を修正する --}} <p>{!! nl2br(preg_replace('/(https?:\/\/[^\s]*)/', '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>', $item['content'])) !!}</p> <a href="{{route('detail', ['content_id' => $item['id']])}}">詳細</a> <a href="{{route('edit', ['content_id' => $item['id']])}}">編集</a> @endforeach @endsectionlaravel8_crudディレクトリで下記コマンドを実行してビューファイルを開く。
$ vi resources/views/contents/detail.blade.php下記のように編集する。
laravel8_crud/resources/views/contents/detail.blade.php@extends('layouts.app') @section('content') <h1>detail</h1> @if (isset($item['file_path'])) <img src="{{asset('storage/' . $item['file_path'])}}" alt="{{asset('storage/' . $item['file_path'])}}"> @endif <p>投稿ID: {{$item['id']}}</p> {{-- 下記を修正する --}} <p>投稿内容: {!! nl2br(preg_replace('/(https?:\/\/[^\s]*)/', '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>', $item['content'])) !!}</p> <p>投稿時間: {{$item['created_at']}}</p> <a href="{{route('edit', ['content_id' => $item['id']])}}">編集</a> <form action="{{route('delete')}}" method="post"> @csrf <input type="hidden" name="id" value="{{$item['id']}}"> <input type="submit" value="削除"> </form> @endsection確認
laravel8_crudディレクトリで下記コマンドを実行してローカルサーバを起動する。
$ php artisan serveブラウザで下記にアクセスする。
下記にアクセスする。
URLがリンク化されており、クリックすると新しいタブで筆者のQiitaの画面が表示されることを確認する。
URLの投稿の「詳細」をクリックする。
URLがリンク化されており、クリックすると新しいタブで筆者のQiitaの画面が表示されることを確認する。
- 投稿日:2020-11-20T10:22:54+09:00
【PHP】セッションとクッキーを初心者向けに説明
超詳しい参考サイト
Web Design Leaves
クッキー
とは?セッション
とは?から始まる話は難しいので上記のサイトを参考にしてください。
最高にわかりやすいです。ここでは
使用例
とセッションとクッキーの関連性
に絞ります。保存先
セッションの保存先は
Webサーバー
です。
クッキーの保存先はクライアントのブラウザ
です。セッションはブラウザとサーバーが接続された時に session_start()によって生成されます。
セッション クッキー 保存先 Webサーバー ブラウザ 変数名 $_SESSION $_COOKIE クッキー(クライアント)のセッションID
ブラウザ側にある
クッキー
にはPHPSESSID
が保存されます。
例えば下のような値です。
セッション名 値 PHPSESSID '682dos0637qu0g1l8clhs9sv7a' WebサーバーのセッションID
Webサーバーは数多く保存しているセッションがどのクライアントに紐付くかをPHPSESSIDで判断しています。
ブラウザ(PHPSESSID) Webサーバー(SESSION) '682dos0637qu0g1l8clhs9sv7a' <-----> '682dos0637qu0g1l8clhs9sv7a' '7qu0g1l8cl682dos063hs9sv7a' 'lhs9sv7a682dos0637qu0g1l8c' セッション変数
セッションは
Webサーバーに保存できる変数
です。
Webサーバーに変数が保存できると何が便利なのでしょうか?
セッション変数
の利点
・ページをまたいで
値のやりとりができる。
・ブラウザを経由しない
ため改ざんされづらい。具体例
send.php
にアクセスすると即時receive.php
に飛んで'51'を画面出力します。send.php<?php session_start(); $_SESSION['id'] = '51'; //リダイレクト header('location: ./receive.php');receive.php<?php session_start(); echo $_SESSION['id']; //string -> 51どうでしょう?うまくいきましたね!
send.phpで$_SESSION['id']
を保存して、receive.phpでアクセスできました!
session_start();
はセッションを使用するときのおまじないです。
各ファイルの先頭
に必ず置いてください。クッキーのセッションIDを確認する
ここで、クッキーに保存されている
PHPSESSID
を確認してみましょう。
Chrome:
デベロッパーツール -> Applicationタブ -> Cookies -> URL -> Value
Safari:
Safariの準備 -> 環境設定 -> 詳細 -> メニューバーに“開発”メニューを表示
開発タブ -> Webインスペクタを表示 -> ストレージタブ -> Cookie -> 値PHPSESSIDが確認できたでしょうか?
PHPSESSIDはそれが破棄されるまで
同じ値が使用されます。セッションの破棄
上で破棄されるまでと言いました。
それでは破棄してみましょう!(公式)delete_session.php<?php session_start(); //セッションの初期化 $_SESSION = []; //セッションクッキーを削除 if (isset($_COOKIE[session_name()])) { setcookie(session_name(), '', time() - 42000, '/'); } //セッションを破壊 session_destroy(); //ここまででPHPSESSIDもセッションも消去されています。 //リダイレクト -> send.php -> 新たなPHPSESSIDが生成される header('location: ./send.php');send.php, receive.php, delete_session.phpは同じフォルダに入れてください。
デベロッパーツールで
PHPSESSID
を観察しながら、
send.php
動作 ->delete_session.php
動作で。
PHPSESSIDが生成
->変更
されているのが見えます!ぜひデベロッパーツールで確認してみてください。
どうでしたでしょうか?
セッション変数の利用の一助になれば幸いです。LGTMお願いします!
ストックのついでにお願いします!
モチベーションがあがります!
- 投稿日:2020-11-20T10:11:14+09:00
RubyエンジニアがPHPを勉強し始めるときに見る記事
この記事 is 何
RubyエンジニアがPHPを勉強し始めるときに見る記事です。
動機
今までRubyをやってきていて、PHPを使うことになったというケースは少なくないと思っています。
特に実務未経験の方々では、このケースが多いのではないでしょうか?
というのは、実務未経験が学習している言語は、Rubyがファーストチョイスである一方で、PHPを使う企業は少なくないためです。
ちなみに、僕もそのケースでした。
そういう方々が過度に不安を持ったりせず、スムーズに転向できるようにしたいと思い、この記事を書きました。この記事の主なターゲット
- 今までRubyを勉強してたが、PHPを使うことになった人
- というか半年前の自分
この記事で書くつもりのないこと
- 技術選定時・初学者が学ぶ言語としてRuby or PHPはどっちが良いのかということ
- 網羅的・辞書的にRubyとPHPを比較した結果
- RubyとPHPの文法の正確な対応関係
学習のし始め
RubyからPHPへの転向コスト
Rubyをちゃんと習得できた方であれば、転向・学習コストにおいて問題はほぼ起きないと思います。
文法を調べながらとりあえず書き始められる、というレベルに達するには半日〜3日程度の勉強で済むと思います。文法を調べるときに何を使うか
php.net
PHPは公式ドキュメントが神なので、基本的にこのサイトを見ればPHPの文法的な解決してくれるはずです。ググラビリティも良好で、「array_merge php」などと検索すれば公式ドキュメントが先頭に出てくれます。
本題
動作確認バージョン$ php -v PHP 7.3.11 ... $ ruby -v ruby 2.6.3p62 ...基本的なオブジェクトの概念
出力
Ruby PHP 改行なし出力 echo 型情報付き出力 p var_dump() 配列に対し改行付き出力 puts echo, PHP_EOL Rubyの
echo
に近いです。
Rubyのp
は、PHPでいうとvar_dump
に近いです。Rubyの
puts
は?と言われると、対応したものはありません。
echo
とPHP_EOL
を組み合わせる必要があります。objects/print.rbprint 'sample!' # sample! sample_array = [1, 'sample'] print sample_array # [1, "sample"] p sample_array # [1, "sample"] puts sample_array # 1 # sampleobjects/class.php<?php echo 'sample!'; // sample! $sample_array = [1, 'sample']; echo $sample_array; // Array var_dump($sample_array); // array(2) { // [0]=> // int(1) // [1]=> // string(6) "sample" // } foreach ($sample_array as $value) { echo $value . PHP_EOL; } // 1 // sampleプリミティブ型のクラス
Ruby PHP プリミティブ型は クラス ただの型 文字列への変換 to_s "{$変数}" 数値への変換 to_i intval() Rubyでは
String
,Integer
,Array
といったプリミティブ型も全てがオブジェクトです。
一方、PHPにはプリミティブ型においてはクラスの概念はありません。PHPでは
string
への変換は、ダブルクウォートで囲った上で変数展開することによって実現します。
また、int
に変換するにはintval()
を使います。objects/class.rbint3 = 3 string3 = int3.to_s p string3 # "3" p string3.class # String re_int3 = string3.to_i p re_int3 # 3 p re_int3.class # Integerobjects/method.php<?php $int3 = 3; $string3 = "{$int3}"; var_dump($string3); // string(1) "3" get_class($string3); // Warning: get_class() expects parameter 1 to be object, string given in ... $re_int3 = intval($string3); var_dump($re_int3); // int(3) get_class($re_int3); // Warning: get_class() expects parameter 1 to be object, int given in ...値・オブジェクトに対する基本的な操作・変換
Ruby PHP 基本的な操作・変換は オブジェクトメソッド 標準関数の引数に渡す 文字数を調べる length / size mb_strlen() 配列を合計する sum array_sum() Rubyでは値・オブジェクトに対する基本的な操作・変換はオブジェクトメソッドで実現します。
参考: class Object(Ruby 2.7.0 リファレンスマニュアル)一方、PHPは標準関数が充実しており、その標準関数の引数として対象を渡すのが一般的です。
objects/method.rbaddress = '千代田区千代田1-1' puts address.length # 10 fibonacci_numbers = [1, 1, 2, 3, 5, 8, 13] puts fibonacci_numbers.sum # 33objects/method.php<?php $address = '千代田区千代田1-1'; echo mb_strlen($address); // 10 $fibonacci_numbers = [1, 1, 2, 3, 5, 8, 13]; echo array_sum($fibonacci_numbers); // 33配列・ハッシュと、連想配列
Ruby PHP 配列の概念 配列 連想配列 連想配列の概念 ハッシュ 連想配列 配列の要素の取得 配列[インデックス] 連想配列[インデックス] 連想配列の要素の取得 配列[シンボル] 連想配列[キー] Rubyでは配列と連想配列(ハッシュ)を使い分けます。
一方で、PHPはちょっと特殊で、連想配列しかありません。PHPにおける(連想配列でない)配列は、キーが数値である連想配列です。
また、Rubyでは連想配列のキーにはシンボルを使うことが多いと思いますが、PHPでは文字列をキーとすることが多いです。objects/array.rbdays_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] p days_of_week # ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] puts days_of_week[0] # Monday fruits = {red: 'apple', purple: 'grape', yellow: 'lemon'} p fruits # {:red=>"apple", :purple=>"grape", :yellow=>"lemon"} puts fruits[:red] # appleobjects/array.php<?php $days_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; var_dump($days_of_week); // array(7) { // [0]=> // string(6) "Monday" // [1]=> // string(7) "Tuesday" // [2]=> // string(9) "Wednesday" // [3]=> // string(8) "Thursday" // [4]=> // string(6) "Friday" // [5]=> // string(8) "Saturday" // [6]=> // string(6) "Sunday" // } echo $days_of_week[0]; // Monday $fruits = ['red' => 'apple', 'purple' => 'grape', 'yellow' => 'lemon']; var_dump($fruits); // array(3) { // ["red"]=> // string(5) "apple" // ["purple"]=> // string(5) "grape" // ["yellow"]=> // string(5) "lemon" //} echo $fruits['red']; // apple配列への操作
Ruby PHP 配列への追加 配列 << 新要素 配列[] = 新要素 連想配列への追加 配列[シンボル] = 新要素 配列[キー] = 新要素 繰り返し処理 each foreach 繰り返し処理(返り値使用) map array_map() 繰り返し処理内での行いたい処理 ブロック コールバック関数 配列への追加は、Rubyは
<<
によってできる一方、PHPでは配列[] = 新要素
という書き方を使います。
連想配列への追加は、書き方的にほぼ違いは無いかと思います。手続き的な繰り返し処理は、Rubyなら
each
, PHPならforeach
です。
返り値を使用したいときはRubyならmap
, PHPならarray_map()
を使います。繰り返し処理中に行いたい処理を表現するのは、Rubyならブロック、PHPならコールバック関数を使います。
array_map()
はよく使う割にはちょっと複雑な見た目をしていますね。objects/array_function.rbsequence_numbers = [1, 2, 3, 4, 5] sequence_numbers << 6 p sequence_numbers # [1, 2, 3, 4, 5, 6] fruits = {red: 'apple', purple: 'grape', yellow: 'lemon'} fruits[:orange] = 'pumpkin' p fruits # {:red=>"apple", :purple=>"grape", :yellow=>"lemon", :orange=>"pumpkin"} sequence_numbers.each do |number| multiple_of_3 = number * 3 puts multiple_of_3 end # 3 # 6 # 9 # 12 # 15 # 18 multiples = sequence_numbers.map do |number| number * 3 end p multiples # [3, 6, 9, 12, 15, 18]objects/array_function.php<?php $sequence_numbers = [1, 2, 3, 4, 5]; $sequence_numbers[] = 6; var_dump($sequence_numbers); // array(6) { // [0]=> // int(1) // [1]=> // int(2) // [2]=> // int(3) // [3]=> // int(4) // [4]=> // int(5) // [5]=> // int(6) // } $fruits = ['red' => 'apple', 'purple' => 'grape', 'yellow' => 'lemon']; $fruits['orange'] = 'pumpkin'; var_dump($fruits); // array(4) { // ["red"]=> // string(5) "apple" // ["purple"]=> // string(5) "grape" // ["yellow"]=> // string(5) "lemon" // ["orange"]=> // string(7) "pumpkin" // } foreach ($sequence_numbers as $number) { $multiple_of_3 = $number * 3; echo $multiple_of_3 . PHP_EOL; } // 3 // 6 // 9 // 12 // 15 // 18 $multiples = array_map( function ($number) { return $number * 3; }, $sequence_numbers ); var_dump($multiples); // array(6) { // [0]=> // int(3) // [1]=> // int(6) // [2]=> // int(9) // [3]=> // int(12) // [4]=> // int(15) // [5]=> // int(18) // }クラス関連
クラスは重要なので、重点的に解説します。
インスタンス変数=プロパティ
Ruby PHP メンバ変数 インスタンス変数 プロパティ privateなメンバ変数の定義 不要 private $変数; publicなメンバ変数の定義 @変数に代入し、attr_accessor public $変数; コンストラクタ def initialize function __construct() メンバ変数への代入 @変数に代入 $this->変数
に代入メンバ変数の呼び出し . -> Rubyのインスタンス変数は、PHPのプロパティに該当します。
Rubyはインスタンス変数の宣言は特に必要なく、コンストラクタで@変数
に代入してしまえば完了です。
一方、PHPだと宣言が必要で、private $変数;
のように定義します。また、メンバ変数を公開可能にしたいのであれば、Rubyでは
attr_accessor
を使う一方、PHPではpublic $変数
によって定義します。classes/Person.rbclass Person attr_accessor :name def initialize name, age @name = name @age = age end end person = Person.new '一郎', 10 p person # #<Person:0x00007ff39f158750 @name="一郎", @age=10> puts person.name # 一郎 puts person.age # Traceback (most recent call last): # classes/Person.rb:16:in `<main>': undefined method `age' for #<Person:0x00007ff39f158750 @name="一郎", @age=10> (NoMethodError)classes/Person.php<?PHP class Person { public $name; private $age; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } } $person = new Person('一郎', 10); var_dump($person); // object(Person)#1 (2) { // ["name"]=> // string(6) "一郎" // ["age":"Person":private]=> // int(10) // } echo $person->name; // 一郎 echo $person->age; // Fatal error: Uncaught Error: Cannot access private property Person::$age in ...クラスの定数
Ruby PHP 定数の定義 大文字 const 大文字 クラス外からの定数の呼び出し クラス::定数 クラス::定数 クラス内からの定数の呼び出し 定数 self::定数 PHPだと定数は
const
を付けて宣言します。
クラス外からの呼び出しは、RubyでもPHPでも同じ書き方です。
PHPだとクラス外からの呼び出しではself::
をつけます。classes/Sample.rbclass Sample TEST_CODE = 'test_code' def print_code puts "コードは#{TEST_CODE}です。"; end end puts Sample::TEST_CODE # test_code sample = Sample.new sample.print_code # コードはtest_codeです。classes/Sample.php<?PHP class Sample { const TEST_CODE = 'test_code'; public function printCode() { $code = self::TEST_CODE; echo "コードは「{$code}」です。"; } } echo Sample::TEST_CODE; // test_code $sample = new Sample(); $sample->printCode(); // コードは「test_code」です。インスタンスメソッド
Ruby PHP publicメソッドの定義方法 ただのdef public function() privateメソッドの定義方法 privateの下でdef private function() Rubyではクラス内で何も行わずに
def
をするとpublicメソッドとなり、private
の下で定義されるとprivateメソッドになります。
一方、PHPではメソッドの定義時に必ずpublic
/private
を定義します。
(本当はもっと色々種類がありますが割愛)classes/Product.rbclass Product def initialize price, cost @price = price @cost = cost end def print_judgment if calc_profit > 0 puts 'この商品は利益が出ます!どんどん売りましょう!'; else puts 'この商品は利益が出ません...売るべきではないかもしれません...' end end private def calc_profit @price - @cost end end product = Product.new 120, 100 product.print_judgment # この商品は利益が出ます!どんどん売りましょう! product = Product.new 90, 100 product.print_judgment # この商品は利益が出ません...売るべきではないかもしれません... product.calc_profit # Traceback (most recent call last): # classes/Product.rb:30:in `<main>': private method `calc_profit' called for #<Product:0x00007fc9f19dc408 @price=120, @cost=100> (NoMethodError)classes/Product.php<?php class Product { private $price; private $cost; public function __construct($price, $cost) { $this->price = $price; $this->cost = $cost; } public function printJudgment() { if ($this->calcProfit() > 0) { echo 'この商品は利益が出ます!どんどん売りましょう!'; } else { echo 'この商品は利益が出ません...売るべきではないかもしれません...'; } } private function calcProfit() { return $this->price - $this->cost; } } $product = new Product(120, 100); $product->printJudgment(); // この商品は利益が出ます!どんどん売りましょう! $product = new Product(90, 100); $product->printJudgment(); // この商品は利益が出ません...売るべきではないかもしれません... $product->calcProfit(); // Fatal error: Uncaught Error: Call to private method Product::calcProfit() from context '' in ...クラスメソッドとstaticメソッド
Ruby PHP 静的メソッド クラスメソッド staticメソッド インスタンスメソッド インスタンスメソッド staticでないメソッド 静的メソッドの定義方法 self static function() 静的メソッドの呼び出し クラス::メソッド クラス::メソッド Rubyにおけるクラスメソッドは、PHPではstaticメソッドに該当します。
逆に、インスタンスメソッドはstaicでないメソッドということになります。Rubyでクラスメソッドを定義するときは、
class << self
の中で定義することが多いと思います。
一方で、PHPではメソッドの定義ごとにstatic
を付与することで定義します。また、
public
/private
はどんなメソッドでも付けるので、staticメソッドにもpublic
/private
を付けて定義します。
静的メソッドの呼び出しの書き方は、RubyとPHPとでほぼ差は無いかと思います。classes/VertebrateAnimal.rbclass VertebrateAnimal class << self def is_vertebrate_animal group get_vertebrate_animals.include? group end private def get_vertebrate_animals %w[fishes amphibians reptiles birds mammals] end end end is_vertebrate_animal1 = VertebrateAnimal::is_vertebrate_animal 'fishes' puts is_vertebrate_animal1 # true is_vertebrate_animal2 = VertebrateAnimal::is_vertebrate_animal 'insects' puts is_vertebrate_animal2 # falseclasses/VertebrateAnimal.php<?PHP class VertebrateAnimal { public static function isVertebrateAnimal($group) { $vertebrate_animals = self::getVertebrateAnimals(); return in_array($group, $vertebrate_animals, true); } private static function getVertebrateAnimals() { return ['fishes', 'amphibians', 'reptiles', 'birds', 'mammals']; } } $is_vertebrate_animal1 = VertebrateAnimal::isVertebrateAnimal('fishes'); var_dump($is_vertebrate_animal1); // bool(true) $is_vertebrate_animal2 = VertebrateAnimal::isVertebrateAnimal('insects'); var_dump($is_vertebrate_animal2); // bool(false)ゲッターとセッター
Ruby PHP ゲッター attr_reader getXX() セッター attr_writer setXX() Rubyにおける
attr_reader
およびattr_writer
に該当するような文法は、PHPにはありません。
よってgetXX
,setXX
という命名で自作することになります。classes/Capsule.rbclass Capsule attr_reader :element attr_writer :element def initialize element @element = element end end capsule = Capsule.new '有効成分' puts capsule.element # 有効成分 p capsule # #<Capsule:0x00007f8d909ac660 @element="有効成分"> capsule.element = '毒' p capsule # #<Capsule:0x00007f8d909ac660 @element="毒">classes/Capsule.php<?PHP class Capsule { private $element; public function __construct($element) { $this->element = $element; } public function getElement() { return $this->element; } public function setElement($element) { $this->element = $element; } } $capsule = new Capsule('有効成分'); echo $capsule->getElement(); // 有効成分 var_dump($capsule); // object(Capsule)#1 (1) { // ["element":"Capsule":private]=> // string(12) "有効成分" // } $capsule->setElement('毒'); var_dump($capsule); // object(Capsule)#1 (1) { // ["element":"Capsule":private]=> // string(3) "毒" // }その他ハマりポイント
ライブラリの対応関係
Ruby PHP ライブラリ管理 Gem Composer テスト Rspec PHPUnit Linter Rubocop PHP-CS-Fixerなど コメント RDoc PHPDoc フレームワーク Ruby on Rails Laravel, CakePHPなど 有名どころのライブラリなどの対応関係のみを記載しました。
Rubyと言ったらRails、Railsと言ったらRubyという印象ですが、PHPではフレームワークは複数の選択肢があります。
シェアが高いという意味であればLaravelが近く、MVCの思想に忠実という意味ではCakePHPに近いかなという印象を持っています。真偽判定・nil/null判定
Ruby PHP == そこそこ使う 絶対に使わない Null nil null オブジェクトのNull確認 ! empty() PHPの==はあまりにもヤバいことで有名だと思いますので、比較のときには必ず
===
を使うようにします。
Rubyでのnil
は、PHPだとnull
に該当します。Rubyでは全てがオブジェクトであり、真偽値判定・
nil
判定がうまく設計されていて、オブジェクトのみで直感的に真偽値判定・nil
判定をできることも多いです。
一方、PHPの場合は直感的に真偽値判定・null
判定を行うのは危険なので、型を意識して判定した方が安全です。
オブジェクトがnullや空かどうかを確認するなら、empty()
を使うのが有効です。others/User.rbclass User class << self def find_by_id id # IDが1のときはユーザオブジェクトを返し、それ以外のときはユーザオブジェクトを返さないとします if id == 1 User.new '最初のユーザ' else nil end end end def initialize name @name = name end end def print_user user # ユーザオブジェクトが存在するかを確認する if !user puts 'ユーザはいません' else p user end end user2 = User::find_by_id 2 print_user user2 # ユーザはいません p user2 # nil user1 = User::find_by_id 1 print_user user1 # #<User:0x00007fe70f173f88 @name="最初のユーザ">others/User.php<?php class User { private $name; public function __construct($name) { $this->name = $name; } static function findById($id) { /** IDが1のときはユーザオブジェクトを返し、それ以外のときはユーザオブジェクトを返さないとします */ if ($id === 1) { return new static('最初のユーザ'); } else { return null; } } } function printUser($user) { // ユーザオブジェクトが存在するかを確認する if (empty($user)) { echo 'ユーザはいません'; } else { var_dump($user); } } $user2 = User::findById(2); printUser($user2); // ユーザはいません var_dump($user2); // NULL $user1 = User::findById(1); printUser($user1); // object(User)#1 (1) { // ["name":"User":private]=> // string(18) "最初のユーザ" // }if文の返り値
Ruby PHP if文の返り値 最後の値 なし 分岐によって値を生成する場合 ifの返り値に入れる 一度値を初期化し、再代入する PHPは
if
文の返り値が返ってきません。
そのため、分岐によって値を生成させるケースでは一度値を初期化するなどしてから再代入する、みたいな方法を取る必要があります。どうしても再代入がいやだ、イミュータブルにしたい、という場合は三項演算子という方法もあります。
ただし、三項演算子は多くの場合は処理が分かりにくくなるだけなので、非推奨です。others/day.rbdef print_ymd is_beginning_of_month today = Time.now datetime = if is_beginning_of_month Time.new today.year, today.month, 1 # is_beginning_of_month = falseでは現在日を返す else today # 月初を返す end puts datetime.strftime "%Y年%m月%d日です" end print_ymd false # 2020年12月07日です print_ymd true # 2020年12月01日ですothers/day.php<?php function printYmd($is_beginning_of_month) { $today = new DateTimeImmutable(); $datetime = null; if ($is_beginning_of_month) { // 月初を返す $datetime = new DateTimeImmutable($today->format('Y-m-01')); } else { // $is_beginning_of_month = falseでは現在日を返す $datetime = $today; } echo $datetime->format('Y年m月d日です'); } printYmd(false); // 2020年12月07日です printYmd(true); // 2020年12月01日です /** * 別の書き方。コード量は少ないが分かりにくい */ function printYmd2($is_beginning_of_month) { $today = new DateTimeImmutable(); $datetime = $is_beginning_of_month ? new DateTimeImmutable($today->format('Y-m-01')) : $today; echo $datetime->format('Y年m月d日です'); }名前付き引数がない(PHP7以前)
Ruby PHP7以前 PHP8以後 名前付き引数 引数名: なし 引数名: PHP7以前では名前付き引数がありません。
よって、オプション引数と言いながらも順番を意識して代入する必要があります(辛い)。
このため、依存性注入が凄まじくやりづらいです。PHP8には名前付き引数が導入されています。
【PHP8.0】PHPに名前付き引数が実装されるothers/argument.rbdef calc_goku_scouter original_power, kaio_ken: 1, is_suppressed: false, is_super_saiyan: false power = original_power * kaio_ken if power > 5000 && is_suppressed power = 5000 end if is_super_saiyan power += 100000000 end power end puts calc_goku_scouter 85000 # 85000 puts calc_goku_scouter 85000, kaio_ken: 2 # 170000 puts calc_goku_scouter 85000, is_suppressed: true # 5000 puts calc_goku_scouter 85000, kaio_ken: 20, is_super_saiyan: true # 101700000others/argument.php<?php function calcGokuScouter($original_power, $kaio_ken = 1, $is_suppressed = false, $is_super_saiyan = false) { $power = $original_power * $kaio_ken; if ($power > 5000 && $is_suppressed) { $power = 5000; } if ($is_super_saiyan) { $power += 100000000; } return $power; } echo calcGokuScouter(85000); // 85000 echo calcGokuScouter(85000, 2); // 170000 echo calcGokuScouter(85000, 1, true); // 5000 echo calcGokuScouter(85000, 20, false, true); // 101700000interfaceとabstract
Ruby PHP インターフェース なし interface 抽象クラス なし abstract Rubyには無い概念として、PHPには
interface
,abstract
というものがあります。特に
interface
は重要なのですが、中々概念の理解が難しいかもしれません。
とても勉強になった記事があるので、貼っておきます。
脱PHP初心者!インターフェイスを理解しよう
abstract
はGoFのデザインパターンでいうTemplate Methodパターンを実装するのに必要です。
参考になった記事を貼っておきます。
PHPによるデザインパターン入門 - TemplateMethod〜処理を穴埋めする - Do You PHP はてブロ結び
いかがでしたか?
もし誤記・間違い・より良い書き方などあれば、ご指摘いただけると嬉しいです。一応GitHubにもコードをまとめておきました。
https://github.com/kumackey/php-ruby他参考になりそうなもの
PHPer向けのRuby入門
この記事の逆パターンです。演習問題が付いてる優しさ。PHPerがRubyを勉強するのに役に立つTips
同じくこの記事の逆パターン。元PHPエンジニアがPHPとRubyを比較してみた
PHPとRubyの文法の違いなど。PHPからRubyへ
Rubyの公式が出している、PHPとの違いというドキュメント
- 投稿日:2020-11-20T10:11:14+09:00
【PHP入門】RubyエンジニアがPHPを勉強し始めるときに見る記事
この記事 is 何
RubyエンジニアがPHPを勉強し始めるときに見る、PHPの入門記事です。
動機
今までRubyをやってきていて、PHPを使うことになったというケースは少なくないと思っています。
特に実務未経験の方々では、このケースが多いのではないでしょうか?
というのは、実務未経験が学習している言語は、Rubyがファーストチョイスである一方で、PHPを使う企業は少なくないためです。
ちなみに、僕もそのケースでした。
そういう方々が過度に不安を持ったりせず、スムーズに転向できるようにしたいと思い、この記事を書きました。この記事の主なターゲット
- 今までRubyを勉強してたが、PHPを使うことになった人
- というか半年前の自分
この記事で書くつもりのないこと
- 技術選定時・初学者が学ぶ言語としてRuby or PHPはどっちが良いのかということ
- 網羅的・辞書的にRubyとPHPを比較した結果
- RubyとPHPの文法の正確な対応関係
学習のし始め
RubyからPHPへの転向コスト
Rubyをちゃんと習得できた方であれば、転向・学習コストにおいて問題はほぼ起きないと思います。
文法を調べながらとりあえず書き始められる、というレベルに達するには半日〜3日程度の勉強で済むと思います。文法を調べるときに何を使うか
php.net
PHPは公式ドキュメントが神なので、基本的にこのサイトを見ればPHPの文法的な解決してくれるはずです。ググラビリティも良好で、「array_merge php」などと検索すれば公式ドキュメントが先頭に出てくれます。
本題
動作確認バージョン$ php -v PHP 7.3.11 ... $ ruby -v ruby 2.6.3p62 ...基本的なオブジェクトの概念
出力
Ruby PHP 改行なし出力 echo 型情報付き出力 p var_dump() 配列に対し改行付き出力 puts echo, PHP_EOL Rubyの
echo
に近いです。
Rubyのp
は、PHPでいうとvar_dump
に近いです。Rubyの
puts
は?と言われると、対応したものはありません。
echo
とPHP_EOL
を組み合わせる必要があります。objects/print.rbprint 'sample!' # sample! sample_array = [1, 'sample'] print sample_array # [1, "sample"] p sample_array # [1, "sample"] puts sample_array # 1 # sampleobjects/class.php<?php echo 'sample!'; // sample! $sample_array = [1, 'sample']; echo $sample_array; // Array var_dump($sample_array); // array(2) { // [0]=> // int(1) // [1]=> // string(6) "sample" // } foreach ($sample_array as $value) { echo $value . PHP_EOL; } // 1 // sampleプリミティブ型のクラス
Ruby PHP プリミティブ型は クラス ただの型 文字列への変換 to_s "{$変数}" 数値への変換 to_i intval() Rubyでは
String
,Integer
,Array
といったプリミティブ型も全てがオブジェクトです。
一方、PHPにはプリミティブ型においてはクラスの概念はありません。PHPでは
string
への変換は、ダブルクウォートで囲った上で変数展開することによって実現します。
また、int
に変換するにはintval()
を使います。objects/class.rbint3 = 3 string3 = int3.to_s p string3 # "3" p string3.class # String re_int3 = string3.to_i p re_int3 # 3 p re_int3.class # Integerobjects/method.php<?php $int3 = 3; $string3 = "{$int3}"; var_dump($string3); // string(1) "3" get_class($string3); // Warning: get_class() expects parameter 1 to be object, string given in ... $re_int3 = intval($string3); var_dump($re_int3); // int(3) get_class($re_int3); // Warning: get_class() expects parameter 1 to be object, int given in ...値・オブジェクトに対する基本的な操作・変換
Ruby PHP 基本的な操作・変換は オブジェクトメソッド 標準関数の引数に渡す 文字数を調べる length / size mb_strlen() 配列を合計する sum array_sum() Rubyでは値・オブジェクトに対する基本的な操作・変換はオブジェクトメソッドで実現します。
参考: class Object(Ruby 2.7.0 リファレンスマニュアル)一方、PHPは標準関数が充実しており、その標準関数の引数として対象を渡すのが一般的です。
objects/method.rbaddress = '千代田区千代田1-1' puts address.length # 10 fibonacci_numbers = [1, 1, 2, 3, 5, 8, 13] puts fibonacci_numbers.sum # 33objects/method.php<?php $address = '千代田区千代田1-1'; echo mb_strlen($address); // 10 $fibonacci_numbers = [1, 1, 2, 3, 5, 8, 13]; echo array_sum($fibonacci_numbers); // 33配列・ハッシュと、連想配列
Ruby PHP 配列の概念 配列 連想配列 連想配列の概念 ハッシュ 連想配列 配列の要素の取得 配列[インデックス] 連想配列[インデックス] 連想配列の要素の取得 配列[シンボル] 連想配列[キー] Rubyでは配列と連想配列(ハッシュ)を使い分けます。
一方で、PHPはちょっと特殊で、連想配列しかありません。PHPにおける(連想配列でない)配列は、キーが数値である連想配列です。
また、Rubyでは連想配列のキーにはシンボルを使うことが多いと思いますが、PHPでは文字列をキーとすることが多いです。objects/array.rbdays_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] p days_of_week # ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] puts days_of_week[0] # Monday fruits = {red: 'apple', purple: 'grape', yellow: 'lemon'} p fruits # {:red=>"apple", :purple=>"grape", :yellow=>"lemon"} puts fruits[:red] # appleobjects/array.php<?php $days_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; var_dump($days_of_week); // array(7) { // [0]=> // string(6) "Monday" // [1]=> // string(7) "Tuesday" // [2]=> // string(9) "Wednesday" // [3]=> // string(8) "Thursday" // [4]=> // string(6) "Friday" // [5]=> // string(8) "Saturday" // [6]=> // string(6) "Sunday" // } echo $days_of_week[0]; // Monday $fruits = ['red' => 'apple', 'purple' => 'grape', 'yellow' => 'lemon']; var_dump($fruits); // array(3) { // ["red"]=> // string(5) "apple" // ["purple"]=> // string(5) "grape" // ["yellow"]=> // string(5) "lemon" //} echo $fruits['red']; // apple配列への操作
Ruby PHP 配列への追加 配列 << 新要素 配列[] = 新要素 連想配列への追加 配列[シンボル] = 新要素 配列[キー] = 新要素 繰り返し処理 each foreach 繰り返し処理(返り値使用) map array_map() 繰り返し処理内での行いたい処理 ブロック コールバック関数 配列への追加は、Rubyは
<<
によってできる一方、PHPでは配列[] = 新要素
という書き方を使います。
連想配列への追加は、書き方的にほぼ違いは無いかと思います。手続き的な繰り返し処理は、Rubyなら
each
, PHPならforeach
です。
返り値を使用したいときはRubyならmap
, PHPならarray_map()
を使います。繰り返し処理中に行いたい処理を表現するのは、Rubyならブロック、PHPならコールバック関数を使います。
array_map()
はよく使う割にはちょっと複雑な見た目をしていますね。objects/array_function.rbsequence_numbers = [1, 2, 3, 4, 5] sequence_numbers << 6 p sequence_numbers # [1, 2, 3, 4, 5, 6] fruits = {red: 'apple', purple: 'grape', yellow: 'lemon'} fruits[:orange] = 'pumpkin' p fruits # {:red=>"apple", :purple=>"grape", :yellow=>"lemon", :orange=>"pumpkin"} sequence_numbers.each do |number| multiple_of_3 = number * 3 puts multiple_of_3 end # 3 # 6 # 9 # 12 # 15 # 18 multiples = sequence_numbers.map do |number| number * 3 end p multiples # [3, 6, 9, 12, 15, 18]objects/array_function.php<?php $sequence_numbers = [1, 2, 3, 4, 5]; $sequence_numbers[] = 6; var_dump($sequence_numbers); // array(6) { // [0]=> // int(1) // [1]=> // int(2) // [2]=> // int(3) // [3]=> // int(4) // [4]=> // int(5) // [5]=> // int(6) // } $fruits = ['red' => 'apple', 'purple' => 'grape', 'yellow' => 'lemon']; $fruits['orange'] = 'pumpkin'; var_dump($fruits); // array(4) { // ["red"]=> // string(5) "apple" // ["purple"]=> // string(5) "grape" // ["yellow"]=> // string(5) "lemon" // ["orange"]=> // string(7) "pumpkin" // } foreach ($sequence_numbers as $number) { $multiple_of_3 = $number * 3; echo $multiple_of_3 . PHP_EOL; } // 3 // 6 // 9 // 12 // 15 // 18 $multiples = array_map( function ($number) { return $number * 3; }, $sequence_numbers ); var_dump($multiples); // array(6) { // [0]=> // int(3) // [1]=> // int(6) // [2]=> // int(9) // [3]=> // int(12) // [4]=> // int(15) // [5]=> // int(18) // }クラス関連
クラスは重要なので、重点的に解説します。
インスタンス変数=プロパティ
Ruby PHP メンバ変数 インスタンス変数 プロパティ privateなメンバ変数の定義 不要 private $変数; publicなメンバ変数の定義 @変数に代入し、attr_accessor public $変数; コンストラクタ def initialize function __construct() メンバ変数への代入 @変数に代入 $this->変数
に代入メンバ変数の呼び出し . -> Rubyのインスタンス変数は、PHPのプロパティに該当します。
Rubyはインスタンス変数の宣言は特に必要なく、コンストラクタで@変数
に代入してしまえば完了です。
一方、PHPだと宣言が必要で、private $変数;
のように定義します。また、メンバ変数を公開可能にしたいのであれば、Rubyでは
attr_accessor
を使う一方、PHPではpublic $変数
によって定義します。classes/Person.rbclass Person attr_accessor :name def initialize name, age @name = name @age = age end end person = Person.new '一郎', 10 p person # #<Person:0x00007ff39f158750 @name="一郎", @age=10> puts person.name # 一郎 puts person.age # Traceback (most recent call last): # classes/Person.rb:16:in `<main>': undefined method `age' for #<Person:0x00007ff39f158750 @name="一郎", @age=10> (NoMethodError)classes/Person.php<?PHP class Person { public $name; private $age; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } } $person = new Person('一郎', 10); var_dump($person); // object(Person)#1 (2) { // ["name"]=> // string(6) "一郎" // ["age":"Person":private]=> // int(10) // } echo $person->name; // 一郎 echo $person->age; // Fatal error: Uncaught Error: Cannot access private property Person::$age in ...クラスの定数
Ruby PHP 定数の定義 大文字 const 大文字 クラス外からの定数の呼び出し クラス::定数 クラス::定数 クラス内からの定数の呼び出し 定数 self::定数 PHPだと定数は
const
を付けて宣言します。
クラス外からの呼び出しは、RubyでもPHPでも同じ書き方です。
PHPだとクラス外からの呼び出しではself::
をつけます。classes/Sample.rbclass Sample TEST_CODE = 'test_code' def print_code puts "コードは#{TEST_CODE}です。"; end end puts Sample::TEST_CODE # test_code sample = Sample.new sample.print_code # コードはtest_codeです。classes/Sample.php<?PHP class Sample { const TEST_CODE = 'test_code'; public function printCode() { $code = self::TEST_CODE; echo "コードは「{$code}」です。"; } } echo Sample::TEST_CODE; // test_code $sample = new Sample(); $sample->printCode(); // コードは「test_code」です。インスタンスメソッド
Ruby PHP publicメソッドの定義方法 ただのdef public function() privateメソッドの定義方法 privateの下でdef private function() Rubyではクラス内で何も行わずに
def
をするとpublicメソッドとなり、private
の下で定義されるとprivateメソッドになります。
一方、PHPではメソッドの定義時に必ずpublic
/private
を定義します。
(本当はもっと色々種類がありますが割愛)classes/Product.rbclass Product def initialize price, cost @price = price @cost = cost end def print_judgment if calc_profit > 0 puts 'この商品は利益が出ます!どんどん売りましょう!'; else puts 'この商品は利益が出ません...売るべきではないかもしれません...' end end private def calc_profit @price - @cost end end product = Product.new 120, 100 product.print_judgment # この商品は利益が出ます!どんどん売りましょう! product = Product.new 90, 100 product.print_judgment # この商品は利益が出ません...売るべきではないかもしれません... product.calc_profit # Traceback (most recent call last): # classes/Product.rb:30:in `<main>': private method `calc_profit' called for #<Product:0x00007fc9f19dc408 @price=120, @cost=100> (NoMethodError)classes/Product.php<?php class Product { private $price; private $cost; public function __construct($price, $cost) { $this->price = $price; $this->cost = $cost; } public function printJudgment() { if ($this->calcProfit() > 0) { echo 'この商品は利益が出ます!どんどん売りましょう!'; } else { echo 'この商品は利益が出ません...売るべきではないかもしれません...'; } } private function calcProfit() { return $this->price - $this->cost; } } $product = new Product(120, 100); $product->printJudgment(); // この商品は利益が出ます!どんどん売りましょう! $product = new Product(90, 100); $product->printJudgment(); // この商品は利益が出ません...売るべきではないかもしれません... $product->calcProfit(); // Fatal error: Uncaught Error: Call to private method Product::calcProfit() from context '' in ...クラスメソッドとstaticメソッド
Ruby PHP 静的メソッド クラスメソッド staticメソッド インスタンスメソッド インスタンスメソッド staticでないメソッド 静的メソッドの定義方法 self static function() 静的メソッドの呼び出し クラス::メソッド クラス::メソッド Rubyにおけるクラスメソッドは、PHPではstaticメソッドに該当します。
逆に、インスタンスメソッドはstaicでないメソッドということになります。Rubyでクラスメソッドを定義するときは、
class << self
の中で定義することが多いと思います。
一方で、PHPではメソッドの定義ごとにstatic
を付与することで定義します。また、
public
/private
はどんなメソッドでも付けるので、staticメソッドにもpublic
/private
を付けて定義します。
静的メソッドの呼び出しの書き方は、RubyとPHPとでほぼ差は無いかと思います。classes/VertebrateAnimal.rbclass VertebrateAnimal class << self def is_vertebrate_animal group get_vertebrate_animals.include? group end private def get_vertebrate_animals %w[fishes amphibians reptiles birds mammals] end end end is_vertebrate_animal1 = VertebrateAnimal::is_vertebrate_animal 'fishes' puts is_vertebrate_animal1 # true is_vertebrate_animal2 = VertebrateAnimal::is_vertebrate_animal 'insects' puts is_vertebrate_animal2 # falseclasses/VertebrateAnimal.php<?PHP class VertebrateAnimal { public static function isVertebrateAnimal($group) { $vertebrate_animals = self::getVertebrateAnimals(); return in_array($group, $vertebrate_animals, true); } private static function getVertebrateAnimals() { return ['fishes', 'amphibians', 'reptiles', 'birds', 'mammals']; } } $is_vertebrate_animal1 = VertebrateAnimal::isVertebrateAnimal('fishes'); var_dump($is_vertebrate_animal1); // bool(true) $is_vertebrate_animal2 = VertebrateAnimal::isVertebrateAnimal('insects'); var_dump($is_vertebrate_animal2); // bool(false)ゲッターとセッター
Ruby PHP ゲッター attr_reader getXX() セッター attr_writer setXX() Rubyにおける
attr_reader
およびattr_writer
に該当するような文法は、PHPにはありません。
よってgetXX
,setXX
という命名で自作することになります。classes/Capsule.rbclass Capsule attr_reader :element attr_writer :element def initialize element @element = element end end capsule = Capsule.new '有効成分' puts capsule.element # 有効成分 p capsule # #<Capsule:0x00007f8d909ac660 @element="有効成分"> capsule.element = '毒' p capsule # #<Capsule:0x00007f8d909ac660 @element="毒">classes/Capsule.php<?PHP class Capsule { private $element; public function __construct($element) { $this->element = $element; } public function getElement() { return $this->element; } public function setElement($element) { $this->element = $element; } } $capsule = new Capsule('有効成分'); echo $capsule->getElement(); // 有効成分 var_dump($capsule); // object(Capsule)#1 (1) { // ["element":"Capsule":private]=> // string(12) "有効成分" // } $capsule->setElement('毒'); var_dump($capsule); // object(Capsule)#1 (1) { // ["element":"Capsule":private]=> // string(3) "毒" // }その他ハマりポイント
ライブラリの対応関係
Ruby PHP ライブラリ管理 Gem Composer テスト Rspec PHPUnit Linter Rubocop PHP-CS-Fixerなど コメント RDoc PHPDoc フレームワーク Ruby on Rails Laravel, CakePHPなど 有名どころのライブラリなどの対応関係のみを記載しました。
Rubyと言ったらRails、Railsと言ったらRubyという印象ですが、PHPではフレームワークは複数の選択肢があります。
シェアが高いという意味であればLaravelが近く、MVCの思想に忠実という意味ではCakePHPに近いかなという印象を持っています。真偽判定・nil/null判定
Ruby PHP == そこそこ使う 絶対に使わない Null nil null オブジェクトのNull確認 ! empty() PHPの==はあまりにもヤバいことで有名だと思いますので、比較のときには必ず
===
を使うようにします。
Rubyでのnil
は、PHPだとnull
に該当します。Rubyでは全てがオブジェクトであり、真偽値判定・
nil
判定がうまく設計されていて、オブジェクトのみで直感的に真偽値判定・nil
判定をできることも多いです。
一方、PHPの場合は直感的に真偽値判定・null
判定を行うのは危険なので、型を意識して判定した方が安全です。
オブジェクトがnullや空かどうかを確認するなら、empty()
を使うのが有効です。others/User.rbclass User class << self def find_by_id id # IDが1のときはユーザオブジェクトを返し、それ以外のときはユーザオブジェクトを返さないとします if id == 1 User.new '最初のユーザ' else nil end end end def initialize name @name = name end end def print_user user # ユーザオブジェクトが存在するかを確認する if !user puts 'ユーザはいません' else p user end end user2 = User::find_by_id 2 print_user user2 # ユーザはいません p user2 # nil user1 = User::find_by_id 1 print_user user1 # #<User:0x00007fe70f173f88 @name="最初のユーザ">others/User.php<?php class User { private $name; public function __construct($name) { $this->name = $name; } static function findById($id) { /** IDが1のときはユーザオブジェクトを返し、それ以外のときはユーザオブジェクトを返さないとします */ if ($id === 1) { return new static('最初のユーザ'); } else { return null; } } } function printUser($user) { // ユーザオブジェクトが存在するかを確認する if (empty($user)) { echo 'ユーザはいません'; } else { var_dump($user); } } $user2 = User::findById(2); printUser($user2); // ユーザはいません var_dump($user2); // NULL $user1 = User::findById(1); printUser($user1); // object(User)#1 (1) { // ["name":"User":private]=> // string(18) "最初のユーザ" // }if文の返り値
Ruby PHP if文の返り値 最後の値 なし 分岐によって値を生成する場合 ifの返り値に入れる 一度値を初期化し、再代入する PHPは
if
文の返り値が返ってきません。
そのため、分岐によって値を生成させるケースでは一度値を初期化するなどしてから再代入する、みたいな方法を取る必要があります。どうしても再代入がいやだ、イミュータブルにしたい、という場合は三項演算子という方法もあります。
ただし、三項演算子は多くの場合は処理が分かりにくくなるだけなので、非推奨です。others/day.rbdef print_ymd is_beginning_of_month today = Time.now datetime = if is_beginning_of_month Time.new today.year, today.month, 1 # is_beginning_of_month = falseでは現在日を返す else today # 月初を返す end puts datetime.strftime "%Y年%m月%d日です" end print_ymd false # 2020年12月07日です print_ymd true # 2020年12月01日ですothers/day.php<?php function printYmd($is_beginning_of_month) { $today = new DateTimeImmutable(); $datetime = null; if ($is_beginning_of_month) { // 月初を返す $datetime = new DateTimeImmutable($today->format('Y-m-01')); } else { // $is_beginning_of_month = falseでは現在日を返す $datetime = $today; } echo $datetime->format('Y年m月d日です'); } printYmd(false); // 2020年12月07日です printYmd(true); // 2020年12月01日です /** * 別の書き方。コード量は少ないが分かりにくい */ function printYmd2($is_beginning_of_month) { $today = new DateTimeImmutable(); $datetime = $is_beginning_of_month ? new DateTimeImmutable($today->format('Y-m-01')) : $today; echo $datetime->format('Y年m月d日です'); }名前付き引数がない(PHP7以前)
Ruby PHP7以前 PHP8以後 名前付き引数 引数名: なし 引数名: PHP7以前では名前付き引数がありません。
よって、オプション引数と言いながらも順番を意識して代入する必要があります(辛い)。
このため、依存性注入が凄まじくやりづらいです。PHP8には名前付き引数が導入されています。
【PHP8.0】PHPに名前付き引数が実装されるothers/argument.rbdef calc_goku_scouter original_power, kaio_ken: 1, is_suppressed: false, is_super_saiyan: false power = original_power * kaio_ken if power > 5000 && is_suppressed power = 5000 end if is_super_saiyan power += 100000000 end power end puts calc_goku_scouter 85000 # 85000 puts calc_goku_scouter 85000, kaio_ken: 2 # 170000 puts calc_goku_scouter 85000, is_suppressed: true # 5000 puts calc_goku_scouter 85000, kaio_ken: 20, is_super_saiyan: true # 101700000others/argument.php<?php function calcGokuScouter($original_power, $kaio_ken = 1, $is_suppressed = false, $is_super_saiyan = false) { $power = $original_power * $kaio_ken; if ($power > 5000 && $is_suppressed) { $power = 5000; } if ($is_super_saiyan) { $power += 100000000; } return $power; } echo calcGokuScouter(85000); // 85000 echo calcGokuScouter(85000, 2); // 170000 echo calcGokuScouter(85000, 1, true); // 5000 echo calcGokuScouter(85000, 20, false, true); // 101700000interfaceとabstract
Ruby PHP インターフェース なし interface 抽象クラス なし abstract Rubyには無い概念として、PHPには
interface
,abstract
というものがあります。特に
interface
は重要なのですが、中々概念の理解が難しいかもしれません。
とても勉強になった記事があるので、貼っておきます。
脱PHP初心者!インターフェイスを理解しよう
abstract
はGoFのデザインパターンでいうTemplate Methodパターンを実装するのに必要です。
参考になった記事を貼っておきます。
PHPによるデザインパターン入門 - TemplateMethod〜処理を穴埋めする - Do You PHP はてブロ結び
いかがでしたか?
もし誤記・間違い・より良い書き方などあれば、ご指摘いただけると嬉しいです。一応GitHubにもコードをまとめておきました。
https://github.com/kumackey/php-ruby他参考になりそうなもの
PHPer向けのRuby入門
この記事の逆パターンです。演習問題が付いてる優しさ。PHPerがRubyを勉強するのに役に立つTips
同じくこの記事の逆パターン。元PHPエンジニアがPHPとRubyを比較してみた
PHPとRubyの文法の違いなど。PHPからRubyへ
Rubyの公式が出している、PHPとの違いというドキュメント
- 投稿日:2020-11-20T02:08:58+09:00
ほぼ未経験Webエンジニアが入社半年でしたことまとめ(2020/11)
言語
・PHP
・HTML
・JavaScript
(・MySQL)やったこと
・Web開発用の開発環境構築(XAMPP設定など)(なんだかんだ3,4回した気がする)
・変数や配列など基礎的な内容を理解
・Ajax勉強
・オブジェクト指向の勉強
・セキュリティ少し学んだ
・DBについて少し学んだ
・より良いコードが書けるようにリーダブルコードを読んだ
・リーダブルコードを英語で読みたいと思い、原書を購入(まだ読んでない…)
・mapboxのチュートリアル的なページを確認
・HTMLとJavaScriptにmapboxAPIを組み合わせて、マップ情報を活用したHTMLファイル作成(指定場所の面積計算など)
・エンジニア数十人が書いたエッセイ集みたいな本を買って読んだ
・メルカリ創業の本を読んだ(サクセスストーリー感があって非常に面白かった)
・kotlinとswiftをすこし内容みてみた
・UdemyでswiftとJavaScriptのコース(英語)を受講(現在進行中)感想
・幅広く興味を持っていい経験ができた気がする
・mapboxに触れられたのはよかった
・Udemyの英語コースは、英語の勉強にもなってとてもよい
・ちょっと時間の使い方があまりうまくなかった
・もう少しやりたいことに時間を使えばよかった
・面白いものをもっと探求したかった、開発できていればよかった
・もっと本を読みたい今後やりたいこと
・kotlinまたswiftに本格的に手を出す
・何か1つスマホアプリをリリースする
・フレームワークに手を出す
・JavaScriptでアニメーションっぽいものを駆使して何か面白いものをつくる
・mapboxを駆使して一風変わったワクワクするものをつくりたい
・mapboxでARのAPIが活用出来たら面白そうなので、ARで何かできないか模索する