20201115のPHPに関する記事は24件です。

【PHP】Windowsでツールを作ってみよう(準備編)

はじめに

PHPと言えばブラウザ上で動くサーバ用のプログラミング言語というイメージがあるかと思いますが、
ローカル環境で使えるツールなども手軽に作成することが出来ます。
ここではPHPを使用してWindows環境で使えるツールを作成していきたいと思います。

PHP開発環境構築

まずはPHPの開発環境を構築します。
XAMPPをダウンロード

下記URLへアクセスします。
https://www.apachefriends.org/jp/index.html
qiita_01.png
ページ中段辺りの「Windows 向け XAMPP」をクリックすると、exeファイルがダウンロードできます。

2.ダウンロードしたexeファイルをダブルクリックします。
[インストールするコンポーネント選択]
ApacheとPHPにチェックが入っていることを確認し、Nextボタンを押下。
qiita_02.png

[インストールフォルダ選択]
デフォルトのままで良いので、このままNextボタンを押します。
qiita_03.png

その後、何度かNextボタンを押すとインストールが開始されます。
qiita_04.png
以下の画面が出ればインストール完了です。
qiita_05.png

設定

次に以下の設定を行います。
■XAMPPコントロールパネル設定
1.Cドライブの直下に「xampp」フォルダが出来ていることを確認します
qiita_06.png
2.xamppフォルダへ移動し「xampp-control.exe」を起動します
qiita_07.png
3.Apacheの箇所の「Start」ボタンを押下します
qiita_08.png
4.Apacheが起動し、Port番号が表示されれば成功です
qiita_09.png

■PHP環境変数設定
PHPをコマンドプロンプトから実行するために、環境変数へ登録します。
1.「c:\xampp\php」フォルダに「php.exe」が存在することを確認
qiita_10.png
2.システムのプロパティを開き「詳細設定タブ」の「環境変数」ボタンを押下
qiita_11.png
3.下部の「システム環境変数」の「Path」を選択し「編集」ボタンを押下
qiita_12.png
4.「新規」ボタンを押下
qiita_13.png
5.「c:\xampp\php」と入力し「OK」ボタンを押下
qiita_14.png

サンプルコード作成

1.「c:\xampp\htdocs」フォルダに「sample」フォルダを作成
qiita_16.png

2.「sample」フォルダ内に「hello.php」ファイルを作成し、以下の内容で作成

hello.php
<?php
echo "hello!! php\n";
?>

以下の状態になっていればOKです。
qiita_17.png

動作確認

  1. ブラウザから実行
    ブラウザを起動しURL欄に「http://localhost/sample/hello.php」と入力しエンターキーを押下
    下記のページが表示されれば成功です。
    qiita_18.png

  2. コマンドプロンプトから実行
    2-1.「c:\xampp\htdocs\sample」フォルダを開き、アドレスバーの欄に「cmd」と入力しエンターキーを押下
    qiita_19.png
    2-2.コマンドプロンプトが起動したら「php hello.php」と入力しエンターキーを押下
    qiita_20.png
    2-3.「hello!! php」の文字が表示されれば成功
    qiita_21.png

エラーが発生した場合

■ブラウザアクセス時、以下のページが表示された場合
qiita_22.png
[原因]
Apacheが起動していない

[解決策]
XAMPP Control Panel」よりApacheを起動

■PHP実行時、以下のエラーが表示された場合
qiita_23.png
[原因]
PHPが環境変数に登録されていない
[解決策]
■PHP環境変数設定を参考に登録する

最後に

以上のように、XAMPPを使用すれば簡単にPHPの開発環境が構築出来ることが分かったかと思います。
次回よりPHPを使用してツールを作成していこうと思います!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Humhubのカスタムモジュールの作り方(静的な情報ページを表示するモジュール)

はじめに

今回は、Humhubが拠り所としているYii2フレームワークの、いわゆるMVCモデルに従った、静的な情報ページを作成してみる。目標は、ユーザーのプロファイルページに情報を表示するモジュールを組み上げることだ。Humhubの公式ドキュメントには、この説明はない。Yii2のドキュメントYii2.0決定版ガイド:モジュールのページと、前回までに解説してきた記事とを合わせて以下を読んでいただきたい。

モジュールについて

あらためてYii2.0決定版ガイドを読むと、モジュールについては次の通り記述されている。

モジュールは、モデル、ビュー、コントローラ、およびその他の支援コンポーネントから構成される自己充足的なソフトウェアのユニットです。 
モジュールが アプリケーション にインストールされている場合、エンド・ユーザはモジュールのコントローラにアクセスする事が出来ます。 
これらのことを理由として、モジュールは小さなアプリケーションと見なされることがよくあります。 しかし、モジュールは単独では配備できず、
アプリケーションの中に存在しなければならないという点で アプリケーション とは異なります。

 モジュールは、モジュールの ベース・パス と呼ばれるディレクトリとして編成されます。 このディレクトリの中に、ちょうどアプリケーションの
場合と同じように、controllers、models、views のようなサブ・ディレクトリが存在して、コントローラ、モデル、ビュー、その他のコードを
収納しています。 

モジュール設定情報

Yii2.0決定版ガイドの説明にしたがうようにサブディレクトリを作成して、モジュールのディレクトリを編成していく。まずは、これまでに見てきたように、 humhubのカスタムモジュール設置ディレクトリに、4つのファイル(comfig.php, Event.php, module.json, Module.php)を含むディレクトリを作成しよう。次のようなディレクトリ構成になる。

mymodule
  |-- config.php
  |-- Events.php
  |-- module.json
  |-- Module.php

ユーザーのプロファイルページに情報を表示するので、config.phpには、 ProfileMenu のEVENT_INITのコールバックを設定しよう。

config.php

  use humhub\modules\user\widgets\ProfileMenu;
  ...
  return [
      ...
      ...
      'events' => [
            ...
            [
                'class' => ProfileMenu::class,
                'event' => ProfileMenu::EVENT_INIT,
                'callback' => [ Osintech\humhub\modules\mymodule\Events, 'onProfileMenuInit']
            ],
            ...
      ]
   ]

そして、 Events.php にて onProfileMenuInit ファンクションをパブリックで宣言する。今回の重点は、このファンクションの中で描かれる'url'項目だ。

Envents.php

  ...
  ...
  public static function onProfileMenuInit($event)
  {
    if ($event->sender->user !== null ) {
        $event->sender->addItem([
            'label' => 'Information',
            'icon' => '<i class="fa fa-cubes"></i>',
            'url' => $event->sender->user->createUrl('/mymodule/information'),
            'isActive' => (Yii::$app->controller->module
                              && Yii::$app->controller->module->id == 'mymodule'),
            'sortOrder' => 9999,
        ]);
    }
  }
  ...
  ...

Menuへの addItem ファンクションの引数として、配列を渡している。配列の中は、'label', 'url', 'icon', 'isActive', 'sortOrder' のキーを設定している。それぞれ、およそ次のような意味であろう(例によってHumhubの公式ドキュメントはないので、筆者の経験と推定だ。)。

キー
label メニューに表示されるアイテム名
icon メニューに表示されるアイコン。FontAwesomeIcon(たぶん、Ver.4)で指定する。
url メニュー選択で遷移するルート。'/モジュール名/ビュー名'の書式で記述する。
isActive アクティブ(有効)にする条件。ほぼお約束のようで、&& のあとでModule自身のIDを指定する。
sortOrder ソート順。数字が大きいほど、メニューの下に並ぶ。

ここまでで、humhubにログインし、マイプロフィールの画面を見て見ると、次のように、アイコンとラベルが指定されて最下段(sorOrder=9999)に表示されていることが確認できるだろう。
sample.png

ちなみに、このままここをクリックすると・・・
sample2.png

まだルートの先を構築していないので当然ではあるが、「クリックすれば動作する」ということが達成できただけでも少し嬉しくなってしまう。(いや、動いて当然なのだが、その当然がちゃんとしてることがどれだけありがたいか・・・。この当然を手に入れるまでの手探り開発の労苦を知るものは少ないだろう・・・。)

Viewの作成

先にしていたルートは、informationビューへのルートであった。このため、viewsフォルダの中には、informationフォルダを作成し、そこにindex.phpを配置しなければならない。次のようにディレクトリを構成し、ファイルを作成する。

mymodule
|-- config.php
|-- Events.php
|-- module.json
|-- Module.php
|-- views
    |-- information
         |-- index.php

index.html を次のように編集しておく。

<?php
   use humhub\modules\ui\icon\widgets\Icon;
?>

<div class="panel panel-default">
  <div class="panel-heading">QiitaでHumhub扱っている人</div>
    <div class="panel-body">
    <?= Icon::get('thumbs-o-up') ?><?php echo $information_value; ?>
    </div>
  </div>
</div>

必要なコンポーネント、ウィジェットをはじめの <?php ~ ?>ブロック内で use 宣言し、その後は、html文内で必要に応じて呼び出して利用する。この例では、uiモジュールのIconウィジェットをuse宣言し、'thumbs-o-up'なFontAwesomeIconを呼び出して表示に使っている。Humhubがさまざまなモジュール、コンポーネントを用意しているようだが、全容を紹介しているような資料がみつからない。オープンソースになっているモジュールがどのようなViewを作成しているのか、真似しながら手探りで作ってみるしかない。
また、$information_valueの値をechoしているが、このファイルの中では$information_valueの値は決定していない。この部分はControllerから変数を渡すことができるのだ。(まさにMVCモデル!)

Controllerの作成

controllersディレクトリを作成し、ルートに従ったControllerを設置する。このとき、controllerのファイル名は、 メニューの addItem ファンクションで指定した引数に従って'ビュー名Controller.php'と命名しなければならない。なお、ビュー名の最初の1文字は大文字にする。今回の例では、次のようになる。

mymodule
|-- config.php
|-- Events.php
|-- module.json
|-- Module.php
|-- views
|   |-- information
|       |-- index.php
|-- controllers
    |-- InformationController.php

さて、このファイルの中で この controllerのクラスを宣言して、ファンクションを記述するのだが・・・。参照元となるControllerを何にするか、は表示を行いたい場面によって異なるので注意だ。筆者の試したところでは、次のような種類があった。

コントローラクラス 動作(表示場所・範囲) 画面サンプル
\humhub\components\Controller または \Yii\web\Controller サイドメニューおよびサイドウィジェットのスペースを確保しない地の部分に表示する。 sample3.png
\humhub\modules\content \components\ContentContainerController コンテンツコンテナ部分(コンテンツが表示される、メニューを残した部分)に表示する。 sample4.png
\humhub\modules\admin \components\Controller (今回は扱わない)モジュールのAdminメニューのイベントをコールバックし、Adminメニューで管理者向けに表示させたい情報のときに使う (例) sample5.png
\humhub\modules\content \components\ContentAddonController コンテンツのウィジェット内部のアドオン表示部。”いいね”や”コメント”といったアドオンメニューの場所。 (例)sample6.png

今回は、プロフィールのコンテンツが表示される場所に情報を表示したいので、\humhub\modules\content\components\ContentContainerController クラスのExtendsとして、コントローラクラスを記述する。

<?php
    namespace Osintech\humhub\modules\mymodule\controllers;
    use \humhub\modules\content\components\ContentContainerController;

    class InformationController extends ContentContainerController
    {
      public function actionIndex()
      {
        return $this->render('index', ['information_value' => "少人数"]);
      }
    }

記述にあたって、class名は、ファイル名で決定している。そのクラス、InformationControllerクラスの中で、パブリックファンクションとして actionIndex() を記述している。これは、 表示させたいviewのファイルを actionビューファイル名() というファンクション名で記述するルールに従ったものである。そして、そのファンクションの返り値として、 $this->render('ビューファイル名', [表示ファイルPHPに渡す変数を連想配列で記述])のレンダリング結果を出力する。これにより画面に情報が表示される。

先のviewにおいて、\$information_valueという変数を利用するように記述してあった。このコントローラでは、その変数に対する値の入力を行なっているのが見て取れるだろう。viewでは\$記号がついていた変数名について、コントローラで\$記号なしで記述している点にも注意だ。

まとめ

今回は、humhubのモジュールで静的な情報表示ページのサンプルを作成した。次回は、ページに対する装飾を扱ってみたいと思う。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC-CUBE4 プラグインのテンプレートを上書きする方法

EC-CUBE4のバージョン4.0.5にアップデートによって、プラグインのテンプレートを直接編集することなくapp/templateフォルダ内で編集することが可能になりました。

実装方法

このようなプラグインのファイル配置のとき、

[app/Plugin/Sample]
│ 
├── Controller
│   └── Admin
│       └── Controller.php
├── Resource
│   └── template
│       └── admin
│           └── config.twig

