20190301のPHPに関する記事は10件です。

複数の配列で2回以上出現する値を抽出する方法

array_intersectではすべての配列の共通項を出せるが、いずれかの配列の共通項を出したいときに迷ったのでメモ。
もっと良い方法あったら教えてください。

array_intersect_any.php
<?php
$a = ['hoge', 'fuga'];
$b = ['hoge', 'fuga', 'piyo'];
$c = ['hoge', 'fuga', 'piyo', 'hogehoge'];

/**
 * すべての配列をマージして出現回数が2回以上の値だけを抽出する
 * 連想配列には対応していない
 * 一つの配列に同じ値が2つあっても共通項として抽出される
 * 
 * @access
 * @return array
 */
function array_intersect_any()
{
    $list = call_user_func_array('array_merge', array_filter(func_get_args(), 'is_array'));
    $count = array_count_values($list);

    return array_unique(array_filter($list, function ($l) use ($count) {
        return $count[$l] > 1;
    }));
}

var_dump(array_intersect_any($a, $b, $c));
/*
array(3) {
  [0]=>
  string(4) "hoge"
  [1]=>
  string(4) "fuga"
  [4]=>
  string(4) "piyo"
}
*/

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

Laravel5基本機能Tips&ブロックチェーン

概要

目的:MVCのWebアプリケーション開発用のオープンソースであるLaravelについて基本機能を調査して記録した。今後、マイニング機器を使用して得られた採掘結果の欲しい情報をAPIなどからバックエンドで取得し見やすいUIにまとめグラフ化する予定である。

開発環境

-PHP5
-MySQL
-laravel5
- ローカル
- mac osx
- (XAMPP)
- Vscode
- 未定:リモートレンタルサーバー(AWS)、Docker
ーNanoppol API