app/template/plugin/Sample/admin/config.twigに配置することで、こちらを優先して読み込まれます。

[app/template]
│
├── admin
├── default
├── plugin
│   └── Sample
│       └── admin
│           └── config.twig
└── user_data

サンプル

商品レビュープラグインのテンプレートを編集してみようと思います。
※ちなみに、こちらです。https://www.ec-cube.net/products/detail.php?product_id=1756

対象ファイルはapp/Plugin/ProductReview4/Resource/template/default/review.twigです。

review.twig
<div id="reviewContent">
      ...
            {% else %}
                <p>{{ 'product_review.front.product_detail.no_review'|trans }}</p>
            {% endif %}
        </div>

*app/template/plugin/ProductReview4/default/に編集したreview.twigを配置。

review.twig
<div id="reviewContent">
      ...
            {% else %}
                <p>{{ 'product_review.front.product_detail.no_review'|trans }}</p>wwwwwwww
            {% endif %}
        </div>

編集後はキャッシュを削除しましょう。

php bin/console cache:clear --no-warmup

スクリーンショット 2020-11-15 22.37.02.png
↓編集後↓
スクリーンショット 2020-11-15 22.42.47.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Zabbixのログイン画面「Cannot start session.」

Zabbixのログイン画面が表示されない。

エラー
Cannot start session.

sessionの所有者は?

PHPのアップデートでsessionの所有者が変わる事象があるらしい。

 ll /var/lib/php/
合計 16
drwxrwx--- 2 root apache     6 10月 28 01:22 opcache
drwxr-xr-x 2 root root       6 10月 28 01:22 peclxml
drwxrwx--- 2 root apache 12288 10月 28 01:22 session
drwxrwx--- 2 root apache     6 10月 28 01:22 wsdlcache

nginxを使っているので、nginxユーザに変更してあげると解決

chown -R nginx:nginx /var/lib/php/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

権限(パーミッション)について

注意:この記事ではセキュリティに関する変更を加える記事になっております。この記事を元に発生した問題や損害に対しては、当方一切の責任を負いませんので、コマンドなどを実行する場合は必ず自己の責任が及ぶ範囲内でお願いいたします。

この記事で出てくる用語

file_put_contents() → PHPを実行した際に、指定されたパスのファイルに内容を加える。
file_get_contents() → PHPを実行した際に、指定されたパスのファイルの内容を呼び出す。
Permission → ディレクトリやファイルを操作する時の権限。(日本語で再帰的)


先日、PHPの学習をしている時に、file_put_contents()file_get_contents()を使用する場面があったのですが、そこでハマってしまったので解決方法を残しておきます。

結論から言うとPermissionの問題でした。



Permissionの確認方法

筆者が使っているのはMacOSなので、まずターミナルを開きます。その次にPermissionを確認したいディレクトリの1階層上まで移動し、下記のコマンドを入力します。

$ ls -la

するとディレクトリとファイルごとに、下記のような表記がずらっと出てきます。

drwxrwxrwx 1 username admin 1918 4 21 14:22 example.html

左端の列が、右端に表示されているディレクトリかファイルのPermissionを示しています。(それ以外はあまり気にしなくて大丈夫です。)
一番左側のdは複雑らしいので無視して、大切なのはrwxが3つ続いている部分になります。


  • 1つ目のrwxは、読み込みのアクセス権限
  • 2つ目のrwxは、書き込みのアクセス権限
  • 3つ目のrwxは、実行のアクセス権限



そして、rwxのそれぞれが示す権限は以下の通りです。

  • rは作成者
  • wは作成者グループ下の編集者
  • xは作成者でも編集者でも無い者(不特定多数)。




Permissionの変更方法(カレントディレクトリ下の全て)

無事にPermissonの確認を終えたら、いよいよ問題のディレクトリ、もしくはファイルのPermissionの変更をしていきます。
先ほど移動したカレントディレクトリのまま、以下のようなコマンドを実行します。

$ chmod 765

まずchmod(チェンジモード)を打ち込むことによって、Permissionの変更が可能な状態にします。そして次に任意の数字を入れて実行すれば、カレントディレクトリ下にある、全てのディレクトリとファイルのPermissionを変更することができます。


因みに任意の数字は以下のように決めることができます。

rwx rwx rwx r-- -w- --x rwx rw- r-x
 ↓    ↓    ↓   ↓  ↓  ↓   ↓   ↓   ↓
 7      7      7  4    2    1  7     6     5
        ↓       ↓        ↓
       777      421       765



表の真ん中の列を見てもらえればわかりやすいですが、rwxはそれぞれナンバリングがされています。


  • rは 4
  • wは 2
  • xは 1

そのため、rwxにしたい場合は 4+2+17 と計算することができます。
そしてrwxrwxrwxにしたい場合は 777777 と数字を打ち込めばOKです。


※ただし、上記で紹介している 777 は、誰でも読み込み、書き込み、実行ができてしまうと言う、セキュリティ上では非常に危険な状態となってしまう為、非推奨となります。


また、Permissionは作成者によって、何かしら必要な意味のある状態で保存されていることが多いので、試しに変更した場合は再度chmodを使用して、元のPermissionに戻しておくと良いでしょう。



Permissionの変更方法(指定したファイルのみ)

カレントディレクトリ下の全てのPermissionを変更するのではなく、こちらで指定して任意のディレクトリ、もしくはファイルのみのPermissionを変更したい場合は、以下のようなコマンドを実行します。

$ chmod 765 example.html

この場合、カレントディレクトリ下のexample.htmlPermission765 に変更することになります。

僕の場合は、このように1つだけファイルのPermissionを変更して、今回の問題だったfile_put_contents()file_get_contents()の実行をできるようにして、解決することができました。



まとめ

今回ご紹介したコマンドの一覧です。

$ ls -la
$ chmod 765
$ chmod 765 example.html

また繰り返しになりますが、Permissionの設定は、セキュリティと関わりのある大事な設定になりますので、変更する際は慎重に行ってください。


最後まで読んでいただき、ありがとうございました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Permission(アクセス権限)について

注意:この記事ではセキュリティに関する変更を加える記事になっております。この記事を元に発生した問題や損害に対しては、当方一切の責任を負いませんので、コマンドなどを実行する場合は必ず自己の責任が及ぶ範囲内でお願いいたします。

この記事で出てくる用語

file_put_contents() → PHPを実行した際に、指定されたパスのファイルに内容を加える。
file_get_contents() → PHPを実行した際に、指定されたパスのファイルの内容を呼び出す。
Permission → ディレクトリやファイルを操作する時の権限。(日本語で再帰的)


先日、PHPの学習をしている時に、file_put_contents()file_get_contents()を使用する場面があったのですが、そこでハマってしまったので解決方法を残しておきます。

結論から言うとPermissionの問題でした。



Permissionの確認方法

筆者が使っているのはMacOSなので、まずターミナルを開きます。その次にPermissionを確認したいディレクトリの1階層上まで移動し、下記のコマンドを入力します。

$ ls -la

するとディレクトリとファイルごとに、下記のような表記がずらっと出てきます。

drwxrwxrwx 1 username admin 1918 4 21 14:22 example.html

左端の列が、右端に表示されているディレクトリかファイルのPermissionを示しています。(それ以外はあまり気にしなくて大丈夫です。)
一番左側のdは複雑らしいので無視して、大切なのはrwxが3つ続いている部分になります。


  • 1つ目のrwxは、読み込みのアクセス権限
  • 2つ目のrwxは、書き込みのアクセス権限
  • 3つ目のrwxは、実行のアクセス権限



そして、rwxのそれぞれが示す権限は以下の通りです。

  • rは作成者
  • wは作成者グループ下の編集者
  • xは作成者でも編集者でも無い者(不特定多数)。




Permissionの変更方法(カレントディレクトリ下の全て)

無事にPermissonの確認を終えたら、いよいよ問題のディレクトリ、もしくはファイルのPermissionの変更をしていきます。
先ほど移動したカレントディレクトリのまま、以下のようなコマンドを実行します。

$ chmod 765

まずchmod(チェンジモード)を打ち込むことによって、Permissionの変更が可能な状態にします。そして次に任意の数字を入れて実行すれば、カレントディレクトリ下にある、全てのディレクトリとファイルのPermissionを変更することができます。


因みに任意の数字は以下のように決めることができます。

rwx rwx rwx r-- -w- --x rwx rw- r-x
 ↓    ↓    ↓   ↓  ↓  ↓   ↓   ↓   ↓
 7      7      7  4    2    1  7     6     5
        ↓       ↓        ↓
       777      421       765



表の真ん中の列を見てもらえればわかりやすいですが、rwxはそれぞれナンバリングがされています。


  • rは 4
  • wは 2
  • xは 1

そのため、rwxにしたい場合は 4+2+17 と計算することができます。
そしてrwxrwxrwxにしたい場合は 777777 と数字を打ち込めばOKです。


※ただし、上記で紹介している 777 は、誰でも読み込み、書き込み、実行ができてしまうと言う、セキュリティ上では非常に危険な状態となってしまう為、非推奨となります。


また、Permissionは作成者によって、何かしら必要な意味のある状態で保存されていることが多いので、試しに変更した場合は再度chmodを使用して、元のPermissionに戻しておくと良いでしょう。



Permissionの変更方法(指定したファイルのみ)

カレントディレクトリ下の全てのPermissionを変更するのではなく、こちらで指定して任意のディレクトリ、もしくはファイルのみのPermissionを変更したい場合は、以下のようなコマンドを実行します。

$ chmod 765 example.html

この場合、カレントディレクトリ下のexample.htmlPermission765 に変更することになります。

僕の場合は、このように1つだけファイルのPermissionを変更して、今回の問題だったfile_put_contents()file_get_contents()の実行をできるようにして、解決することができました。



まとめ

今回ご紹介したコマンドの一覧です。

$ ls -la
$ chmod 765
$ chmod 765 example.html

また繰り返しになりますが、Permissionの設定は、セキュリティと関わりのある大事な設定になりますので、変更する際は慎重に行ってください。


最後まで読んでいただき、ありがとうございました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

「Qiita」と「WordPress」のRSSを取得して、PHPで静的HTMLに表示する方法

外部サイトのRSS情報を取得して表示させる方法

参考にしたページはこのあたり。

PHPで外部サイトのRSS情報を取得して表示させる方法。 - 株式会社オンズ
https://on-ze.com/archives/1615

新着情報を受け取る!PHPでRSSを取得する方法 | TechAcademyマガジン
https://techacademy.jp/magazine/18803

これで「Qiita」の記事を新着情報に表示させたい的なことをやろうとして、
サンプルはその通りにしたら表示されるのですけど、
「Qiita」のRSSフィードだと上手く行かなくてですねー、

結論として言うと
ページによって「RSSフィード」の形式が違うのが原因でした。

output-rss-qiita.php

それで「Qiita」のRSS形式に合わせた
RSSフィードを取得して表示する「.php」がこちら

<!-- ?output-rss.php -->
<?php
// RSSフィードからRSSを取得
$feed = file_get_contents('https://qiita.com/sarap422/feed');

// XML解析を行う上で、XMLで不正文字と扱われる対象を空文字に変換
$invalid_characters = '/[^\x9\xa\x20-\xD7FF\xE000-\xFFFD]/';
$feed = preg_replace($invalid_characters, '', $feed);

// 文字列をXMLとして解析して、SimpleXMLElementクラスのインスタンスに変換
$rss = simplexml_load_string($feed);
?>
<?php
date_default_timezone_set('Asia/Tokyo');
$count = 0;
?>
<dl class="row mx-auto">
    <?php foreach ($rss->entry as $entry) : ?>
        <?php
        // 取得回数の指定
        if ($count >= 3) { break; }
        ?>
        <?php
        $entry_title = $entry->title;
        $entry_pub = date("Y-m-d", strtotime($entry->published));
        $entry_url = $entry->url;
        $entry_cont = mb_strimwidth(strip_tags($entry->content), 0, 110, "…Read More", "utf-8");
        ?>
        <dt class="col-lg-4"><?php echo $entry_pub; ?></dt>
        <dd class="col-lg-8 text-left"><a href="<?php echo $entry_url; ?>" target="_blank" rel="noopener noreferrer">
                <?php echo $entry_title; ?></dd>
        </a></li>
        <?php $count++; ?>
    <?php endforeach; ?>
</dl>
<!--ƒ /?output-rss.php -->

output-rss-wp.php

ついでに「WordPress」は「記事データの取得」から新着情報を表示する方法もあるのですけど、「RSSフィードからの取得」に統一した方がデザインとかたぶんやりやすいですよね?

ということで、「WordPress」のRSS形式に合わせた
RSSフィードを取得して表示する「.php」がこちら

<!-- ?output-rss.php -->
<?php
// RSSフィードからRSSを取得
$feed = file_get_contents('https://sarap422.com/wp1/feed');

// XML解析を行う上で、XMLで不正文字と扱われる対象を空文字に変換
$invalid_characters = '/[^\x9\xa\x20-\xD7FF\xE000-\xFFFD]/';
$feed = preg_replace($invalid_characters, '', $feed);

// 文字列をXMLとして解析して、SimpleXMLElementクラスのインスタンスに変換
$rss = simplexml_load_string($feed);
?>
<?php
date_default_timezone_set('Asia/Tokyo');
$count = 0;
?>
<dl class="row mx-auto">
    <?php foreach ($rss->channel->item as $item) : ?>
        <?php
        // 取得回数の指定
        if ($count >= 3) { break; }
        ?>
        <?php
        $item_title = $item->title;
        $item_pub = date("Y-m-d", strtotime($item->pubDate));
        $item_link = $item->link;
        $item_desc = mb_strimwidth(strip_tags($item->description), 0, 110, "…Read More", "utf-8");
        ?>
        <dt class="col-lg-4"><?php echo $item_pub; ?></dt>
        <dd class="col-lg-8 text-left"><a href="<?php echo $item_link; ?>" target="_blank" rel="noopener noreferrer">
                <?php echo $item_title; ?></a></dd>
        <?php $count++; ?>
    <?php endforeach; ?>
</dl>
<!--ƒ /?output-rss.php -->

rowmx-autocol-lgは、「Bootstrap」のclassなので、適当に変えてください。

「foreach」構文について

ちなみに「foreach」構文は、

<?php foreach ($array as $parameter){
    繰り返したい内容
} ?>
<?php foreach ($array as $parameter) : ?>
    繰り返したい内容
<?php endforeach; ?>

の、どちらでもいいらしいのですけど、
今のところ自分の場合は、 <> で囲んだ方が、htmlタグもそのまま書けるし、
見やすいかなーということで、その書き方にしました。
ついでに引っ張ってくる回数($count >= 3)も指定できるように。

あと「.htaccess」に、AddHandler fcgid-script .html を書いて
静的HTMLに「output-rss.php」をそのまま書けばたぶん動きそうなんですが、

それだとHTMLがゴチャゴチャするので、
「output-rss.php」を「WordPress」の「theme」内に置いて、
上位ディレクトリの「index.html」から「get_template_part」で
「output-rss.php」を引っ張ったら、
何故かディレクトリ指定することもなくそのまま動きました。

<!-- 「get_template_part」はWordPress構文 -->
<?php get_template_part ( 'output-rss-qiita' );  ?>
<?php get_template_part ( 'output-rss-wp' );  ?>

本当は、WordPressの「theme」外の「.php」はそれで置き場変えたいのですけど、
ちょっとよくわからなくて、今PHPの勉強中だし時間かけて無理して調べるところじゃないので現状そんな感じで以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP8.0からはin_arrayの第3引数のtrueを付け忘れても、意図しない挙動が防げるようになる

TL;DR

<?php

$hogeArray = ["hoge", "foo", "bar"];

// PHP 7まで
in_array(0, $hogeArray); // true(意図しない挙動)

in_array(0, $hogeArray, true); // false

// PHP 8
var_dump(in_array(0, $hogeArray)); // false

PHP 8からは、in_arrayの第三引数を省略しても、上記のような意図しない挙動が防げるようになる。

背景

非厳密な比較演算子==の挙動が変更になる

2020/11/26より、PHPの5年ぶりの時期メジャーバージョンアップであるPHP 8がリリースされます。JITなど、重要なRFCが目白押しですが、その中に「非厳密な比較演算子 == の挙動が変更になる」というものがあります。

詳しくは、PHP RFC: Saner string to number comparisons や、他の方が書かれた分かりやすい記事【PHP8.0】非厳密な比較演算子==の挙動が今さら変更になるをご参照ください。

本記事の主題に入る前に、非厳密な比較演算子==の挙動の変更について述べる必要があるため、ざっくりと説明します。


数値(例:0)と数値文字列(例:"0")を非厳密演算子 == で比較する場合、数値文字列は数値に変換されて文字列比較されます。

php8以前
<?php
0 == "0"; // true

それ以外の場合(例:数値と数値文字列以外の文字列の比較)は、文字列を数値に変換して比較します。数値文字列以外の文字列を数値へ変換した場合は 0 になるので、以下の結果になります。

php8以前
<?php
0 == "hoge"; // true

しかし、PHP 8へのメジャーバージョンアップデートによって、 == の挙動が変わります。
数値文字列以外の文字列と数値を比較する場合は、数値を文字列に変換してから、文字列比較するようになります。

php8
<?php
0 == "hoge"; // false

in_arrayの挙動が変わる

本記事の主題です。

非厳密な比較演算子 == の挙動の変更により、in_arrayの挙動も変更となります。

in_arrayは、第3引数でstrictが設定されていない限りは型の比較は行いません。つまり、 == を使って比較しています。

そのため、今までは意図しない挙動を予防するために、in_arrayの第3引数には true をつける必要がありました。

参考:in_arrayを使うときは黙って第三引数を付けること

ですが、今回のPHP 8へのメジャーバージョンアップデートによって、== の挙動が変更になったことにより第3引数にtrueを付けなくとも、意図しない挙動が起きなくなります。

php8
<?php

$hogeArray = ["hoge", "foo", "bar"];
in_array(0, $hogeArray); // false

さいごに

PHP 8の登場により、非厳密な比較演算子 == での比較はより安全になりました。
以下に示した例で、$needleSample0 などになっているエッジケースが起こった場合にin_arrayの第3引数を付け忘れていたことで、問題の特定に開発者が頭を抱えることが少なくなりそうです。

<?php

$hogeArray = ["hoge", "foo", "bar"];

if (in_array($needleSample, $hogeArray)) {
  // なんかの処理
}

注意: この記事は == での比較が今までより安全になったから、これからはin_arrayの第3引数の省略をとにかく推奨する内容ではありません。

自分の調べた範囲では、第3引数を省略しても、今まで発生していた意図しない挙動を防ぐことを確認できましたが、調査し切れておらず防げないパターンがあるかもしれません(是非ご指摘ください:qiitan:)

よって、第3引数を省略して、業務コーディング中に防げないパターンについてあれこれ考察するのは時間を浪費です。乱暴な言い方ですが、これからも困ったら第3引数のstructtrueにしておけば安定です。

補足(2020/11/26まで)

メジャーアップデートは2020/11/26ですが、その前にPHP 8の挙動を確認したい方は、

PHP 8.0のイメージをpullしてこればカレントディレクトリにPHPファイルを置いて、以下のようにPHP 8環境で挙動を試すことができます。

docker run --rm -v `pwd`:/app -w /app php:8.0-rc php php8test.php

参考情報

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP8.0からはin_arrayの第三引数のtrueを付け忘れても意図しない挙動が防げるようになる

TL;DR

<?php

$hogeArray = ["hoge", "foo", "bar"];

// PHP 7まで
in_array(0, $hogeArray); // true(意図しない挙動)

in_array(0, $hogeArray, true); // false

// PHP 8
var_dump(in_array(0, $hogeArray)); // false

PHP 8からは、in_arrayの第三引数を省略しても、上記のような意図しない挙動が防げるようになる。

背景

非厳密な比較演算子==の挙動が変更になる

2020/11/26より、PHPの5年ぶりの時期メジャーバージョンアップであるPHP 8がリリースされます。JITなど、重要なRFCが目白押しですが、その中に「非厳密な比較演算子 == の挙動が変更になる」というものがあります。

詳しくは、PHP RFC: Saner string to number comparisons や、他の方が書かれた分かりやすい記事【PHP8.0】非厳密な比較演算子==の挙動が今さら変更になるをご参照ください。

本記事の主題に入る前に、非厳密な比較演算子==の挙動の変更について述べる必要があるため、ざっくりと説明します。


数値(例:0)と数値文字列(例:"0")を非厳密演算子 == で比較する場合、数値文字列は数値に変換されて文字列比較されます。

<?php
0 == "0"; // true

それ以外の場合(例:数値と数値文字列以外の文字列の比較)は、文字列を数値に変換して比較します。数値文字列以外の文字列を数値へ変換した場合 0 になるので、以下の結果になります。

<?php
0 == "hoge"; // true

しかし、PHP 8へのメジャーバージョンアップデートによって、 == の挙動が変わります。
数値文字列以外の文字列と数値を比較する場合は、数値を文字列に変換してから、文字列比較するようになります。

<?php
0 == "hoge"; // false

in_arrayの挙動が変わる

本記事の主題です。

上記で説明した、非厳密な比較演算子 == の挙動の変更により、in_arrayの挙動も変更となります。

in_arrayは、第3引数でstrictが設定されていない限りは型の比較は行いません。つまり、非厳密な比較演算子の == を使って比較しています。

そのため、今までは意図しない挙動を予防するため、in_arrayの第3引数には true をつける必要がありました。
参考:in_arrayを使うときは黙って第三引数を付けること

ですが、今回のPHP 8へのメジャーバージョンアップデートによって、== の挙動が変更になったことにより第3引数にtrueを付けなくとも、PHP 8以前の意図しない挙動が起きなくなります。

<?php

$hogeArray = ["hoge", "foo", "bar"];
in_array(0, $hogeArray); // false

さいごに

PHP 8の登場により、非厳密な比較演算子 == での比較はより安全になりました。
以下のような記述をしていて、$needleSample0 とかになっているエッジケースが起こった場合にin_arrayの第3引数を付け忘れたことで、開発者が頭を抱えることが少なくなりそうです。

<?php

$hogeArray = ["hoge", "foo", "bar"];

if (in_array($needleSample, $hogeArray)) {
  // なんかの処理
}

注意ですが、この記事は == での比較が今までより安全になったから、これからはin_array第の3引数を省略することをとにかく推奨する内容のものではありません。

自分の調べた範囲では、第3引数を省略しても今まで発生していた意図しない挙動を防ぐことを確認できましたが、調査し切れておらず防げないパターンがあるかもしれません(是非ご指摘ください)。

よって、第3引数を省略して業務コーディング中に防げないパターンについてあれこれ考察して時間を消費するよりも、乱暴な言い方ですが困ったら第3引数のstructtrueにしておけば安心です。

追記(2020/11/26まで)

メジャーアップデートは2020/11/26ですが、その前にPHP 8の挙動を確認したい方は、

PHP 8.0のイメージをpullしてこればカレントディレクトリにPHPファイルを置いて、以下のようにPHP 8環境で挙動を試すことができます。

docker run --rm -v `pwd`:/app -w /app php:8.0-rc php php8test.php

参考情報

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

配列変数 と 連想配列 初学者が初学者向けにまとめた

どうも。
今まで掲示板等々を学習がてら作成してきましたが、5ヶ月というスパンで焦り走りしてきた事で
「フワッとした理解」で「〇〇機能は〇〇で実装できるだろう」と何となく分かるものの、Google先生の力がなければこれ一つ自分で実装できない僕が、
一つ一つの細かな理解が疎かであることから、
これから基礎の基礎を深く理解するためにアウトプットの場としてQiitaに投稿していきます。

自身でGoogle先生を活用して数十サイトや書籍を参考に理解を深めながら、
1、、実際にコードを書いて
2、、ノートに自分の言葉でいつかの自分が見ても伝わるようにまとめていく
3、、最後にQiitaに他の方が見ても分かるよう伝えていく

※間違い部分、誤解している箇所が出てくる可能性もあります。

[配列とは]

複数(プロパティ)のデータをまとめて整理して1つの大きな箱にいれるイメージ。
333.png
出力結果:アイス

呼び方まとめ

・青box1つ1つのまとまりをプロパティと呼ぶ。

・ここでは$box全ての部分を【配列】と呼ぶ。

・自動的に割り当てられる添字のことを【キー】と呼ぶ。

・アイス、チョコアイス、カレー味アイスの部分を【値】と呼ぶ。

問題

ee.png

正解はスクロールしたらすぐ出てきますので、ここから下にスクロールせず解答してみること。

正解:2.3.4.1

※プロパティを要素、配列をインデックスとも呼ぶ。

問題2

Hamburger 配列変数に
テリヤキバーガー/ベーコンレタスバーガー/ホットケーキ
上記3つのハンバーガー[]を上記の順番に格納すること
最後にテリヤキバーガーを出力結果に表示してください

先ずは自身でやること。
答えは以下のリンクを押すと出てきます。
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

次に、$Hamburger配列変数からテリヤキバーガーとホットケーキを改行して出力結果に表示してください。
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

改行の仕方は複数通りあるため上記URLの方法以外でも改行して出力出来ていればOK!!