主な参照記事:Laravel5 入門 インストールからMVCの基本機能をさっと眺める
[リンク](https://blog.hrendoh.com/getting-start-and-overview-of-laravel5/)

1 インストール&ローカル環境構築手順(Windows、Mac)
2 ルーティング
3コントローラー
4 ビュー
 4.1 基本的なビューの呼び出し方
 4.2 Bladeテンプレート
 4.3 Asset
5データベース操作
 5.1 接続設定
 5.2 モデル (ORM)
 5.3 マイグレーション
 5.4 モデルの利用
6 テスト
 6.1 データベースを利用するテスト
 6.2 テストデータベースのマイグレーション
7 標準機能について
 7.1Authについて
 7.2 使用可能なライブラリについて
 7.3 JavaScriptフレームワークについて(Vue.jsなど)

8  その他
 8.1 よく使うコマンドや実装について
         

1 インストール&ローカル環境構築手順(Windows、Mac)

   Laravel プロジェクトの作成

  Laravelインストール手順は、上記の手順を参照

$ composer create-project laravel/laravel --prefer-dist
<project name>

  
$ php artisan serve
Laravel development server started on http://localhost:8000/

artisanコマンドは、 Artisan CLI Usage を参照。artisan listで使用可能なコマンドは右のコマンドで確認できる。

$ php artisan list

2ルーティング

  ルーティングは app/Http/routes.php に記述する

// app/Http/routes.php

<?php
Route::get('/', 'WelcomeController@index');

   上記は、プロジェクトの作成後のデフォルト、’/’を
   WelcomeControllerの indexメソッドにマッピングしている

3コントローラー

コントローラーは、app/Http/Controllersに
App\Http\Controllers\Controllerを継承するクラスを置く
artisanコマンドでもコントローラーを生成可能
$ php artisan make:controller ArticleController
生成されるコントローラーはRestfullなリソースアクセスを提供する
RESTful Resource Controllers

4 ビュー

基本的なビューの呼び出し方
概要は、The BasicsのViews を参照
ビューのファイルは、resources/viewsに置く
ビューへ渡すデータは、view関数の第二引数に渡す
return view('greeting', ['name' => 'James']);
ビュー側は以下のように、渡されたマップのキーで値を参照できる

// resources/views/greeting.php
<html>
<body>
<h1>Hello, <?php echo $name; ?></h1>
</body>
</html>

resources/viewsのサブディレクトリに配置したビューの呼び出しは、以下のようにドットで連結して呼び出す(‘/’でも呼び出せる)

return view('article.create');

Asset

Laravel5 では、CSS、JavascriptをビルドするGulp タスク Laravel Elixir が標準で提供されている
プロジェクト直下のgulpfile.jsを見てみると、resources/assets/less/app.lessをビルドするタスクがはじめから設定されている

    // gulpfile.js
var elixir = require('laravel-elixir');

elixir(function(mix) {
mix.less('app.less');
});

npm実行環境とgulpをインストールして、プロジェクト直下にて以下のコマンドを実行する

$ npm install

開発中はgulp watchしておけば、lessの修正が自動で反映される

$ gulp watch

5 データベース操作

Basic Database Usage の Configuration によると対応データベースは、
MySQL, Postgres, SQLite, SQL Server と豊富
参照URL:laravel データベースの接続、マイグレーションによる

テーブル作成
https://qiita.com/ryo2132/items/a1c8119b00799d3aed00
LaravelでMAMPのMySQLに接続する
https://qiita.com/kei4eva4/items/480448b83df25774fc74

接続設定

データベースへの接続設定は、config/database.phpに記述する
Laravelのルートディレクトリ.envがあり、環境ごとの設定はこちらに記述
Environmentの設定については、LaravelはDotEnv PHPを利用する
MySQLを使用し Read/Write接続を分けない場合は、config/database.phpではなく.envに接続情報を記述する
デフォルトは以下の.env.exampleがインストール時に.envにコピーされる
(homesteadは、MySQLが.env.exampleの内容に合わせてセットアップ済み)

// .env

APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomString

DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

参考: Laravel 5.0 – Environment Detection & Environment Variables
モデル (ORM)

Laravelには、Eloquent ORMというActiveRecord実装がある
モデル生成の artisan コマンドが用意されている

$ php artisan make:model Article

app直下に以下のBlog.phpが生成される

// app/Blog.php

 `<?php

  namespace App;

 use Illuminate\Database\Eloquent\Model;

  class Article extends Model
 {
  //
  }

$tableプロパティに明示的にテーブル名を指定していないので、
このArticleクラスの場合は、articlesテーブルにアクセスする

マイグレーション

上記のArticleモデルを保存するarticlesテーブルを追加する
マイグレーションを作成する場合、以下のように

 artisan mke:migration コマンドを実行する
 $ php artisan make:migration create_articles_table
 Created Migration: 2015_06_09_164737_create_articles_table

マイグレーションファイルはdatabase/migrationsに作成される
(モデル作成時、artisan make:modelコマンドにオプション-mを付けると、モデルと同時にマイグレーションも生成される)
マイグレーションの書き方はWriting Migrationを参照
オートインクリメントのレコードIDと、文字列のtitleとtextをフィールドに持つarticlesテーブルを作成するマイグレーションは以下のようになる

  database/migrations/2015_06_09_164737_create_articles_table

 <?php
 use Illuminate\Database\Schema\Blueprint;
 use Illuminate\Database\Migrations\Migration;

 class CreateArticlesTable extends Migration
  {
   /**
    * Run the migrations.
    *
    * @return void
    */
       public function up()
     { 
         Schema::create('articles',                  
         function($table)
         {
         $table->increments('id');
         $table->string('title');
         $table->text('text');
         $table->timestamps();});
                                }
     /**
     * Reverse the migrations.
     *
     * @return void
     */
        public function down()
     {
        Schema::drop('articles');
                               }
                                }

timestampsは、インスタンスのdateTime型のupdated_atおよびcreated_at列マイグレーションはmigrateコマンドで適用
$ php artisan migrate 
Illuminate/Database/Eloquent/Model – Laravel API
モデルの利用
コントローラーでモデルを利用するには、インポートする
モデル操作は、Modelクラスのファサードおよびインスタンスメソッドで行う
Illuminate/Database/Eloquent/Model – Laravel API

RESTFullコントローラーの実装例

// app/Http/Controllers/ArticleController" highlight="7, 15, 21
<?php
  namespace App\Http\Controllers;
  use Illuminate\Http\Request;
  use App\Article;
  use App\Http\Requests;
  use App\Http\Controllers\Controller;
  class ArticleController extends Controller
   {
   public function index()
   {
     $articles = Article::all();
     return view('article.index', ['articles' => $articles];  }
      public function destroy($id)
     {
    $article = Article::find($id);
    $article->delete(); }}

6 テスト

データベースを利用するテスト
Laravel5では、テスト時にデータベースを切り替える仕組みを標準で用意していない
必要な環境変数はphpunit.xmlに記述する
データベースだけ切り替られれば良いのでDB_DATABASEのみ追加する

// phpunit.xml

テストデータベースのマイグレーション
マイグレーションは、DatabaseMigrationsトレイトを利用して、テストごとにMigrationを実行する

  //tests/ArticleTest
  <?php
  use Illuminate\Foundation\Testing\WithoutMiddleware;
  use Illuminate\Foundation\Testing\DatabaseMigrations;
  use Illuminate\Foundation\Testing\DatabaseTransactions;

    class ArticleTest extends TestCase
       {
           use DatabaseMigrations;
                                    }

7 標準機能について

7.1Authについて
Laravel5.2からmake:authでViewが生成できるようになった
参照:Laravelの標準Authentication(Auth)の動きを調べてみる
   
7.2 使用可能なライブラリについて

Laravelと合わせて使いたいライブラリ
・Pusher
     PusherはPHPでwebsocket(双方向データ通信)を行うためのライブラリ 
    参照URL:PusherはPHPでwebsocket(双方向データ通信)を行う
・Carbon
  PHPで時間を扱うDateTimeのラッパーライブラリ。

   参照URL:PHPで日付時刻処理を書くならCarbonを使うべき
参照URL:Laravelと合わせて使いたいライブラリ5選

7.3 JavaScriptフレームワークについて(Vue.jsなど)
Laravelとフロントエンド

Laravelでは、5.3から、Vue.jsが標準のJavaScriptフレームワークになっているさらに、5.4では、フロントエンドのビルドツールが、gulpベースのElixirから、WebpackベースのMixに変わった。Laravelをインストールすれば、Web APIはLaravelで作って、SPA(Single Page Application)をVue.jsで組む、といったことが簡単にできるようになっている

8.1 よく使うコマンドや実装について

参照URL:
https://walking-succession-falls.com/laravel%E3%81%AE%E5%9F%BA%E6%9C%AC%E6%A9%9F%E8%83%BD%E3%80%81%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E3%81%97%E3%81%9F%E5%B0%8F%E6%8A%80%E3%81%BE%E3%81%A8%E3%82%81/

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

TwilioとLaravel(PHP)を使って大量のSMSを送信する方法

原本

あなたが多数のユーザを持っていて、あなたがSMSを通してそれらを同時に更新するか、または通知する必要がある時があります。 たぶんあなたは会員制サイトや個人的なブログを運営しています。 どのような場合でも、このチュートリアルはあなたのWebアプリを使って大量のSMSを送信するための効率的で簡単な方法を提供します。

環境/対象

  • ターミナル(コマンドライン)
  • Composerインストール済み
  • PHPに精通している
  • Laravel(5+)に精通している
  • 既存のLaravelプロジェクトがある
  • Twilioアカウントを保持している

インストールとTwilio Laravel SDKの設定

最初にやるべきことはTwilio Laravel SDKをインストールすることです。TwilioLaravel SDKは、私たちの一括SMSアプリを起動するために必要な機能を提供します。 そのためにコマンドラインを使用します。 コマンドラインで次のように入力します:

$ composer require twilio/sdk

SDKがインストールされたので、Twilioアカウントを認識するように設定する必要があります。
.envファイルを開き、次のコードを貼り付けます。 必ず変数をTwilioの認証情報に置き換えてください。 TWILIO_FROMはあなたのTwilio番号です。

TWILIO_SID=ACXXXXXXXXXXXXXXXXXXX
TWILIO_TOKEN=XXXXXXXXXXXXXXXXXXXXX
TWILIO_FROM=+81XXXXXXXXXX

BulkSMS ControllerのViewとCodeを設定する

BulkSMSアプリには専用のControllerが必要です。Laravelのartisanコマンドを使用してControllerを作成します。
以下コマンドを貼り付けてControllerを作成します。

$ php artisan make:controller BulkSmsController

Controllerを開き、上部にTwilioクラスをincludeします。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Twilio\Rest\Client;
use Validator;

次に、bulksms.blade.phpという名前のビューファイルを作成して、BulkSMSアプリケーションに必要なフィールドを作成するためのHTMLフォームを作成します。

$ touch resources/views/bulksms.blade.php

新しく作成されたresources/views/bulksms.blade.phpファイルを開き、以下のコードを貼り付けます:

<html>
      <body>
         <form action='' method='post'>
              @csrf
                      @if($errors->any())
              <ul>
             @foreach($errors->all() as $error)
            <li> {{ $error }} </li>
             @endforeach
        @endif

        @if( session( 'success' ) )
             {{ session( 'success' ) }}
        @endif

             <label>Phone numbers (seperate with a comma [,])</label>
             <input type='text' name='numbers' />

            <label>Message</label>
            <textarea name='message'></textarea>

            <button type='submit'>Send!</button>
      </form>
    </body>
</html>

routesフォルダにあるweb.phpを開き、一番下に次のコードを貼り付けます。

<?php

Route::view('/bulksms', 'bulksms');
Route::post('/bulksms', 'BulkSmsController@sendSms');

それでは、HTMLフォームを検証してテキストメッセージを送信するための関数を作成します。app/Http/ControllersフォルダーにあるBulkSmsController.phpファイルを開き、最後の中括弧の前に次のコードを入力します。

<?php

        public function sendSms( Request $request )
    {
       // Your Account SID and Auth Token from twilio.com/console
       $sid    = env( 'TWILIO_SID' );
       $token  = env( 'TWILIO_TOKEN' );
       $client = new Client( $sid, $token );

       $validator = Validator::make($request->all(), [
           'numbers' => 'required',
           'message' => 'required'
       ]);

       if ( $validator->passes() ) {

           $numbers_in_arrays = explode( ',' , $request->input( 'numbers' ) );

           $message = $request->input( 'message' );
           $count = 0;

           foreach( $numbers_in_arrays as $number )
           {
               $count++;

               $client->messages->create(
                   $number,
                   [
                       'from' => env( 'TWILIO_FROM' ),
                       'body' => $message,
                   ]
               );
           }

           return back()->with( 'success', $count . " messages sent!" );

       } else {
           return back()->withErrors( $validator );
       }
   }

テスト

アプリをテストするには、プロジェクトディレクトリでコンソールを開き、次のコマンドを入力します。

$ php artisan serve

お好みのブラウザを使用してhttp://localhost:8000/bulksmsにアクセスし、フォームに記入して送信します。

Conclusion

これで、一括SMS送信アプリを設定したので、SMS機能の拡張がどれほど簡単かを確認できます。
これはあなたの電話番号をあなた自身のデータベースに保存させるという利点をあなたに与えます。

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

else-ifを三項演算子(?:)やnull合体演算子(??)に置き換えてみた

概要

PHP5.3以降で使用可能な三項演算子?:if-else構文の 完全互換だと思いこんで else-ifのネストに置き換えて使ってみたら 想定外の挙動 で少しハマったので反省も踏まえ共有してみた。

状況

画面上の押されたボタンによってデータベースに対する処理を分ける場面です。
formタグ自体は1つで「登録」「更新」「削除」「キャンセル」のsubmitボタン自体にname属性を持たせ、どのボタンが押されたかを判別しています(valueの中身は気にしない方向)

まず最初に書いたコード

db_ctrl.php
if (isset($_POST['regist'])) {
    $action= "regist";
} else if (isset($_POST['update'])) {
    $action= "update";
} else if (isset($_POST['delete'])) {
    $action= "delete";
} else if (isset($_POST['cancel'])) {
    $action= "cancel";
}

動作は問題なし。
でもなんだか冗長というか、我ながら同じ単語何回書くんだと 1人ツッコミ が入る

で、まずは上記を「if-elseの短縮構文」の つもり(思い込み) で三項演算子?:に置き換えてみました

(PHP5.3以降)db_ctrl.php
$action=
isset($_POST['regist'])? "regist" :
isset($_POST['update'])? "update" :
isset($_POST['delete'])? "delete" : "cancel";

最初のコードと比べればだいぶスッキリした。

尤も、この構文だと最後がelse-ifではなくelse(或いはswitch文のdefault:)のようになってしまうので そもそも置き換えられてない んですけども。

とりあえずテスト。
今回期待する結果は「登録」ボタン押下後で$action= "regist";
結果は・・・

南無った
$action = "delete";

ちーん :skull:
なんでやねん!

調べたところ、こういうことだそうで…
(PHP公式マニュアルから引用)

ダメだこいつ?:早くなんとかしないと…

代替案としてnull合体演算子(??)を使用

できれば 「中身が'regist'だったら"regist"を入れる」 なんて単語のリピートも1回の記述で済ませたいし
今回のケースは条件isset()if-elseネストだから、この三項演算子の下に説明のあるnull合体演算子ってのがいい感じで使えるんジャマイカ?

というわけで、早速さっきのPHPマニュアルで覚えたてのnull合体演算子を使ってみました

(PHP7以降)db_ctrl.php
$action =
$_POST['regist']??
$_POST['update']??
$_POST['delete']??
$_POST['cancel']?? "";

ただ、これだと$actionの中身が$_POSTの中身そのままになるので、<input type="submit" name="action" value="登録">ってHTML書いてると思いっきり送信ボタンの日本語ラベルがそのまま値($action = "登録")になるのがネック :cat:

やっぱり基本的にはsubmitボタンにname属性は持たせず<input type="hidden" name="action" value="regist">とセットにするのがいいのかな

最終的にforeachに落ち着いた

結局のところ以下のコードに落ち着きました…

db_ctrl.php
$actions = ['regist', 'update', 'delete', 'cancel'];
foreach ($actions as $action) {
    if (isset($_POST[$action])) break;
}

消化不良な部分

今回の三項演算子?:のこの想定外の挙動、どうやら他の言語の三項演算子ではちゃんと期待通りの結果になる模様 :scream_cat:

なんでPHPだけ違う結果になるのか、 PHPマニュアル自体が「わかりにくい挙動」に要注意 と警鐘を鳴らす仕様を敢えて採用する理由はなんなんだと軽く調べてみたら 「間違って実装しちゃったけど今更修正できないから」 なんて言う人も…ホンマかいなそれ :fearful:
そんなだから海外の言語ランキングで「主軸のない補助輪」とか揶揄されるんじゃ…

結論、まとめ。

PHP(5.3以降)の三項演算子(?:)はネストしてはいけない。 修正しろy
PHP7以降のnull合体演算子(??)のネストは可能ではある。

未熟エンジニアなりの所感(おまけ)
こんなところまで読んで頂きありがとうございます m(_ _)m
PHPにおける三項演算子(?:)の使い所としては「HTML部分にPHPを埋め込む際、foreachのように一行にしたい」といった用途向きでしょうか
ネストは避けるとしても、あまり多用しても逆に可読性が悪くなるのかもしれません
null合体演算子(??)もPHP7以降なので、環境次第でエラー修正する羽目に陥る確率が高い気が…
そもそも他言語からPHP に流れてくる も学ぼうとされる方 は少数派かもですが、同じ仕様だと思って 「なんでやねん!:anger: と躓かれる方がいるかもしれないと思い投稿しました。
いつも他の方の情報を頂いてばかりの自分の投稿がどなたかのお役に立てば幸いです:pray:


あとがき

マークダウン記法の学習と技術情報共有や質問投稿に慣れていく目的も兼ねての初投稿です
MarkdownやQiitaでの投稿自体が初めてなので、主に以下のページを参考にさせていただきました

Markdown記法 チートシート

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

PHP: callable型の引数に、privateメソッドを渡すことができたり、できなかったりする

PHPは、組み込み関数のcallable型引数にはprivateメソッドを渡せるのに、ユーザ定義関数のcallable型引数にはprivateメソッドが渡せない。

例えば、アカウントというクラスがあって、

final class Account
{
    /**
     * @var bool
     */
    private $isAdmin;

    public function __construct(bool $isAdmin)
    {
        $this->isAdmin = $isAdmin;
    }

    public function isAdmin(): bool
    {
        return $this->isAdmin;
    }
}

それをリスト化するアカウントコレクションというクラスがあって、

final class AccountCollection
{
    /**
     * @var Account[]
     */
    private $accounts;

    public function __construct(Account ...$accounts)
    {
        $this->accounts = $accounts;
    }
}

そいつに、管理者アカウントだけ抽出するメソッドをarray_filterをつかって生やしたコードがあるとする:

final class AccountCollection
{
    // ...

    public function getAdminAccounts(): array
    {
        return array_filter($this->accounts, [$this, 'isAdminAccount']);
    }

    private function isAdminAccount(Account $account): bool
    {
        return $account->isAdmin();
    }
}

array_filterの第二引数はcallable型であり、それにAccountCollectionクラスのプライベートメソッドisAdminAccountを渡している。

このとき、次のコードは問題なく動く:

$allAccounts = new AccountCollection(
    new Account(true),
    new Account(false),
    new Account(true),
    new Account(false)
);
$adminAccounts = $allAccounts->getAdminAccounts();
var_dump(count($adminAccounts)); //=> int(2)

このコードで、callable型の引数にprivateメソッドが渡せることが確認できた。

次に、array_filterとそっくりなユーザ定義関数を作る。

function my_array_filter(array $elements, callable $predicate): array
{
    $newElements = [];
    foreach ($elements as $element) {
        if ($predicate($element)) {
            $newElements[] = $element;
        }
    }
    return $newElements;
}

そして、AccountCollectionクラスをarray_filterではなくmy_array_filterを使うように変更する。

final class AccountCollection
{
    /**
     * @var Account[]
     */
    private $accounts;

    public function __construct(Account ...$accounts)
    {
        $this->accounts = $accounts;
    }

    public function getAdminAccounts(): array
    {
        return my_array_filter($this->accounts, [$this, 'isAdminAccount']);
    }

    private function isAdminAccount(Account $account): bool
    {
        return $account->isAdmin();
    }
}

このあとに、次のコードを実行するとFatalエラーになる:

$allAccounts = new AccountCollection(
    new Account(true),
    new Account(false),
    new Account(true),
    new Account(false)
);
$adminAccounts = $allAccounts->getAdminAccounts(); 
//=> PHP Fatal error:  Uncaught TypeError: Argument 2 passed to my_array_filter() must be callable, array given

my_array_filterの第二引数はcallableを受け付けるようになっているが、callableが渡ってきてないよというエラーだ。

my_array_filterにとってAccountCollection::isAdminAccountはprivateで不可視なため発生するエラーなのはわかるが、array_filterでは発生しなかったので言語仕様の一貫性に謎が残る

ちなみに、このFatalエラーはClosure::fromCallableでラップすれば回避できるので、やりたいことができないわけではない。

    public function getAdminAccounts(): array
    {
        return my_array_filter(
            $this->accounts,
            Closure::fromCallable([$this, 'isAdminAccount'])
        );
    }

あと、もちろん、my_array_filterAccountCollectionのメンバーにする方法もある。

final class AccountCollection
{
    /**
     * @var Account[]
     */
    private $accounts;

    public function __construct(Account ...$accounts)
    {
        $this->accounts = $accounts;
    }

    public function getAdminAccounts(): array
    {
        return self::my_array_filter($this->accounts, [$this, 'isAdminAccount']);
    }

    private static function my_array_filter(array $elements, callable $predicate): array
    {
        $newElements = [];
        foreach ($elements as $element) {
            if ($predicate($element)) {
                $newElements[] = $element;
            }
        }
        return $newElements;
    }

    private function isAdminAccount(Account $account): bool
    {
        return $account->isAdmin();
    }
}

まとめ

  • 組み込み関数のcallable型引数にはprivateメソッドが渡せる。
  • ユーザ定義関数のcallable型引数にはprivateメソッドが渡せない($thisのコンテキストが異なるとき)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[MailhogとLaravel]Expected response code 220 but got code "500"のエラー解決方法

Expected response code 220 but got code "500"

上記のようなエラーが発生する場合の解決方法

環境

  • docker
  • laravel
  • mailhog
  • 開発環境(ENV=development)

問題点:確実に環境変数

  • 500エラーが帰ってきているのでメールサーバにはアクセスできている
  • 環境変数自体がおかしいか、読み込めていない

実際に通る.env

MAIL_USERNAMEMAIL_PASSWORDMAIL_ENCRYPTIONはNULLを設定しておきましょう。

MAIL_DRIVER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

解決方法

上記の環境変数さえ読み込めれば、実行はできる。
もしこれを設定してできない場合は環境変数がうまく読み込めていない。
以下の手順で確認してください。

0.環境変数が読み込めているか確認するコマンド

\Config::get('mail')

上記コマンドを実行して、意図した環境変数になっているか確認。
image.png

なっていない場合は以下の手順を試すべし

1.キャッシュクリア

bash
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

2.環境変数ロード

bash
. .env
# もしくは環境変数を環境ごとに分けてる場合は読み込みたいファイルを指定
. .env.development

3.環境変数直接設定する

bash
MAIL_DRIVER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

4.最終手段、mail.phpを書き換える

環境変数を実際に読み込んでいるのはconfig/mail.phpというファイルだ。
ここの環境変数を読み込む部分を削除し、直接値を書き込んでしまえば良い。

bash
'encryption' => env('MAIL_ENCRYPTION', 'ssl'),

# こうなっているのをこうじゃ!

'encryption' => env(''),
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【laravel5.7】メール�送信周りを日本語化

laravelでのメール周り?の英文を日本語に直すメモ

やりたいこと

Email VerificationやPassword Resetの時のメール文や送信しました!などの英語部分を日本語にする。

環境

MacOS 10.14.3
VisualStudio
laravel 5.7

メール内容

viewsで日本語かしても下のようにまだ英語が残っているので、その部分を日本語化します。
スクリーンショット 2019-02-28 14.34.44.png

Notificationのレイアウトを編集する

terminal
php artisan vendor:publish

と打つと、下記のようなリストが表示されます。
スクリーンショット 2019-02-28 14.23.05.png
laravel-notificationsが書いてある番号を入力してEnter。
(上のリストだと"11")

環境によって番号は変わります。

resources/views/vendor/notifications/email.blade.phpが生成されるので編集します。

resources/views/vendor/notifications/email.blade.php
@component('mail::message')
{{-- Greeting --}}
@if (! empty($greeting))
# {{ $greeting }}
@else
@if ($level === 'error')
# @lang('Whoops!')
@else
+# こんにちは
@endif
@endif

{{-- Intro Lines --}}
@foreach ($introLines as $line)
{{ $line }}

@endforeach

{{-- Action Button --}}
@isset($actionText)
<?php
    switch ($level) {
        case 'success':
        case 'error':
            $color = $level;
            break;
        default:
            $color = 'primary';
    }
?>
@component('mail::button', ['url' => $actionUrl, 'color' => $color])
{{ $actionText }}
@endcomponent
@endisset

{{-- Outro Lines --}}
@foreach ($outroLines as $line)
{{ $line }}

@endforeach

{{-- Salutation --}}
@if (! empty($salutation))
{{ $salutation }}
@else
+{{ config('app.name') }}より
@endif

{{-- Subcopy --}}
@isset($actionText)
@slot('subcopy')
+もし、「{{ $actionText }}ボタン」がうまく機能しない場合、以下のURLをコピー&ペーストして直接ブラウザからアクセスしてください。
+ [{{ $actionUrl }}]({{ $actionUrl }})
@endslot
@endisset
@endcomponent

動作確認

再度、メールを送ってみて下のように日本語になっていたらOK。
スクリーンショット 2019-02-28 14.28.47.png

Password Resetの文

下の画像の緑の部分を日本語にします。
スクリーンショット 2019-02-28 12.56.33.png

config/app.php

変更箇所

  • timezone:タイムゾーン
  • locale:言語
  • fallback_local:該当言語が見つからない場合の言語
config/app.php
'timezone' => 'Asia/Tokyo',
'locale' => 'ja',
'fallback_locale' => 'ja',

app.phpのデフォルト言語で指定してある"en"は、
resources/lang/enから表示をしています。

その中に、下記4つのファイルがあるかと思います。

  • auth.php
  • pagination.php
  • password.php
  • validation.php

これを日本語に編集します。
1. enファイルをコピペして"ja"にリネーム。
2. ここから日本語訳をコピーして日本語に編集

今回はパスワードリセット部分を日本語化にしたいので、password.phpだけ編集します。

resources/lang/ja/password.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Password Reset Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are the default lines which match reasons
    | that are given by the password broker for a password update attempt
    | has failed, such as for an invalid token or invalid new password.
    |
    */

    'password' => 'パスワードは6文字以上にして、確認用入力欄と一致させてください。',
    'reset' => 'パスワードは再設定されました!',
    'sent' => 'パスワード再設定用のURLをメールで送りました。',
    'token' => 'パスワード再設定用のトークンが不正です。',
    'user' => "メールアドレスに一致するユーザーが存在しません。",

];

動作確認

http://127.0.0.1:8000
ログイン画面のPassword Resetリンクにとんで、メールアドレスをいれて送信してみてください。
スクリーンショット 2019-03-01 10.48.09.png

日本語になっていればOK。

おまけ

その他3つのファイルは日本語にするとこんな感じになります。

resources/lang/ja/auth.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are used during authentication for various
    | messages that we need to display to the user. You are free to modify
    | these language lines according to your application's requirements.
    |
    */

    'failed' => '認証情報が記録と一致しません。',
    'throttle' => 'ログイン試行が規定回数を超えました。:seconds秒後に再開できます。',

];

resources/lang/ja/pagination.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Pagination Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are used by the paginator library to build
    | the simple pagination links. You are free to change them to anything
    | you want to customize your views to better match your application.
    |
    */

    'previous' => '&laquo; 前へ',
    'next' => '次へ &raquo;',

];

resources/lang/ja/validation.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Validation Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines contain the default error messages used by
    | the validator class. Some of these rules have multiple versions such
    | as the size rules. Feel free to tweak each of these messages here.
    |
    */

    'accepted'             => ':attributeを承認してください。',
    'active_url'           => ':attributeには有効なURLを指定してください。',
    'after'                => ':attributeには:date以降の日付を指定してください。',
    'after_or_equal'       => ':attributeには:dateかそれ以降の日付を指定してください。',
    'alpha'                => ':attributeには英字のみからなる文字列を指定してください。',
    'alpha_dash'           => ':attributeには英数字・ハイフン・アンダースコアのみからなる文字列を指定してください。',
    'alpha_num'            => ':attributeには英数字のみからなる文字列を指定してください。',
    'array'                => ':attributeには配列を指定してください。',
    'before'               => ':attributeには:date以前の日付を指定してください。',
    'before_or_equal'      => ':attributeには:dateかそれ以前の日付を指定してください。',
    'between'              => [
        'numeric' => ':attributeには:min〜:maxまでの数値を指定してください。',
        'file'    => ':attributeには:min〜:max KBのファイルを指定してください。',
        'string'  => ':attributeには:min〜:max文字の文字列を指定してください。',
        'array'   => ':attributeには:min〜:max個の要素を持つ配列を指定してください。',
    ],
    'boolean'              => ':attributeには真偽値を指定してください。',
    'confirmed'            => ':attributeが確認用の値と一致しません。',
    'date'                 => ':attributeには正しい形式の日付を指定してください。',
    'date_format'          => '":format"という形式の日付を指定してください。',
    'different'            => ':attributeには:otherとは異なる値を指定してください。',
    'digits'               => ':attributeには:digits桁の数値を指定してください。',
    'digits_between'       => ':attributeには:min〜:max桁の数値を指定してください。',
    'dimensions'           => ':attributeの画像サイズが不正です。',
    'distinct'             => '指定された:attributeは既に存在しています。',
    'email'                => ':attributeには正しい形式のメールアドレスを指定してください。',
    'exists'               => '指定された:attributeは存在しません。',
    'file'                 => ':attributeにはファイルを指定してください。',
    'filled'               => ':attributeには空でない値を指定してください。',
    'gt' => [
        'numeric' => ':attributeには、:valueより大きな値を指定してください。',
        'file'    => ':attributeには、:value kBより大きなファイルを指定してください。',
        'string'  => ':attributeは、:value文字より長く指定してください。',
        'array'   => ':attributeには、:value個より多くのアイテムを指定してください。',
    ],
    'gte' => [
        'numeric' => ':attributeには、:value以上の値を指定してください。',
        'file'    => ':attributeには、:value kB以上のファイルを指定してください。',
        'string'  => ':attributeは、:value文字以上で指定してください。',
        'array'   => ':attributeには、:value個以上のアイテムを指定してください。',
    ],
    'image'                => ':attributeには画像ファイルを指定してください。',
    'in'                   => '選択された:attributeは正しくありません。',
    'in_array'             => ':attributeには:otherの値を指定してください。',
    'integer'              => ':attributeは整数で指定してください。',
    'ip'                   => ':attributeには、有効なIPアドレスを指定してください。',
    'ipv4'                 => ':attributeには、有効なIPv4アドレスを指定してください。',
    'ipv6'                 => ':attributeには、有効なIPv6アドレスを指定してください。',
    'json'                 => ':attributeには、有効なJSON文字列を指定してください。',
    'lt' => [
        'numeric' => ':attributeには、:valueより小さな値を指定してください。',
        'file'    => ':attributeには、:value kBより小さなファイルを指定してください。',
        'string'  => ':attributeは、:value文字より短く指定してください。',
        'array'   => ':attributeには、:value個より少ないアイテムを指定してください。',
    ],
    'lte' => [
        'numeric' => ':attributeには、:value以下の値を指定してください。',
        'file'    => ':attributeには、:value kB以下のファイルを指定してください。',
        'string'  => ':attributeは、:value文字以下で指定してください。',
        'array'   => ':attributeには、:value個以下のアイテムを指定してください。',
    ],
    'max' => [
        'numeric' => ':attributeには、:max以下の数字を指定してください。',
        'file'    => ':attributeには、:max kB以下のファイルを指定してください。',
        'string'  => ':attributeは、:max文字以下で指定してください。',
        'array'   => ':attributeは:max個以下指定してください。',
    ],
    'mimes'                => ':attributeには:valuesタイプのファイルを指定してください。',
    'mimetypes'            => ':attributeには:valuesタイプのファイルを指定してください。',
    'min' => [
        'numeric' => ':attributeには、:min以上の数字を指定してください。',
        'file'    => ':attributeには、:min kB以上のファイルを指定してください。',
        'string'  => ':attributeは、:min文字以上で指定してください。',
        'array'   => ':attributeは:min個以上指定してください。',
    ],
    'not_in'               => '選択された:attributeは正しくありません。',
    'not_regex'            => ':attributeの形式が正しくありません。',
    'numeric'              => ':attributeには、数字を指定してください。',
    'present'              => ':attributeが存在していません。',
    'regex'                => ':attributeに正しい形式を指定してください。',
    'required'             => ':attributeは必ず指定してください。',
    'required_if'          => ':otherが:valueの場合、:attributeも指定してください。',
    'required_unless'      => ':otherが:valuesでない場合、:attributeを指定してください。',
    'required_with'        => ':valuesを指定する場合は、:attributeも指定してください。',
    'required_with_all'    => ':valuesを指定する場合は、:attributeも指定してください。',
    'required_without'     => ':valuesを指定しない場合は、:attributeを指定してください。',
    'required_without_all' => ':valuesのどれも指定しない場合は、:attributeを指定してください。',
    'same'                 => ':attributeと:otherには同じ値を指定してください。',
    'size' => [
        'numeric' => ':attributeは:sizeを指定してください。',
        'file'    => ':attributeのファイルは、:sizeキロバイトでなくてはなりません。',
        'string'  => ':attributeは:size文字で指定してください。',
        'array'   => ':attributeは:size個指定してください。',
    ],
    'starts_with' => ':attributeは:valuesのいずれかで始めてください。',
    'string'               => ':attributeは文字列を指定してください。',
    'timezone'             => ':attributeには、有効なゾーンを指定してください。',
    'unique'               => ':attributeの値は既に存在しています。',
    'uploaded'             => ':attributeのアップロードに失敗しました。',
    'url'                  => ':attributeに正しい形式を指定してください。',
    'uuid'                 => ':attributeに有効なUUIDを指定してください。',

    /*
    |--------------------------------------------------------------------------
    | Custom Validation Language Lines
    |--------------------------------------------------------------------------
    |
    | Here you may specify custom validation messages for attributes using the
    | convention "attribute.rule" to name the lines. This makes it quick to
    | specify a specific custom language line for a given attribute rule.
    |
    */

    'custom' => [
        'attribute-name' => [
            'rule-name' => 'custom-message',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Custom Validation Attributes
    |--------------------------------------------------------------------------
    |
    | The following language lines are used to swap our attribute placeholder
    | with something more reader friendly such as "E-Mail Address" instead
    | of "email". This simply helps us make our message more expressive.
    |
    */

    'attributes' => [],

];

ただ、これだけだと下記のようにバリデーションがinputタグのname値が表示されます。

emailは必ず指定してください。
passwordは必ず指定してください。

ここも日本語化したい場合は、
validation.phpの"attributes"で指定します。

resources/lang/ja/validation.php
'attributes' => [
    'email' => 'メールアドレス',
    'password' => 'パスワード',
    'password_confirmation' => 'パスワード(確認)',
    'name' => 'ユーザー名'
],

とりあえず以上です。

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

Tリーグ 琉球アスティーダの試合結果をCSVで出力する

2018年10月、日本で卓球のプロリーグが開幕しました。

公式サイトでは、試合結果のほか、個人成績も集計・ランキング化されていて、なかなか面白いです。サービスエースはあの選手が一番得点が多いんだなあ、ですとか。

公式サイトではAPIなど使っていないようで、試合のスコアや選手のランキングはJSON取得して、その値をページに書き込む、といった処理はしていません。
これだと個人でデータを集計したり加工したりできず、不便です。不便ですよね?
そこで、HTMLソースの値をCSVとして出力することにしました。

使用したのはPHP 5.6
(JavaScriptより面倒だから。面倒だと勉強になりそうだから)。
今回、ファイル出力する対象は、贔屓チームの試合結果としました。
https://tleague.jp/match/?season=2018

↓用意したスクリプト。

<?php

const SEASON_MONTH_SET = [
    ['2018', '201810'],
    ['2018', '201811'],
    ['2018', '201812'],
    ['2018', '201901'],
    ['2018', '201902'],
    ['2018', '201903'],
];
const MATCH_URL = 'https://tleague.jp/match/';
const TEAM = '琉球';
const CSV = '/tmp/output.csv';
const CSV_TITLE = ['date', 'team', 'team score', 'opponent score', 'opponent', 'home/away', 'arena'];

function csv_records($resource, $url) {
    $csv_records = [];

    curl_setopt($resource, CURLOPT_HEADER, false);
    // http://php.net/manual/en/function.curl-exec.php
    // if the CURLOPT_RETURNTRANSFER option is set, it will return the result on success, FALSE on failure. 
    curl_setopt($resource, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($resource, CURLOPT_BINARYTRANSFER, true);
    curl_setopt($resource, CURLOPT_URL, $url);
    curl_setopt($resource, CURLOPT_SSLVERSION,1); 
    $html = curl_exec($resource);
    $dom = new DOMDocument();

    // 取得htmlが適切でないらしく下記warningが出力される。
    // PHP Warning:  DOMDocument::loadHTML(): htmlParseEntityRef: no name in Entity
    // 出したくないなら
    // libxml_use_internal_errors(true);
    $dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));

    $xpath = new DOMXPath($dom);
    $match_men = $xpath->query('.//li[@class="match-men"]');

    foreach ($match_men as $match) {
        $c_home = $xpath->query('.//div[@class="cell-home"] /a', $match);
        $c_away = $xpath->query('.//div[@class="cell-away"] /a', $match);

        $home = $c_home->item(0)->textContent;
        $away = $c_away->item(0)->textContent;
        if (!in_array(TEAM, [$home, $away])) {
            continue;
        }

        $c_score = $xpath->query('.//div[@class="cell-result"] /div /strong', $match);
        $score = $c_score->item(0)->textContent;
        $scores = explode(' ', $score); // [home score, '-'(constant string value), away score]

        $c_date = $xpath->query('.//div[@class="cell-date"]', $match);
        $date = $c_date->item(0)->textContent;

        $home_game = TEAM === $home;

        $team           = $home_game ? $home      : $away;
        $opponent       = $home_game ? $away      : $home;
        $team_score     = $home_game ? $scores[0] : $scores[2];
        $opponent_score = $home_game ? $scores[2] : $score[0];
        $homeaway       = $home_game ? 'home'     : 'away'; 

        $c_arena = $xpath->query('.//div[@class="cell-arena"] /a', $match);
        $arena = $c_arena->item(0)->textContent;

        $csv_records[] = [$date, $team, $team_score, $opponent_score, $opponent, $homeaway, $arena];
    }
    return $csv_records;
}

////////////////////////////////
// main
////////////////////////////////
$resource = curl_init();
$csv_records = [CSV_TITLE];
$csv_file = fopen(CSV, 'w');
$season_month_set = SEASON_MONTH_SET;

foreach ($season_month_set as $season_month) {
    $season = $season_month[0];
    $month = $season_month[1];
    // example:    $url = 'https://tleague.jp/match/?season=2018&month=201902'
    $url = MATCH_URL . '?season=' . $season . '&month=' . $month;

    $monthly_records = csv_records($resource, $url);
    $csv_records = array_merge($csv_records, $monthly_records);
}
foreach ($csv_records as $record) {
    fputcsv($csv_file, $record);
}
curl_close($resource);
fclose($csv_file);

↓実行結果。

date,team,"team score","opponent score",opponent,home/away,arena
2018/10/26(金),琉球,2,3,岡山,away,名古屋武田テバ
(中略)
2019/02/22(金),琉球,0,4,TT彩たま,home,宜野湾宜野湾市

満足しました。

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

php-master-changes 2019-02-28

今日は配列の文字列変換の処理タイミングの修正、不要な m4 マクロの削除、不要コードの削除、extract() でクラッシュする場合がある問題の修正、あるHTTP アクセスするテストケースのスキップ可能化、AppVeyor で opcache 有効時の並列テスト無効化、imagecreatefromstring() の引数処理の ZPP 対応、OpenSSL 1.1.1b での挙動修正対応、mysqli の embedded サーバサポートコードの削除、DateInterval::createFromDateString() がエラーを吐かずに失敗する問題の修正、_DO_THROW() マクロ内で return するのをやめる修正があった!

2019-02-28

bwoebi: Delay array to string conversion notice until runtime

petk: Remove deprecated PHP_EXTENSION m4 macro

petk: Remove unused PHP_AC_BROKEN_SNPRINTF m4 macro

petk: Remove ZEND_FP_EXCEPT macro and HAVE_FP_EXCEPT

petk: Remove not needed PHP_PDO_PEAR_CHECK m4 macro

petk: Remove unused package2.xml file

bwoebi: Fix test (order of warning / notice changes due to delaying until runtime)

nikic: Fixed bug #77669

nikic: Mark ext/xmlreader/tests/bug70309.phpt as online test

nikic: Disable test parallelization on AppVeyor with opcache

nikic: Use zpp string argument in imagecreatefromstring()

weltling: Sync with behavior change in OpenSSL 1.1.1b

nikic: Remove mysqli embedded server support

cmb69: Remove dead code

weltling: Sync with 7be0e06b482e5bf14eaf4fe9a882d8b72d644038

derickr: Fixed bug #50020 (DateInterval:createDateFromString() silently fails)

nikic: Remove more leftovers of mysqli embedded server

nikic: Don't return inside _DO_THROW macro

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

【PHP】in_arrayについて 〜条件分岐編〜

この記事では、僕が自分自身で学んでいったことを、メモのようにとっていくものです。

そのため、他の人には全然役に立たなかったりする場合もあると思いますが、ご了承ください。

今回は、『in_array』を使用した条件分岐になります。

ちょっと初心者にはとっつきにくい部分があると思いますので、できるだけわかりやすく解説していきたいと思います。

目次

  • そもそも「in_array」とは?
  • どんなときに使うの?
  • 実際に「in_array」を使ってみよう!
  • 「in_array」の解説
  • まとめ

そもそも「in_array」とは?

そもそもこの「in_array」とは一体なんなのか、簡単に説明していきたいと思います。

こちらの「in_array」というのは、PHPに用意されている関数の一種です。

PHPには様々な関数が用意されています。

そういったものは、使用用途を知ることができれば、誰でも簡単に使用し、コードに組み込むことができます。

関数は難解ではあるけれど、小さな機能みたいなものなので、初心者にとっては非常にありがたいものだったりするわけです。

そして、今回の「in_array」もその非常にありがたい関数の一種なのです。

どんなときに使うの?

「in_array」は配列に指定された値が存在するか確認するための関数になっています。

例えば、文字列などがある配列に存在するかどうか調べたいとします。

今回は車のメーカーが書かれている配列の中から、自分が知っているメーカーがあるかどうか調べたい時。

それをきちんとコードに落とすのは、少々手間がかかります。

// 車のメーカーが記載されている配列
$CarManufacturer = [
  "トヨタ",
  "日産",
  "ホンダ",
  "マツダ",
  "スズキ",
  "三菱" ];

このように車のメーカーが記載されている配列があったとします。

$numcar = "レクサス";

自分が探したい車のメーカーを変数に代入します。
こうしてやっていき、「in_array」を使わずに、配列の中とすり合わせを行うとすると、このようになります。

$CarManufacturers = [
  "トヨタ",
  "日産",
  "ホンダ",
  "マツダ",
  "スズキ",
  "三菱" ];

$numcar = "レクサス";
switch ($numcar) {
  case $CarManufacturers[0]:
    echo "あなたが探していた車のメーカーは存在します。";
    break;

  case $CarManufacturers[1]:
    echo "あなたが探していた車のメーカーは存在します。";
    break;

  case $CarManufacturers[2]:
    echo "あなたが探していた車のメーカーは存在します。";
    break;

  case $CarManufacturers[3]:
    echo "あなたが探していた車のメーカーは存在します。";
    break;

  case $CarManufacturers[4]:
    echo "あなたが探していた車のメーカーは存在します。";
    break;

  case $CarManufacturers[5]:
    echo "あなたが探していた車のメーカーは存在します。";
    break;

  default:
    echo "あなたが探していた車のメーカーは見つかりませんでした。";
    break;

こう見てみると、本当に見にくいですね。

ただ、こういった条件分岐も、もっと綺麗に書くことができます。(笑)

そこは大目にみてください。

さて、とりあえずわかってもらえたと思うのが、いちいち条件分岐をしていくのは、非常に効率が悪いということです。

基本的にコーディングというものは、書く量が少なく、見やすいものが良いとされています。

少なくても、見にくければ、良いコードとは言えないと言われています!

また、たくさんコードを書くことで、ミスをしてしまうことがあると思います。
*人間なので。

実際に「in_array」を使ってみよう!

さて、ここからが本当の意味でのメモになりますが、実際に上で書いたものを、「in_array」で書いてみましょう!

$CarManufacturers = [
  "トヨタ",
  "日産",
  "ホンダ",
  "マツダ",
  "スズキ",
  "三菱" ];

$numcar = "レクサス";

ここまでは、通常の条件分岐と同じになります。

ここから先が大きく変わります!

if (in_array($numcar, $CarManufacturer)) {
  echo "あなたが探していた車のメーカーは存在します。";
} else {
  echo "あなたが探していた車のメーカーは見つかりませんでした。";
};

どうでしょう。

以前のコードがひどいこともありますが、ものすごく綺麗になりましたね。

また、コードが少ないからといって、見にくいわけでも無いので、非常に良いと思います。

全体のコードとしてはこのようになりました。

$CarManufacturers = [
  "トヨタ",
  "日産",
  "ホンダ",
  "マツダ",
  "スズキ",
  "三菱" ];

$numcar = "レクサス";

if (in_array($numcar, $CarManufacturer)) {
  echo "あなたが探していた車のメーカーは存在します。";
} else {
  echo "あなたが探していた車のメーカーは見つかりませんでした。";
};

「in_array」の解説

ここからは、実際の細かいところまでの解説を行なっていきたいと思います。

細かい解説とはいっても、バリバリコードを書いている方からしてみると、まだまだ大雑把なところもあると思いますが、お手柔らかにお願いします。
*コメント欄に書いていただけると、メッセージのやりとりができるので、そちらに書いていただけると助かります!

「in_array」の構造

「in_array」はどういう構造になっているのか、僕が最低限意識していることを書いていきたいと思います。

in_array(値1, 値2);

上のコードで説明していきたいと思います。

上のコードの「値1」と「値2」。

こちらの関係性を覚えておけば、とりあえずは使うことができると思います。

「in_array」の場合は、「値1」が「値2」に入っているかどうか、です!

今回の例では、「値1」や「値2」を変数としていましたが、定数でも、数字などのものでも大丈夫です。

ただし気をつけておきたいのは、配列の中身を調べるものなので、「値2」は配列になります!

まとめ

いかがだったでしょうか?

今回は「in_array」を取り上げて、メモがわりにしましたが、この「in_〇〇」という関数は他にもあるので、その都度、メモしていきたいとおもいます!

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