ちなみに、上記URLの通りに文字列の中に変数を取り入れる場合は""(ダブルクォーテーション)です。
ダブルクォーテーションとシングルクォーテーションの違いは以下URLが非常に分かりやすいです!
https://qiita.com/bitcoinjpnnet/items/64458299eaeefbacab44

配列に格納されている値を全て出力結果に表示するには?

foreach文を使います。

【foreach文とは】
(リスト)や(配列)に格納されたデータ[要素とも値とも呼ぶ]に対して記述[プログラム]された処理を
繰り返し実行する力を持っているループ文です。

$box = ['アイス','チョコアイス','カレー味アイス'];
foreach($box as $value) {
    echo $value;
}
出力結果:アイスチョコアイスカレー味アイス

格納されたデータが全て出力されると繰り返し終了します。

また、添字[キー]も出力したい場合には

foreach ($box as $key=>$value){
echo "$key=>$value \n";
}

出力結果:
0=>アイス
1=>チョコアイス
2=>カレー味アイス

おさらいです。
文字列の中で変数展開したい場合はダブルクォーテーションで囲む。
\nは改行を意味します。
Macユーザーの方は半角[optionキー+¥]。

$valueの部分は任意名です。

問題3

Hamburger配列変数に格納されてる値を全て出力結果に表示してください。

答え
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

Hamburger配列変数に格納されている値とキーを全て出力結果に表示してください。
条件
改行を行うこと。
カンマ/コンマをいれること

表示結果例
キー=>値、
キー=>値、
キー=>値、

答え
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

但し、やり方は複数通りある。

これである程度配列についての理解が出来たのではないでしょうか?
配列を初めて聞いた方は少しまだ理解できていないかもしれません。
Google先生に「配列 とは」で検索すると結構出てきます。

それでは次に連想配列について理解を深めていきたいと思います。

連想配列とは

任意の文字列をキーに割り当てる事が可能。
・文字列(クォーテーションで囲むもの)
・整数

連想配列の良いところ

・キーが任意文字列のため値と同じ意味を持たせた文字列にすればパッと見て分かりやすい!
例: Apple =>りんご car => 車

・1つの小箱(要素ともいうプロパティともいう)にキーと値で2つの意味を持たせれる。
例: 顧客の連絡先と名前を管理したい場合
例: '〇〇会社小林様' => xxx-xxxx-xxxx(これは電話番号です)

実際に試して覚えよう!

連想配列のキーに割り当てられるが注意すべき事

・true false ・・・ キーに割り当てれるが、true = 1 false = 0に自動変換される
・小数点       ・・・ キーに割り当てれるが、自動的に切り捨て整数に自動変換される


実際に試して覚えよう!
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

連想配列もつまりは配列の仲間なので配列を理解出来れば連想配列も理解できると思います。

次回、配列を複数の出力方法で出力をし、ループ処理等を併せて理解する記事を書きます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel Mixを使用してSCSSをCSSにコンパイルしてみよう

開発環境

  • Laravel 8.0
  • php 7.3
  • laravel-mix 5.0.1

はじめに

今回はlaravelにSCSSを導入してから実際にコンパイルするまでの流れを記事にしています。
※すでにLaravelプロジェクトを立ち上げている前提での手順になりますのでご了承ください

Laravel Mix

Laravel Mixとは、フロントエンドのアセットをコンパイル、バンドルしてくれるツール。
ツールの中身はwebpackを利用している

webpackを使うと何がいいの?

・依存性を解決できる
・リクエスト数を減らすことができる

SCSSを導入するにあたって本記事ではLaravel Mixを使用します。
すでに、package.jsonにLaravel Mixは最初から記述されているためターミナルでnpm installしちゃいましょう

$ npm install

次にwebpack.mix.jsを開いてみるとこんな感じになってます

webpack.mix.jsとはwebpackというJavaScriptパッケージツールで使うもの(ラッパー)

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel applications. By default, we are compiling the CSS
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js')
    .postCss('resources/css/app.css', 'public/css', [
        //
    ]);

実際にコンパイルしてみる

まずはresources内にsassディレクトリを作成して、その中にapp.scssを作成します。

そして、webpack.mix.jsを下記内容に編集

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel applications. By default, we are compiling the CSS
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');
//  resources/sass/app.scssを参照して、public内にcssのファイルを作成します 

編集したらターミナルでnpm run dev

$ npm run dev

成功したら、public内にcssが生成されているのを確認してください。

以上でLaravel Mixを使用してSCSSを導入するまでの流れになります。

補足

バンドル(合体)してコンパイルするケース↓↓

 // jsファイルをバンドル(合体)したい場合
mix
.scripts([ 'public/js/app.js' , 'public/js/app2.js' ], 'public/js/all.js' );
//[admin.jsとdashboard.js]を all.js としてバンドル(合体)させます。

// cssファイルをバンドル(合体)したい場合
mix
.styles([ 'public/css/app.css' , 'public/css/app2.css' ], 'public/css/all.css' );
// app.css と app2.css をバンドル(合体)させて
// publicフォルダに all.css を作成します。


5:各views/○○○○.blade.phpでの使用方法

<!-- Scripts(JSの場合※srcで呼び出します。) -->
<script src="./public/index.js"></script>

<!-- Styles(CSSの場合※hrefで呼び出します。) -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">

便利コマンド

公式ドキュメント参照

npm run watch
コマンドはターミナルで実行し続け、関連ファイル全部の変更を監視します。
Webpackは変更を感知すると、アセットを自動的に再コンパイルします。

npm run watch-poll
特定の環境のWebpackでは、ファイル変更時に更新されないことがあります。
自分のシステムでこれが起きた場合は、watch-pollコマンドを使用してください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel Mixを使用してSCSSを導入してみよう

開発環境

  • Laravel 8.0
  • php 7.3
  • laravel-mix 5.0.1

はじめに

今回はlaravelにSCSSを導入してから実際にコンパイルするまでの流れを記事にしています。
※すでにLaravelプロジェクトを立ち上げている前提での手順になりますのでご了承ください

Laravel Mix

Laravel Mixとは、フロントエンドのアセットをコンパイル、バンドルしてくれるツール。
ツールの中身はwebpackを利用している

webpackを使うと何がいいの?

・依存性を解決できる
・リクエスト数を減らすことができる

SCSSを導入するにあたって本記事ではLaravel Mixを使用します。
すでに、package.jsonにLaravel Mixは最初から記述されているためターミナルでnpm installしちゃいましょう

$ npm install

次にwebpack.mix.jsを開いてみるとこんな感じになってます

webpack.mix.jsとはwebpackというJavaScriptパッケージツールで使うもの(ラッパー)

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel applications. By default, we are compiling the CSS
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js')
    .postCss('resources/css/app.css', 'public/css', [
        //
    ]);

実際にコンパイルしてみる

まずはresources内にsassディレクトリを作成して、その中にapp.scssを作成します。

そして、webpack.mix.jsを下記内容に編集

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel applications. By default, we are compiling the CSS
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');
//  resources/sass/app.scssを参照して、public内にcssのファイルを作成します 

編集したらターミナルでnpm run dev

$ npm run dev

成功したら、public内にcssが生成されているのを確認してください。

以上でLaravel Mixを使用してSCSSを導入するまでの流れになります。

補足

バンドル(合体)してコンパイルするケース↓↓

 // jsファイルをバンドル(合体)したい場合
mix
.scripts([ 'public/js/app.js' , 'public/js/app2.js' ], 'public/js/all.js' );
//[admin.jsとdashboard.js]を all.js としてバンドル(合体)させます。

// cssファイルをバンドル(合体)したい場合
mix
.css([ 'public/css/app.css' , 'public/css/app2.css' ], 'public/css/all.css' );
// app.css と app2.css をバンドル(合体)させて
// publicフォルダに all.css を作成します。


5:各views/○○○○.blade.phpでの使用方法

<!-- Scripts(JSの場合※srcで呼び出します。) -->
<script src="./public/index.js"></script>

<!-- Styles(CSSの場合※hrefで呼び出します。) -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">

便利コマンド

公式ドキュメント参照

npm run watch
コマンドはターミナルで実行し続け、関連ファイル全部の変更を監視します。
Webpackは変更を感知すると、アセットを自動的に再コンパイルします。

npm run watch-poll
特定の環境のWebpackでは、ファイル変更時に更新されないことがあります。
自分のシステムでこれが起きた場合は、watch-pollコマンドを使用してください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

バリデーションのメッセージ カスタマイズしてみた

バリデーションのメッセージカスタマイズ

validation.phpの中エラーメッセージを変更せずに、オリジナルのバリデーションメッセージを
設定してバリデートメッセージを出せたので記事にしました。

基本的には英語ですが、validation.phpの中に設定されています。
日本語版は下記から確認できます。
https://readouble.com/laravel/5.6/ja/validation-php.html

一部ですが、こんな感じでバリデーションメッセージが設定されています。
attributeは好きなように設定できます。

'required'=> ':attributeは必須です。',
'unique'   => ':attributeは既に存在します。',

 'attributes' => [
 'first_name'=>'姓名',
 'last_name'=>'姓名',
]

下記のようにバリデーションを設定できます。
このように設定すると、first_name、last_nameが空欄の場合、
姓名は必須です。などとエラーメッセージが出力されます。

  public function rules()
    {
        return [
            'first_name' => 'required',
            'last_name' => 'required',
        ];
    }

例えば、他のbladeではattributeは必要です。としたい場合、
'required'=> ':attributeは必要です。',

上記のように変えてあげればよいのですが、そうすると先程のエラーメッセージも変わってしまいます。
ここのページだけメッセージを変えるということができるのです。

結論、messages()メソッドを設定できます。
下記のように設定してあげると、実現できます。

    public function messages()
    {
        return [
            'first_name.required' => ':attributeは必要です。'
        'last_name.required' => ':attributeは必要です。'
        ];
    }

まとめ

messages()メソッドを追加して、first_name.requiredとドット区切りで指定すると、メッセージのみ変更可能でした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPで湯婆婆を短く書く

はじめに

この投稿は @Nemesis さんの Javaで湯婆婆を実装してみる をはじめとした湯婆婆ムーヴに乗っかったものです。
@TD12734 さんの HTMLで最も短い湯婆婆(記事内で試せます) に触発されPHPでも短く書けないか試してみました。

とりあえず普通に書く

<?php
$realName = "安達桜";
$splittedRealname = mb_str_split($realName);
$newName = $splittedRealname[array_rand($splittedRealname)];

echo 'フン。' . $realName . 'というのかい。贅沢な名だねぇ。今からお前の名前は' . $newName . 'だ。いいかい、' . $newName . 'だよ。分かったら返事をするんだ、' . $newName . '!!';
// 実行結果
// フン。安達桜というのかい。贅沢な名だねぇ。今からお前の名前は桜だ。いいかい、桜だよ。分かったら返事をするんだ、桜!!

マルチバイトの扱いの関係で多少冗長になってしまいましたが、文字列を mb_str_split()することで配列化することができます。
その配列の中からランダムに1つを取り出すことで新しい名前が無事決まりました。

名前を外部から与えられるようにする

yubaba.php
<?php
$splittedRealname = mb_str_split($_GET['realname']);
$newName = $splittedRealname[array_rand($splittedRealname)];

echo 'フン。' . $_GET['realname']. 'というのかい。贅沢な名だねぇ。今からお前の名前は' . $newName . 'だ。いいかい、' . $newName . 'だよ。分かったら返事をするんだ、' . $newName . '!!';

幸いにしてPHPではURLにクエリを付与することにより外部から入力を与えることができます。
この例でしたらブラウザからアクセスする際に yubaba.php?realname=安達桜 とすることで最初に書いたプログラムと同等になるはずです。多分。

コードを短くしていく

yubaba.php
<?="フン。".($r=$_GET['r'])."というのかい。贅沢な名だねぇ。今からお前の名前は".($n=mb_str_split($r)[rand(0,mb_strlen($r)-1)])."だ。いいかい、{$n}だよ。分かったら返事をするんだ、{$n}!!";

($r=$_GET['r'])($n=mb_str_split($r)[rand(0, mb_strlen($r)-1)])の部分は変数への代入と表示を一括して行っています。
さらにPHPでは文字列をダブルクォートで括ることで、その文字列中の{}内は変数展開が行われるため文字数省略には有用なテクニックです。

PHPのバージョンを5.3まで下げる

yubaba.php
<?="フン。{$r}というのかい。贅沢な名だねぇ。今からお前の名前は".($n=preg_split('//u',$r)[rand(1,mb_strlen($r)-1)])."だ。いいかい、{$n}だよ。分かったら返事をするんだ、{$n}!!";

PHP5.3では悪名高いregister_globalsが使用可能です。(register_globalsについては下記の記事をご参照ください)
PHP 5.4 以上でも register_globals を再現するライブラリ MercifulPolluter

こちらを有効にすることで$_GET['r']をわざわざ書かなくて済むようになります。なんて便利なんだ。
その代わりPHP7で追加されたmb_str_splitが使用できなくなってしまいますので、代わりにpreg_split('//u',$r)を使用しました。
ただし、このままだと分割した配列の最初と最後が空文字になってしまうため、randの範囲を調整することで空文字部分を選ばないようにしています。

名前をシングルバイト文字前提とする

yubaba.php
<?="フン。{$r}というのかい。贅沢な名だねぇ。今からお前の名前は".($n=str_shuffle($r)[0])."だ。いいかい、{$n}だよ。分かったら返事をするんだ、{$n}!!";

マルチバイトで扱おうとするからコードが冗長になるのです。
シングルバイトを前提にすれば1文字抜き取る部分はstr_shuffle($r)[0]だけでよくなります。

ちなみにこちらで無理やりマルチバイトの名前を通すと文字化けします。

yubaba.php
<?php
$_GET['r']="安達桜";
?>

<?="フン。".($r=$_GET['r'])."というのかい。贅沢な名だねぇ。今からお前の名前は".($n=str_shuffle($r)[0])."だ。いいかい、{$n}だよ。分かったら返事をするんだ、{$n}!!";

//実行結果
//フン。安達桜というのかい。贅沢な名だねぇ。今からお前の名前は�だ。いいかい、�だよ。分かったら返事をするんだ、�!!

ファイル名を変える

仕上げにファイル名を湯婆婆のセリフとして問いかけも実装すれば完成です。
アクセスする際のURIは契約書だよ。そこに名前を書きな。.php?r=adachisakuraのようになります。

契約書だよ。そこに名前を書きな。.php
<?="フン。{$r}というのかい。贅沢な名だねぇ。今からお前の名前は".($n=str_shuffle($r)[0])."だ。いいかい、{$n}だよ。分かったら返事をするんだ、{$n}!!";

終わりに

出かけるつもりが1時間も記事作成に費やしてしまった…

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】リダイレクトの書き方メモ

  • リダイレクト定義の書き方について。
リダイレクトの基本
// httpの場合
return redirect('test/index');                 // http://xxxxx/test/index
return redirect()->to('test/index');           // ↑と同義
return redirect('test/index', 301);            // ステータスコードを指定する場合(※ デフォルトは、302)
return redirect('test/index', 301, ['test-header' => 'テスト'] ); // HTTPヘッダー を追加する場合

// httpsの場合
return redirect('test/index', 302, [], true);  // https://xxxxx/test/index


// ルート名での指定
return redirect()->route('test.list');
return redirect()->route('test.show', ['id' => 12]);      // id情報を含むルーティングの場合(例: test/{id} )
$user = App\User::find(12);                               // ↑と同義
return redirect()->route('test.show', ['id' => $test]);


// コントローラ名での指定
return redirect()->action('TestController@index');
return redirect()->action('TestController@show', ['id' => 12]);    // id情報を含む場合

パス、アクションの指定

パス、アクションの指定
return redirect($to = null, $status = 302, $headers = [], $secure = null);          // パスの指定
return redirect()->to($path, $status = 302, $headers = [], $secure = null);         // 取得インスタンスへのパス指定
return redirect()->route($route, $parameters = [], $status = 302, $headers = []);   // 取得インスタンスへのルート指定
return redirect()->action($action, $parameters = [], $status = 302, $headers = []); // 取得したインスタンスへアクション指定
return redirect()->away($path, $status = 302, $headers = []);                       // 取得したインスタンスへの外部ドメインの指定

// コントローラを使わず、リダイレクト先を指定する場合
Route::redirect($uri, $destination, $status = 301);

データも一緒にリダイレクト

セッションデータと一緒にリダイレクト(※フラッシュメッセージなどに使う)
return redirect('home')->with('result', '完了');
return redirect('home')->with([       // 複数データを格納する場合は、配列で!
    'result_1'=>'成功-1', 'result_2'=>'成功-2', 'result_3'=>'成功-3'
]);
// ビューで取得
{{ session('result') }}

直前ページへのリダイレクト

直前ページにリダイレクト
// 基本
public function back() {
    return back();
}

// データも一緒に、直前ページに戻す場合
public function back() {
    return back()->with('result', 'ok!');
    return back()->withInput();     // 送信データがセッション内に格納される
}
// ビューで取得
{{ session('result') }}

// 例
public function back(Request $request) {
    return back()->withInput($request->only(['email']));
}
// ビューで取得
<textarea name="message">{{ old('message') }}</textarea>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コマンドなしでGithubにコードをアップロードして、Github Desktopに追加する方法

こんにちは、くりぱんです。

この記事で実現できること

  1. Githubにコードをアップロードできる
  2. Github Desktopにアップロードしたリポジトリを追加できる

開発環境

  • OS:MacOS
  • Git:2.29.2

説明

私は個人開発や個人学習のために、Githubへコードをアップロードしています。
また、コードを簡単に管理できるように、Github Desktopを使用しています。
今回は、Githubへコードをアップロードしてもらい、Github Desktopを使用してコードを管理できるようにする方法を説明していきます。

簡単実装

実装準備

Githubのアカウントを下記から取得してください。
https://github.com/

Github Desktopを下記からダウンロードしてください。
https://desktop.github.com/

Github

  • まずは、Newをクリック
    スクリーンショット 2020-11-15 0.52.14.png

  • ①にfirst_githubと入力して、②のCreate repositoryをクリック
    ※ ①のfirst_githubは任意の名前で大丈夫です。
    スクリーンショット 2020-11-15 0.53.50.png

  • Set up in Desktopをクリック
    スクリーンショット 2020-11-15 1.03.32.png

  • GitHub Desktop.appを開くをクリック
    スクリーンショット 2020-11-15 1.14.56.png

  • Choose...をクリック
    スクリーンショット 2020-11-15 1.15.54.png

  • Finderで今回アップロードするコードが入ったフォルダを選択し、開くをクリック
    私の場合は、今回/Applications/MAMP/htdocs/first_githubというLaravelのプロジェクトをGithubにアップロードするので、'first_github'を選択しています。
    スクリーンショット 2020-11-15 1.16.42.png

  • パスを確認して、OKならCloneをクリック
    スクリーンショット 2020-11-15 1.20.13.png

  • 右上に今回追加したfirst_githubのリポジトリがGithub Desktopに追加されているのがわかります。
    スクリーンショット 2020-11-15 1.21.22.png

これで自由にコード管理ができるようになります!
Github Desktopは、とても簡単に操作できるのでぜひ使ってみてください!

最後に

コマンドなしでGithubにコードをアップロードして、Github Desktopでコマンドなしでコミットやマージなど何でもできます。初学者の方にも扱いやすいので、ぜひ良いコード管理ライフをお楽しみください!

Twitterもやってます!
プログラミングや金融知識、英語、エンジニアの現実についてつぶやいています!
よかったら見てみてくださいね!

https://twitter.com/sakuslife

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

スクレイピングでアクセスできない時の対処法(php)

はじめに

php 7.3
スクレイピングでアクセスできない場合をまとめました。
curlを使用しました。

リダイレクトされる

ページURLが変更されてリダイレクトされている場合です。
この場合は、オプションでリダイレクト先へ飛ぶようにします

test.php
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_FOLLOWLOCATION => true, //リダイレクトを辿る
        CURLOPT_MAXREDIRS => 10,  //リダイレクト数
        CURLOPT_AUTOREFERER => true,  //リダイレクトした際のRefererのURLを自動セット
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

HTTPSにアクセスしてエラー

サーバー証明書の検証でエラーが起きた場合です。
この場合は、オプションで証明書の検証をしないように設定して回避します

test.php
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_SSL_VERIFYPEER => false, //証明書の検証を行わないよう設定
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

ブラウザで除外される

ブラウザからは見えるのに、プログラムではアクセスできない場合です。
どのブラウザからのアクセスかをサーバ側で判定してエラーページに遷移させたりします。
この場合は、ヘッダーのユーザーエージェントを偽装してアクセスします。
ユーザーエージェントの中身は変更していただいても構いません。

test.php
    $headers = array(
        "HTTP/1.0",
        "User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
    );
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => $headers,  //ヘッダーのUser-Agentに通常のPCからのアクセスのように見せかけます
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

Cookieで除外される

ブラウザからは見えるのに、プログラムではアクセスできない場合です。
Cookieの中身を判定して、エラーページに遷移させたりします。
curlではCookieを明示的に付与しなければ空でアクセスされるため、そういったプログラムでのアクセスを回避するために設定されている場合があります。
この場合は、サーバからCookieを受け取り、そのCookieを使用してアクセスするようにします。

test.php
    $headers = array(
        "HTTP/1.0",
        "Connection:keep-alive",
        "User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
    );
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => $headers,  
        CURLOPT_COOKIEJAR => "test.cookie", //Cookieを取得してカレントディレクトリにtest.cookieファイルとして保存
        CURLOPT_COOKIEFILE => "test.cookie", //カレントディレクトリのtest.cookieファイルをCookieとして使用して通信
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

アクセスはできたが、圧縮されている

値は帰ってきたが文字化けしている場合です。エンコーディングの違いも考えられるので中身をみて判断してください。
圧縮されている場合は取得時にエンコーディングするようにオプションで設定します。

test.php
    $headers = array(
        "HTTP/1.0",
        "Accept-Encoding:gzip ,deflate",
        "Connection:keep-alive"
    );
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => $headers,  
        CURLOPT_ENCODING => 'gzip',  //zip形式でエンコーディングする
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

最後に

スクレイピングで情報を抜き出す際には、対象ページの利用規約でスクレイピングが禁止されていないか、著作権法、個人情報保護法に抵触しないか、相手のサーバに負荷をかけすぎないかなどをよく確認の上、行われた方が良いかと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

スクレイピングする時にアクセスできない(php)

はじめに

php 7.3
スクレイピングでアクセスできない場合をまとめました。
curlを使用しました。

リダイレクトされる

ページURLが変更されてリダイレクトされている場合です。
この場合は、オプションでリダイレクト先へ飛ぶようにします

test.php
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_FOLLOWLOCATION => true, //リダイレクトを辿る
        CURLOPT_MAXREDIRS => 10,  //リダイレクト数
        CURLOPT_AUTOREFERER => true,  //リダイレクトした際のRefererのURLを自動セット
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

HTTPSにアクセスしてエラー

サーバー証明書の検証でエラーが起きた場合です。
この場合は、オプションで証明書の検証をしないように設定して回避します

test.php
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_SSL_VERIFYPEER => false, //証明書の検証を行わないよう設定
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

ブラウザで除外される

ブラウザからは見えるのに、プログラムではアクセスできない場合です。
どのブラウザからのアクセスかをサーバ側で判定してエラーページに遷移させたりします。
この場合は、ヘッダーのユーザーエージェントを偽装してアクセスします。
ユーザーエージェントの中身は変更していただいても構いません。

test.php
    $headers = array(
        "HTTP/1.0",
        "User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
    );
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => $headers,  //ヘッダーのUser-Agentに通常のPCからのアクセスのように見せかけます
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

Cookieで除外される

ブラウザからは見えるのに、プログラムではアクセスできない場合です。
Cookieの中身を判定して、エラーページに遷移させたりします。
curlではCookieを明示的に付与しなければ空でアクセスされるため、そういったプログラムでのアクセスを回避するために設定されている場合があります。
この場合は、サーバからCookieを受け取り、そのCookieを使用してアクセスするようにします。

test.php
    $headers = array(
        "HTTP/1.0",
        "Connection:keep-alive",
        "User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
    );
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => $headers,  
        CURLOPT_COOKIEJAR => "test.cookie", //Cookieを取得してカレントディレクトリにtest.cookieファイルとして保存
        CURLOPT_COOKIEFILE => "test.cookie", //カレントディレクトリのtest.cookieファイルをCookieとして使用して通信
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

アクセスはできたが、圧縮されている

値は帰ってきたが文字化けしている場合です。エンコーディングの違いも考えられるので中身をみて判断してください。
圧縮されている場合は取得時にエンコーディングするようにオプションで設定します。

test.php
    $headers = array(
        "HTTP/1.0",
        "Accept-Encoding:gzip ,deflate",
        "Connection:keep-alive"
    );
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => $headers,  
        CURLOPT_ENCODING => 'gzip',  //zip形式でエンコーディングする
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

最後に

スクレイピングで情報を抜き出す際には、対象ページの利用規約でスクレイピングが禁止されていないか、著作権法、個人情報保護法に抵触しないか、相手のサーバに負荷をかけすぎないかなどをよく確認の上、行われた方が良いかと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPのビルトイン関数まとめ(ファイル関連)

はじめに

PHPの学習をはじめたので、アウトプットとして記載します。

ビルトイン関数とは

ビルトインとはあらかじめ組み込まれていることを意味します。
関数は自身で作ることができますが、PHPにはあらかじめ用意された関数があり、それらをビルトイン関数と呼びます。

PHPのビルトイン関数(ファイル関連)

fopen:ファイルを開く、fclose:ファイルを閉じる、fwrite:ファイルに書き込む

phpファイル
$fp = fopen('names.txt', 'w'); //names.txtを'w'(書き込みモード)で開く、ファイルがない場合は作られる

fwrite($fp, "taro\n"); //テキストファイルにtaroの文字を書き込む、\nは改行の意味

fclose($fp); //開いたファイルを閉じる

fopenのオプション

phpファイル
$fp = fopen('names.txt', 'w'); //'w'はwrite(書き込みモード)の意味
$fp = fopen('names.txt', 'a'); //'a'はappend(追加するモード)の意味
$fp = fopen('names.txt', 'r'); //'r'はread(読み込みモード)の意味

fread:サイズを指定してファイルを読み込む、filesize:ファイルサイズを調べる

phpファイル
$fp = fopen('names.txt', 'r');
$contents = fread($fp, filesize('names.txt')); //$contentsにname.txtの中身を代入
fclose($fp);
echo $contents;

fgets:ファイルを1行ずつ読み込む

phpファイル
$fp = fopen('names.txt', 'r');
while (($line = fgets($fp))!== false) { 
  echo $line;
}  //names.txtを1行ずつ読み込み、読み込み終了時に読み込みした内容を表示する
fclose($fp);

file_put_contents:fopenを使わず、ファイルに書き込む

phpファイル
$contents = "taro\njiro\nsaburo\n";
file_put_contents('names.txt', $contents); //names.txtファイルの中にtaro\njiro\nsaburo\nが書き込まれる

file_get_contents:fopenを使わず、ファイルを読み込む

phpファイル
$contents = file_get_contents('names.txt'); //names.txtファイルの中身を$contentsの中に入れることができる

file:ファイルの中身を配列にする

phpファイル
$lines = file('names.txt', FILE_IGNORE_NEW_LINES); //$linesはnames.txtの中身を順に入れた配列となる
//FILE_IGNORE_NEW_LINESは末尾の改行をなくすオプション

opendir:ディレクトリを操作できるようにする、readdir:ディレクトリの中身を1行ずつ読み込む

phpファイル
file_put_contents('data/taro.txt', "taro\n");
file_put_contents('data/jiro.txt', "jiro\n");

$dp = opendir('data');
while(($item = readdir($dp)) !== false) {
  if ($item === '.' || $item == '..'){
    continue;
  }  //dataディレクトリの中身(ファイル)が存在する限り$itemに代入する、ただし、'.'や'..'は除く
  echo $item . PHP_EOL;
}

glob:指定したパスを配列として取り出す、basename:ファイル名だけ取り出せる

phpファイル
foreach (glob('data/*.txt') as $item) { //globで取り出したファイルを要素とする配列の要素を$itemに代入する
  echo $item . PHP_EOL; // ファイルを表示する、表示はdata/〇〇.txtの形式
  echo basename($item) . PHP_EOL; // ファイルを表示する、表示は〇〇.txtの形式
}

file_exits:ディレクトリやファイルが存在する時true、存在しない時falseを返す
is_writable:ファイルが書き込み可能な時true、書き込み不可の時falseを返す
is_readable:ファイルが読み込み可能な時true、読み込み不可の時falseを返す

phpファイル
file_exists('data'); //dataディレクトリもしくはdataファイルがあれば、true
is_writable('data/taro.txt'); //dataディレクトリ内のtaro.txtが書き込み可能ならtrue
is_readable('data/taro.txt'); //dataディレクトリ内のtaro.txtが読み込み可能ならtrue

参考

ドットインストール

最後に

本投稿が初学者の復習の一助となればと幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPのビルトイン関数まとめ(配列)

はじめに

PHPの学習をはじめたので、アウトプットとして記載します。

ビルトイン関数とは

ビルトインとはあらかじめ組み込まれていることを意味します。
関数は自身で作ることができますが、PHPにはあらかじめ用意された関数があり、それらをビルトイン関数と呼びます。

PHPのビルトイン関数(配列)

implode:配列をつなげる

phpファイル
$d = [2020, 11, 15];
echo implode('_', $d) . PHP_EOL;
=> 2020_11_15

explode:変数を配列にする

phpファイル
$t = '17:32:45';
print_r(explode(':', $t));
=> Array
(
    [0] => 17
    [1] => 32
    [2] => 45
)

array_unshift:配列の先頭に要素を加える、array_push:配列の末尾に要素を加える

phpファイル
$scores = [30, 40, 50];

array_unshift($scores, 10, 20);
print_r($scores);
=> Array
(
    [0] => 10
    [1] => 20
    [2] => 30
    [3] => 40
    [4] => 50
)

array_push($scores, 60, 70);
print_r($scores);
=> Array
(
    [0] => 10
    [1] => 20
    [2] => 30
    [3] => 40
    [4] => 50
    [5] => 60
    [6] => 70
)

array_shift:配列の先頭の要素を削除する、array_pop:配列の末尾の要素を削除する

phpファイル
$scores = [30, 40, 50];

array_shift($scores);
print_r($scores);
=> Array
(
    [0] => 40
    [1] => 50
)

array_pop($scores);
print_r($scores);
=> Array
(
    [0] => 40
)

array_splice:配列の要素を削除・追加できる

phpファイル
$scores = [30, 40, 50, 60, 70, 80];

array_splice($scores, 2, 3); //2番目の要素から3つ分の要素を削除する
print_r($scores);
=> Array
(
    [0] => 30
    [1] => 40
    [2] => 80
)
phpファイル
$scores = [30, 40, 50, 60, 70, 80];

array_splice($scores, 2, 3, 100); //2番目の要素から3つ分の要素を削除し、その位置に100を追加する
print_r($scores);
=> Array
(
    [0] => 30
    [1] => 40
    [2] => 100
    [3] => 80
)
phpファイル
$scores = [30, 40, 50, 60, 70, 80];

array_splice($scores, 2, 0, [100, 101]); //2番目の要素から削除はせずに、100と101を追加する
print_r($scores);
=> Array
(
    [0] => 30
    [1] => 40
    [2] => 100
    [3] => 101
    [4] => 50
    [5] => 60
    [6] => 70
    [7] => 80
)

array_slice:配列から要素を切り取る

phpファイル
$scores = [30, 40, 50, 60, 70];

以下は3行は全て同じ意味の記述
$partial = array_slice($scores, 3, 2); //3番目の要素から2つ分の要素を切り取る
$partial = array_slice($scores, 2); //3番目の要素から最後の要素の要素まで切り取る
$partial = array_slice($scores, -2); //後ろから2番目の要素から最後の要素まで切り取る

print_r($partial);
=> Array
(
    [0] => 60
    [1] => 70
)

sort:配列を値の小さい順に並べ替える、rsort:配列を値の大きい順に並び替える、shuffle:配列の順番はランダムに並び替える

phpファイル
$scores = [40, 50, 20, 30];

sort($scores);
print_r($scores);
=> Array
(
    [0] => 20
    [1] => 30
    [2] => 40
    [3] => 50
)

rsort($scores);
print_r($scores);
=> Array
(
    [0] => 50
    [1] => 40
    [2] => 30
    [3] => 20
)

shuffle($scores);
print_r($scores);
=> Array
(
    [0] => 20
    [1] => 30
    [2] => 40
    [3] => 50
)

array_rand:配列のキーをランダムに切り取る

phpファイル
$scores = [40, 50, 20, 30];

$picked = array_rand($scores, 2);
echo $scores[picked[0]] . PHP_EOL;
echo $scores[picked[0]] . PHP_EOL;
=> 出力する度に配列からランダムに2つの値が出る

array_fill:配列に値を指定した個数入れる

phpファイル
$scores = array_fill(0, 5, 10); //0番目から5個分の要素に10を入れる

range:配列に順番に値を入れる

phpファイル
$scores = range(2, 10); //2~10までの値が配列の要素を入れる
$scores = range(2, 10, 3); //2に3ずつ足して10以下の値を配列の要素に入れる([2, 5, 8])

array_sum:配列を全て足し合わせる

phpファイル
$scores = [1, 2, 3];
echo array_sum($scores); //1+2+3
=> 6

array_merge:複数の配列をつなげる

phpファイル
$a = [3, 4, 8];
$b = [4, 8, 12];
$c = [1, 2];

$merged = array_merge($a, $b, $c); //[3, 4, 8, 4, 8, 12, 1, 2]

array_unique:配列から重複している要素を取り除く

phpファイル
$a = [3, 4, 8];
$b = [4, 8, 12];

$merged = array_merge($a, $b); //[3, 4, 8, 4, 8, 12]
array_unique($merged); //[3, 4, 8, 12]

array_diff:第一引数の配列から第二引数の配列の要素と同じものを取り除く

phpファイル
$a = [3, 4, 8];
$b = [4, 8, 12];

array_diff($a, $b); //[3, 4, 8]から4と8が取り除かれ、[3]となる

array_intersect:引数の配列の共通要素のみ配列にする

phpファイル
$a = [3, 4, 8];
$b = [4, 8, 12];
$c = [3, 4, 8];

array_intersect($a, $b, $c); //[4, 8]

array_map:配列に対し関数の処理を実行する

phpファイル
$prices = [100, 200, 300];

$newPrices = array_map(
  function($n) {return $n * 1.1;}, //第一引数に関数(fn($n) => $n * 1.1に置き換えても同じ意味)
  $prices                //第二引数に配列
);
//$newPrices = [110, 220, 330]

array_filter:配列に関数の処理を実行し、Trueのものだけ取り出す

phpファイル
$numbers = range(1, 10); //$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

$evenNumbers = array_filter(
  $numbers,              //第一引数に配列
  fn($n) => $n % 2 === 0 //第二引数に関数
);
//$evenNumbers = [2, 4, 6, 8, 10]

array_keys:配列のキーのみ取り出す、array_values:配列のバリューのみ取り出す

phpファイル
$scores = [
  'dog' => 80,
  'cat' => 70,
  'rat' => 60,
];

array_keys($scores); //['dog', 'cat', 'rat']
array_values($scores); //[80, 70, 60]

array_key_exists:指定したキーがあればtrue、なければfalseを返す
in_array:指定したバリューがあればtrue、なければfalseを返す

phpファイル
$scores = [
  'dog' => 80,
  'cat' => 70,
  'rat' => 60,
];

array_key_exists('dog', $scores); //true
in_array(80, $scores); //true

array_search:指定したバリューを探し、そのキーを返す

phpファイル
$scores = [
  'dog' => 80,
  'cat' => 70,
  'rat' => 60,
];

array_search(70, $scores); //cat

asort:キーを保持したまま、バリューを昇順に並び替える
arsort:キーを保持したまま、バリューを降順に並び替える
ksort:キーを昇順に並び替える
krsort:キーを降順に並び替える
※キーを添字以外で指定していた場合、sortやrsortで並び替えるとキーが添字に変換されてしまう。

phpファイル
$scores = [
  'dog' => 80,
  'cat' => 70,
  'rat' => 60,
];

asort($scores);
print_r($scores);
=> Array
(
    [rat] => 60
    [cat] => 70
    [dog] => 80
)

arsort($scores);
print_r($scores);
=> Array
(
    [dog] => 80
    [cat] => 70
    [rat] => 60
)

ksort($scores);
print_r($scores);
=> Array
(
    [cat] => 70
    [dog] => 80
    [rat] => 60
)

krsort($scores);
print_r($scores);
=> Array
(
    [rat] => 60
    [dog] => 80
    [cat] => 70
)

usort:何を比較して並び替えるか定義できる関数(配列の中に複数の配列がある場合)

phpファイル
$data = [
  ['name' => 'dog', 'score' => 80],
  ['name' => 'cat', 'score' => 60],
  ['name' => 'rat', 'score' => 70],
  ['name' => 'fox', 'score' => 60],
];

usort(
  $data,
  function($a, $b){
    if($a['score'] === $b['score']) {
      return 0;
    }                                           //並び替えない時は0を返す
    return $a['score'] > $b['score'] ?  1: -1;  //並び替える時は後ろに回すものに1、前に回すものに-1を返す
  }
);

print_r($data);
=> Array
(
    [0] => Array
        (
            [name] => cat
            [score] => 60
        )

    [1] => Array
        (
            [name] => fox
            [score] => 60
        )

    [2] => Array
        (
            [name] => rat
            [score] => 70
        )

    [3] => Array
        (
            [name] => dog
            [score] => 80
        )

)

array_column:配列のカラム内の値を取得する

phpファイル
$data = [
  ['name' => 'dog', 'score' => 80],
  ['name' => 'cat', 'score' => 60],
  ['name' => 'rat', 'score' => 70],
  ['name' => 'fox', 'score' => 60],
];

$scores = array_column($data, 'score');
print_r($scores);
=> Array
(
    [0] => 80
    [1] => 60
    [2] => 70
    [3] => 60
)

array_multisort:配列を複数のカラムで並び替える時に使う

phpファイル
$data = [
  ['name' => 'dog', 'score' => 80],
  ['name' => 'cat', 'score' => 60],
  ['name' => 'rat', 'score' => 70],
  ['name' => 'fox', 'score' => 60],
];

$scores = array_column($data, 'score');
$names = array_column($data, 'name');

array_multisort(
  $scores, SORT_DESC, SORT_NUMERIC, //SORT_DESCは降順、SORT_NUMERICは数値を意味するオプション
  $names, SORT_DESC, SORT_STRING, //SORT_STRINGは文字列を意味するオプション、デフォルトは昇順
  $data
);

print_r($data);
=> Array
(
    [0] => Array
        (
            [name] => dog
            [score] => 80
        )

    [1] => Array
        (
            [name] => rat
            [score] => 70
        )

    [2] => Array
        (
            [name] => fox
            [score] => 60
        )

    [3] => Array
        (
            [name] => cat
            [score] => 60
        )

)

参考

ドットインストール

最後に

本投稿が初学者の復習の一助となればと幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPのビルトイン関数まとめ(文字列や数値)

はじめに

PHPの学習をはじめたので、アウトプットとして記載します。

ビルトイン関数とは

ビルトインとはあらかじめ組み込まれていることを意味します。
関数は自身で作ることができますが、PHPにはあらかじめ用意された関数があり、それらをビルトイン関数と呼びます。

PHPのビルトイン関数(文字列や数値)

sprintf:フォーマットした文字列を返す
%s:文字列、%d:整数、%f:浮動小数点数

phpファイル
<?php

$name = 'Apple';
$score = 32.246;

$info = "[$name][$score]";
echo $info . PHP_EOL;
=> [Apple][32.246]

$info = sprintf("[%15s][%10.2f]", $name, $score); //15は15文字、10.2は小数点含め10文字、小数点以下2文字
echo $info . PHP_EOL;
=> [          Apple][     32.25]

$info = sprintf("[%-15s][%010.2f]", $name, $score); //-15は全部で15文字で文字列は左づめ、%0は0が手前に出る
echo $info . PHP_EOL;
=> [Apple          ][0000032.25]

printf:フォーマットした文字列を出力する(sprintfとechoが合体したようなもの)

phpファイル
<?php

$name = 'Apple';
$score = 32.246;

printf("[%-15s][%010.2f]" . PHP_EOL, $name, $score);
=> [Apple          ][0000032.25]

strlen:文字列の長さを表示する

phpファイル
$input = 'dot_yamada';
echo strlen($input) . PHP_EOL;
=> 10

mb_strlen:日本語の文字列の長さを表示する

phpファイル
$input = 'こんにちは';
echo strlen($input) . PHP_EOL;
=> 5

strpos:文字列の中の指定した文字の場所を表示する

phpファイル
$input = 'dot_yamada';
echo strpos($input, '_') . PHP_EOL;
=> 3 //順番は0から始まる

mb_strpos:日本語の文字列の中の指定した文字列の場所を表示する

phpファイル
$input = 'こんにちは';
echo strpos($input, 'に') . PHP_EOL;
=> 2 //順番は0から始まる

trim:空白を取り除く

$input ='   dot_yamada';
echo $input . PHP_EOL;
=>    dot_yamada

$input = trim($input);
echo $input . PHP_EOL;
=> dot_yamada

str_replace:文字を入れ替える

$input = 'dot_yamada';
$input = str_replace('_', '-', $input); //$inputの'_'を'-'に入れ替える
echo $input . PHP_EOL;
=> dot-yamada

substr:固定長データからデータを抜き出す

$input = '20200320Item-A  1200';
$date = substr($input, 0, 8);
echo $date . PHP_EOL;
=> 20200320

substr_replace:固定長データのデータを入れ替える

$input = '20200320Item-A  1200';
$input = substr_replace($input, 'Item-B  ', 8, 8);
echo $input . PHP_EOL;
=> '20200320Item-B  1200';

number_format:数字を3桁ごとにカンマを入れる

$input = 1200
echo number_format($input) . PHP_EOL;
=> 1,200

preg_match:パターンに合致するもの一つを引き出す

$input = 'Call us at 03-3001-1256 or 03-3015-3222';
$pattern = '/\d{2}-\d{4}-\d{4}/'; //正規表現

preg_match($pattern, $input, $matches);
print_r($matches);
=> Array
(
    [0] => 03-3001-1256
)

preg_match_all:パターンに合致するもの全てを引き出す

$input = 'Call us at 03-3001-1256 or 03-3015-3222';
$pattern = '/\d{2}-\d{4}-\d{4}/';

preg_match_all($pattern, $input, $matches);
print_r($matches);
=> Array
(
    [0] => Array
        (
            [0] => 03-3001-1256
            [1] => 03-3015-3222
        )

)

preg_replace:パターンに合致するものを入れ替える

$input = 'Call us at 03-3001-1256 or 03-3015-3222';
$pattern = '/\d{2}-\d{4}-\d{4}/'; //正規表現

$input = preg_replace($pattern, '**-****-****', $input);
echo $input . PHP_EOL;
=> Call us at **-****-**** or **-****-****

ceil:数値を切り上げ、floor:数値を切り捨て、round:四捨五入

$n = 5.6283;

echo ceil($n) . PHP_EOL;
=> 6

echo floor($n) . PHP_EOL;
=> 5

echo round($n) . PHP_EOL;
=> 6

echo round($n, 2) . PHP_EOL; //小数点以下が2桁になるように四捨五入
=> 5.63

max:最大値を選択、min:最小値を選択

echo max(3, 9, 4) . PHP_EOL;
=> 9

echo min(3, 9, 4) . PHP_EOL;
=> 3

参考

ドットインストール

最後に

本投稿が初学者の復習の一助となればと幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel6 改行をビューで表示する

目的

  • PHPのエスケープシーケンスを用いた改行をビューで表示する方法をまとめる

実施環境

  • ハードウェア環境
項目 情報
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 バージョン 6.X commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う
MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする

前提条件

  • 実施環境に近い開発環境が用意できていること。
  • ローカルサーバを起動する事ができるLaravel6のアプリケーションが存在していること。

前提情報

  • PHPのエスケープシーケンスを用いて改行を含んだ文字列をビューで改行して表示したい。
  • ブラウザでは下記のように表示してほしい。

    A
    <br>
    B
    <br>
    C
    

概要

  1. ルーティング情報の記載
  2. コントローラファイルの作成と記載
  3. ビューファイルの作成と記載
  4. 確認

詳細

  1. ルーティング情報の記載

    1. Laravelアプリ名ディレクトリで下記コマンドを実行してルーティングファイルを開く。

      $ vi routes/web.php
      
    2. 下記のルーティング情報を追記する。

      Laravelアプリ名ディレクトリ/routes/web.php
      Route::get('/index', 'TestController@index')->name('index');
      
  2. コントローラファイルの作成と記載

    1. Laravelアプリ名ディレクトリで下記コマンドを実行してコントローラファイルを作成する。

      $ php artisan make:controller TestController
      
    2. Laravelアプリ名ディレクトリで下記コマンドを実行してコントローラファイルを開く。

      $ vi app/Http/Controllers/TestController.php
      
    3. 下記のアクションをコントローラファイルに記載する。

      Laravelアプリ名ディレクトリ/app/Http/Controllers/TestController.php
      public function index()
      {
          /* シングルクオートで文字列を囲むとエスケープシーケンスが文字列扱いされるので注意 */
          $str = "A\nB\nC";
          return view('tests.index', ['str' => $str]);
      }
      
    4. 記載後のコントローラファイルの全体の内容を下記に記載する。

      Laravelアプリ名ディレクトリ/app/Http/Controllers/TestController.php
      <?php
      
      namespace App\Http\Controllers;
      
      use Illuminate\Http\Request;
      
      class TestController extends Controller
      {
          // 下記を追記する
          public function index()
          {
              /* シングルクオートで文字列を囲むとエスケープシーケンスが文字列扱いされるので注意 */
              $str = "A\nB\nC";
              return view('tests.index', ['str' => $str]);
          }
          // 上記までを追記する
      }
      
    5. ビューファイルの作成と記載

    6. Laravelアプリ名ディレクトリで下記コマンドを実行してビューファイルを格納するディレクトリを作成する。

      $ mkdir -p resources/views/tests
      
    7. Laravelアプリ名ディレクトリで下記コマンドを実行してビューファイルを作成して開く。

      $ vi resources/views/tests/index.blade.php
      
    8. 下記の内容を記載する。

      Laravelアプリ名ディレクトリ/resources/views/tests/index.blade.php
      <p>{!! nl2br(e($str)) !!}</p>
      
    9. 確認

    10. Laravelアプリ名ディレクトリで下記コマンドを実行してローカルサーバを起動する。

      $ php artisan serve
      
    11. 下記にアクセスする。

    12. 下記のようにABCがそれぞれ改行されて表示されることを確認する。

      127_0_0_1_8000_index.png

検証

  1. 変数に入った文字列をビューファイルで表示する際、本来は{{ }}でくくって表示するが今回は{!! !!}でくくっている。試しにビューファイルの記載を{{ }}にして$strだけを表示してみる。

    1. 下記のようにビューファイルのソースを修正した。

      Laravelアプリ名ディレクトリ/resources/views/tests/index.blade.php
      <p>{{$str}}</p>
      
    2. 下記のように改行がなされずに表示されてしまう。

      127_0_0_1_8000_index.png

{!! nl2br(e($str)) !!}の簡単な解説

  1. e($str)の説明
    • 変数$strに格納された文字列の中の「& (アンパサンド)」「" (ダブルクォート)」「' (シングルクォート)」「< (小なり)」「> (だいなり)」を別の文字に変換している。
    • もし仮に$strにXSS攻撃を意図としたリンクなどが含まれていたときに悪意のあるリンクタグを表示されないようにエスケープする。
  2. nl2br()の説明
    • PHPのエスケープシーケンス(\nなど)からhtmlのタグ(<br>など)を作成する関数である。
    • これは変数$strに格納されている\nをhtmlの<br>に置き換えてくれている。(正確には\nの直前に<br>を追記してくれている。)
  3. {!! !!}の説明
    • 通常の{{ }}はXSS攻撃を予防するために特殊文字を勝手にエスケープしてしまう。
    • これは関数nl2br()て作成した<br>タグの例外ではなくエスケープされてしまう。
      • https://readouble.com/laravel/6.x/ja/blade.html「エスケープしないデータの表示 デフォルトでブレードの{{ }}文はXSS攻撃を防ぐために、PHPのhtmlspecialchars関数を自動的に通されます。しかしデータをエスケープしたくない場合は、以下の構文を使ってください。」
  4. まとめると「{!! !!}を使用しないとnl2br()で作成した<br>がエスケープされてしまう。しかし{!! !!}はXSS攻撃される可能性がある。それを防ぐためにnl2br()にわたす変数$strには特殊文字が入っていたら困る。nl2br()にわたす前にXSS攻撃と思しき特殊文字はエスケープして渡す」という感じ。

おまけ

  1. PHPのhtmlspecialchars関数について

    1. {{ }}を用いたビューファイルの表示はPHPのhtmlspecialchars関数を通したものであるらしい。
    2. PHPのhtmlspecialchars関数が何をしているのかを気になったので調べてみる。下記にPHPドキュメントのリンクを記載する。
    3. 当該関数を通すと下記の特殊文字列が変換される。

      PHP__htmlspecialchars_-_Manual.png

    4. なので{{ }}を通して表示する文字列は上記の変換が行われた上で表示が行われる。

    5. htmlspecialchars関数を迂回して表示したいときは{!! !!}を使用する。

    6. Laravelで意図的にhtmlspecialchars関数で特殊文字列を変換したいときはヘルパ関数e()を使用する。

    7. 脆弱性の観点からみて今回のような特殊ケースを覗いて{!! !!}は多用しないほうが良いと思う。

    8. 特殊ケースで{!! !!}を使用するとしてもLaravelならヘルパ関数e()を併用するなど攻撃に対する対策が必要であると考える。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Laravel] 画像アップロード機能

簡単なCRUD機能を作成した際に画像アップロード機能を作成しましたのでまとめました。

ビューファイルに反映

create.blade.php
@section('content')
<div class="container" style="margin-top:150px;">
  <div class="row">
      <div class="col-12">
        <div class="card mt-3">
          <div class="card-body pt-0">
            @include('error_card_list')
            <div class="card-text">
              <form method="POST" enctype="multipart/form-data" action="{{ route('tweets.store') }}">
                @include('tweets.form')
                <button type="submit" class="btn blue-gradient btn-block">投稿する</button>
              </form>
            </div>
          </div>
        </div>
      </div>
  </div>
</div>
@endsection
form.blade.php
@csrf
<div class="md-form">
  <label>タイトル</label>
  <input type="text" name="title" class="form-control" required value="{{ $tweet->title ??  old('title') }}">
</div>
<div class="form-group">
  <label></label>
  <textarea name="content" required class="form-control" rows="16" placeholder="本文">{{ $tweet->content ??   old('content') }}</textarea>
</div>
<div class="form-group">
<input type="file" name="tweet_img"  type="file" value="{{ old('tweet_img')}}" >
</div>
<div class="md-form">
  <label>住所</label>
  <input type="text" name="address" class="form-control" required value="{{ $tweet->address ??   old('address') }}">
</div>

① "enctype" => "multipart/form-data"
二つ以上のファイルを同時にリクエストに格納するための方式。画像アップロードのフォームには必須。

② csrf
クロスサイトスクリプティングというWebアプリケーションの脆弱性の略称で、上記のinputタグはこの脆弱性からWebサービスを守るためのトークン情報です。POST送信を行う際は、必須となります。

③ old関数
入力した内容が保持された状態で登録画面が表示されるようになり、ユーザーはエラーになった箇所だけを修正すれば良くなります。

以下が画像アップロードに関する記載になります。

nameは各自好きな名前に設定して下さい。

create.blade.php
<form method="POST" enctype="multipart/form-data" action="{{ route('tweets.store') }}">
@include('tweets.form')
<button type="submit" class="btn blue-gradient btn-block">投稿する</button>
</form>
form.blade.php
<div class="form-group">
<input type="file" name="tweet_img"  type="file" value="{{ old('tweet_img')}}" >
</div>

モデル作成

Tweet.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Tweet extends Model
{
    //不正なリクエストによってtweetsテーブルが予期せぬ内容に更新されることを防ぐ
    protected $fillable = [
        'title',
        'content',
        'address',
        'tweet_img' => 'image|file'
    ];

    //もしuserメソッドがBelongsToクラスではなく、整数や文字列などの別の型を返そうとした場合、その時点でTypeErrorという例外が発生して処理が終了
    public function user(): BelongsTo
    {
         //$thisはTweetクラスのインスタンス自身を示す
        return $this->belongsTo('App\User');
    }
}

画像アップ用コントローラー設定

TweetController.php
    public function store(TweetRequest $request, Tweet $tweet)
    {
        if ($file = $request->tweet_img) {
            $fileName = time() . $file->getClientOriginalName();
            $target_path = public_path('uploads/');
            $file->move($target_path, $fileName);
        } else {
            $fileName = "";
        }
        $tweet->fill($request->all()); 
        $tweet->user_id = $request->user()->id;
        $tweet->tweet_img = $fileName;
        $tweet->save();
        return redirect('/');
    }

コントローラーがややこしいので詳細を説明いたします。

if ($file = $request->profile_img) {
            $fileName = time() . $file->getClientOriginalName();
            $target_path = public_path('uploads/');
            $file->move($target_path, $fileName);
        } else {
            $fileName = "";
        }

この部分では、 $fileにformからくる画像の情報が入っています。
画像が場合は、$fileNameを空文字にしています。

getClientOriginalName()
拡張子を含め、アップロードしたファイルのファイル名を取得することができます。
time()
タイムスタンプを取得します。
public_path()
publicディレクトリの完全パスを返します。ここでは、publicディレクトリ内にuploadsディレクトリを作成しています。
$file->move($target_path, $fileName)
画像をpublic/uploads/に、$fileNameという名前で挿入しています。

$tweet->fill($request->all()); 
        $tweet->user_id = $request->user()->id;
        $tweet->tweet_img = $fileName;
        $tweet->save();
        return redirect('/');

$tweet->fill($request->all());
リクエストのallメソッドを使用することでPOSTリクエストのパラメータをtokenを配列型式で表示できます。

[
    "_token" => "CdU7HghsXIOi14n7UnwCeOALRPGiVkMegZmK6RDc",
    "title" => "画像とは",
    "content" => "画像はアップロードできます。",
]

そして、Tweetモデルのfillメソッドにこの配列を渡すと、Tweetモデルのfillableプロパティ内に指定しておいたプロパティ(ここではtitleとcontent、address、tweet_img)のみが、$tweetの各プロパティに代入されます。

fillableプロパティを定義したことで、クライアントからのリクエストのパラメーター値をそのまま取り込んで更新しても良いプロパティは、titleとcontent、address、tweet_imgのみと制限されるようになりました。

不正なリクエストによってtweetsテーブルが予期せぬ内容に更新されることを防ぐようになりました。

注目するべきは、$tweet->tweet_img = $fileName;です。
データベースには、画像の名前しか保存していません。

画像を表示

画面に画像を表示できるようにするためにlaravelの公開用publicフォルダにシンボリックリンクを貼ります。

php artisan storage:link;

最後にブラウザへ出力しましょう。

index.php
div class="container" style="margin-top:50px;">
  @foreach($tweets as $tweet) 
  <div class="card-body">
      <img  src="/uploads/{{$tweet->tweet_img}}"class="img-fluid" alt="Responsive image">
      </div>
  @endforeach

</div>

今までの作業は、データベースには画像の名前だけを保存して、画像本体はpublicディレクトリ内のuploadsの中に保存したことになります。
srcの部分は人によって変わります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【業務未経験・独学】自社開発企業様から内定をもらうまでのお話

筆者のプロフィール

プログラミング歴三年弱
独学

どのくらい応募したか

エージェントの経由での応募も含めるとだいたい70−80社ほど。そのうち書類通過は15社くらい。
内定は3社いただきました。(1社は自社開発ではないです。)
選考途中のものは全てお断りしたのでもしかしたらもう1−2社くらい内定いただけかもしれないです。
就活期間 2020年10月初旬〜2020年11月中旬の1ヶ月ちょい

概要

社内で管理しているエクセルファイルとかを勝手にVBAで自動化するうちにプログラミングが楽しくなり、WEB系エンジニアにジョブチェンジ

具体的な学習方法

基本ほぼ全てアウトプットをベースに学習しました(最近はインプットもするように心がけています。)
なので最初に必ずやりたいことがあってそれを実現する方法を調べるという手順になります。

※途中から学習方法というよりは私がプログラミングができるようになるまでの過程になってます。なんか初学者の方のヒントになればとは思います。

★具体例
エクセルで毎回毎回同じフィルターかけるのめんどくさいからボタンを何個か設置してよく使うフィルターはボタン押したら発動するようにしたいわ
と思ったとします。
学習の初期の初期段階を想定すると分からないことというのは以下の通りだと思います。(基本的なエクセルの使い方はわかっている想定です。)

1.ボタンってどうやって設置すんの?
2.プログラムってどこに書くの?
3.そもそもプログラミング分からん

こんな感じかと思います。
ということでそもそもプログラムする前に解決すべき問題がプログラムをどこに書くのか、そしてボタンの設置方法ということが分かります。
なのでまずそれを調べます。

実際私がこのあとにとった行動はとりあえずマクロの記録をしてそれをボタンを押したら呼べるようにするということをしました。(マクロの記録とは記録中にマウスやキーボードで操作した手順を記憶して実行させることができる機能です。もちろんマクロの記録の仕方も最初は分からないので調べます。)

ここまででとりあえずボタンを設置してプログラムを走らせるところまでは分かりました。

次は記録したマクロを編集する方法を調べます。そうすれば自ずとどこにプログラミングを書けばいいかも分かります。
編集の仕方を調べたらちょっといじってみます。
例えば"田中"という名前でフィルターをするマクロを記録したとしたらこんな感じのコードが出力されていたとします。

    Selection.AutoFilter
    ActiveSheet.Range("$A$1:$B$5").AutoFilter Field:=1, Criteria1:="田中"

そうするとあーこれ"田中"の部分を自分の好きな文字に変えたらいいんじゃね?
となると思います。
かなりざっくりですが最初はそんな感じのことをひたすら繰り返してました。
とりあえず近い動きのマクロの記録して実際やりたい動きにするにはどこの数字や文字をいじれば良さそうかなーと考えて適当に触りまくります。
この時点ではもう細かいことは全て無視です。デバックの仕方もしらないのでひたすらコードを編集したら保存してボタンを押して実行、エラーがでたらまた編集そんな感じです。

一見効率が悪いように思えるかもしれませんが自分がやりたいことを最短で実現できるため、自分の書いたプログラムが動くことの楽しさを最短で味わうことができ挫折の確率は下がるのではないかと思います。

そんなこんなで動いたソースコードをひたすらコピペしまくるだけで一通り自分のやりたいことが実現できるスーパーコピペプログラマーになりましたとさ
ただそんなことばかり繰り返しているものだから半年以上は関数を一切使わずにVBAをぶん回していました記憶があります。(関数の存在は知っていたのですがイマイチ必要な理由が分からない+戻り値と返り値が理解できないので使えない)
そんな感じで半年以上続けているとコードを改修する機会も多くなり、スーパーコピペプログラマーとして名を馳せていた私はある日同じ処理が10箇所くらい存在していることに気がつきました。(もっと早く気付け)

その瞬間、関数の必要性が分かったんです。そして同時に今まで戻り値、返り値が理解出来なかったのが不思議なくらい分かったんです。
それに衝撃を受け私はしばらくリファクタリングにハマりました。どんどんコードが短くなり、保守性が高くなっていく感覚、リファクタリングが最高に楽しくなりました。

そうして一年くらいの時を経て私はついに【関数】を会得しました。
それからWEBアプリケーションの世界に進んでいくのでした。

WEBアプリケーションになってもやることは同じです。作りたいものを決めそれを作るために分からないことを調べる。少しずつそれをやってみる。最初は意味も分からずコピペしまくる。気にしない。動くことを最優先。それを繰り返していくとふと、今までコピペしていた内容が分かる瞬間がきます。
それが成長の時ではないでしょうか。

現在のスキル

そんなこんなでプログラミングを始めてから3年弱が過ぎもっとつよつよなプラグラマーになりたいと強く思い転職活動を始めました。
活動期間は冒頭に書いてます。

開発に使用した言語、技術
HTML/CSS(scss,bootstrap)/PHP/Python/Ruby(Ruby on Rails)/JavaScript(Vue.js,JQuery)/VBA/DB(MS SQL,PostgreSQL,MySQL)/AWS(EC2,S3,Route53)/さくらVPS/centOS7/Nginx/Apache/Ajax/docker/git

もちろんひとつひとつのスキルは大したことはないですが上記のような技術を組み合わせて一応WEBアプリケーションはイチから作りたいものは作れるようなレベルにはなりました。

作ったもの

・売上、在庫、経費管理アプリ
・ホームページ(PHPでフルスクラッチ)

ポートフォリオは?

残念ながら現在も社内で稼働していて色々パスワード等ベタ書きしてるところもあり、ソースは公開しておらず、書類選考時にはYoutubeのURLを貼ってなんとなくWEBアプリケーション全体の動きが分かるようにはしてあります。

就活の感想

面接官がエンジニアじゃなくて技術の知識がない人事だといまいち今まで身につけたスキルが評価されずいわゆる面接中のコミュニケーションが上手いかどうかで判断されがちで辛いことがありました。
面接する方が技術者だと話が弾むこともあって楽しい傾向にあります。

これからプログラミング始める方へ

小さなものでいいのでまず自分の作りたいものから作ってみてください。
特にExcelのVBAとスプレッドシートのGASは環境構築もいらないですし現在の業務で使ってる可能性が非常に高いのでおすすめです。
自分の作りたいものができた時初めてプログラミングって楽しい。そう感じると思います。
給料が良さそうだからとかフリーランスで自由に働きたいとかリモートワークがいいとかおそらくそういった動機でプログラミングで始められる方はほとんど挫折すると思います。
プログラミングは目的ではなく金を稼ぐ為の手段という人もいますがもちろんそういった側面があることも否めませんがもっと単純に、楽しいからやる。
そういった人がもっと社会全体で増えて来るともっと面白い未来が見えてくると思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む