20220117のlaravelに関する記事は11件です。

composer require linecorp/line-bot-sdk導入時のエラー解決

概要 composer require linecorp/line-bot-sdkのエラー解決。いくつかネット記事を回ったものの、同じ解決法をとっている人がいなかったので。 環境は以下です。 Cloud9 PHP 7.3.30 Laravel Framework 6.20.44 エラー内容 $ composer require linecorp/line-bot-sdk Using version ^7.3 for linecorp/line-bot-sdk ./composer.json has been updated Running composer update linecorp/line-bot-sdk Loading composer repositories with package information Updating dependencies Your requirements could not be resolved to an installable set of packages. Problem 1 - Root composer.json requires linecorp/line-bot-sdk ^7.3 -> satisfiable by linecorp/line-bot-sdk[7.3.0]. - linecorp/line-bot-sdk 7.3.0 requires ext-curl * -> it is missing from your system. Install or enable PHP's curl extension. To enable extensions, verify that they are enabled in your .ini files: ///中略 You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode. Installation failed, reverting ./composer.json and ./composer.lock to their original content. 解決方法 1、拡張curl導入(やる必要なかった) エラーの内容から、拡張curlが無い、あるいは無効だからインストールに失敗したらしいと予想。 $ sudo apt-get install php-curl 拡張curlはエラー無く導入できたと思われた。再度導入を試みるも同様のエラー。 2、無効化されている可能性 導入と同時に有効化されるはずだが、php.iniで無効化されている可能性を考え、php.iniを開く。「extension=curl」で検索をかけるが見つからなかった。 以下コマンドで入ってるモジュールを調べたところ、そもそも拡張curlが入ってないらしい。どうやら1の段階で拡張curl導入に失敗していた。 $ php -m [PHP Modules] bcmath calendar Core ctype date ///後略 3、再度コマンドを変えて拡張curlを導入 $ sudo apt-get install php7.3-curl 違うコマンドを見つけたので拡張curlの導入を再度試みる。 4、line-bot-sdkを導入 $ composer require linecorp/line-bot-sdk 成功! そういえばエラーのとこにもバージョン指定してあったね。見通しが立つのは早かったけど、コマンドを見つけるまでに時間がかかった。 参考記事 大変お世話になりました。ありがとうございます。 参照日(2022/01/17) https://qiita.com/____easy/items/06406fc62bd7464ad651 https://qiita.com/mktro/items/d164bd4a88fc51f2a99d
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel編 第5章 ~Mvcモデルを使ってDBのデータを表示~

✧MVCモデル編(第3幕)✧ 今回は、MVCモデルを使って、データベースにかかれているものをweb上で表示する仕組みを学んでいきます。 はじめに 前回(第4章)作った、TestController.phpを使っていきます。 まず、TestController.php内に、modelsの中にあるtest.phpを使えるようにするために、以下のコードをTestController.php内に記入する。 use App\Models\Test; といった形で、処理を書く事ができる。 例として、、、route内に以下の文を書く Route::get('tests/test', 'TestController@index'); すると、tests/test内にあるTestController@indexが呼び出されるという訳である。 TestControllerに、飛ばした後は、Testcontroller内に、以下の文を記述する。 public function index(){ 表示したい内容(今回は↓にする) return view('tests.test'); } return view('tests.test');は、viewに飛ばすといった指示なので、(事前にresourse/viewsの中に、testsというフォルダを作って、その中にtest.blade.phpを作る事で)移動することが出来る。 viewフォルダの中にあるファイルは、.bladeを基本的にはつけるようにすること。 例えば、作ったtest.blade.phpの中に、testと入力すると、、、 こんな感じで、入力された文が、routeを伝って、表示される
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel編 ~Mvcモデルを使ってDBのデータを表示 その1~

✧MVCモデル編(第3幕)✧ 今回は、MVCモデルを使って、データベースにかかれているものをweb上で表示する仕組みを学んでいきます。 はじめに 前回(第4章)作った、TestController.phpを使っていきます。 まず、TestController.php内に、modelsの中にあるtest.phpを使えるようにするために、以下のコードをTestController.php内に記入する。 use App\Models\Test; といった形で、処理を書く。 この文を書くことにより、App\Models\TestをTestcontroller内で、使えるようになる。 Modelは、DBとの接続をするための物。 App\Models\Testは、DB内の、testの情報をもっている。 $values = Test::all(); dd($values); ddとは? phpでいう dieとvar_dumpを組み合わせた仕組み 変数の処理を止めて、中身を表示してくれる。 ↓tests/testの結果。 dd($values)の結果が返ってきている。 見てわかるように、DB内の、testに格納されているaaaが表示されているのが確認できる。 これにより、$valuesの中身に、DBの内容が入っているのが、確認できた。 後は、DBの中身がある$valuesを、viewファイルに移動したいので、 return view('tests.test', compact('values')); compactは、ファイルを送るための変数。 複数のファイルもまとめて送ることが出来て、とても便利。 文字の場合は、シングルコーテーションで囲うのを忘れずにすること。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel ~Mvcモデルを使ってDBのデータを表示 その1~

✧MVCモデル編(第3幕)✧ 今回は、MVCモデルを使って、データベースにかかれているものをweb上で表示する仕組みを学んでいきます。 はじめに 前回(第4章)作った、TestController.phpを使っていきます。 まず、TestController.php内に、modelsの中にあるtest.phpを使えるようにするために、以下のコードをTestController.php内に記入する。 use App\Models\Test; といった形で、処理を書く。 この文を書くことにより、App\Models\TestをTestcontroller内で、使えるようになる。 Modelは、DBとの接続をするための物。 App\Models\Testは、DB内の、testの情報をもっている。 $values = Test::all(); dd($values); ddとは? phpでいう dieとvar_dumpを組み合わせた仕組み 変数の処理を止めて、中身を表示してくれる。 ↓tests/testの結果。 dd($values)の結果が返ってきている。 見てわかるように、DB内の、testに格納されているaaaが表示されているのが確認できる。 これにより、$valuesの中身に、DBの内容が入っているのが、確認できた。 後は、DBの中身がある$valuesを、viewファイルに移動したいので、 return view('tests.test', compact('values')); compactは、ファイルを送るための変数。 複数のファイルもまとめて送ることが出来て、とても便利。 文字の場合は、シングルコーテーションで囲うのを忘れずにすること。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel編 第4章 ~Mvcモデル Viewsの仕組み編~

✧MVCモデル編(第2幕)✧ 前回の続き(前回をご覧になってない方は、第3章を読むことをお勧めします) 今回は、routeフォルダの中から、接続先を変える方法について学んでいきます。 Routeの書き方 Route::get('アクセス先', '飛ばした先のアクセス先'); といった形で、処理を書く事ができる。 例として、、、route内に以下の文を書く Route::get('tests/test', 'TestController@index'); すると、tests/test内にあるTestController@indexが呼び出されるという訳である。 TestControllerに、飛ばした後は、Testcontroller内に、以下の文を記述する。 public function index(){ 表示したい内容(今回は↓にする) return view('tests.test'); } return view('tests.test');は、viewに飛ばすといった指示なので、(事前にresourse/viewsの中に、testsというフォルダを作って、その中にtest.blade.phpを作る事で)移動することが出来る。 ワンポイントアドバイス ・viewフォルダの中にあるファイルは、.bladeを基本的にはつけるようにすること。 例えば、作ったtest.blade.phpの中に、testと入力すると、、、 こんな感じで、入力された文が、routeを伝って、表示される
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel ~Routeで、接続先を変える方法~

✧MVCモデル編(第2幕)✧ 前回の続き(前回をご覧になってない方は、第3章を読むことをお勧めします) 今回は、routeフォルダの中から、接続先を変える方法について学んでいきます。 Routeの書き方 Route::get('フォルダの場所', '飛ばした先のアクセス先'); といった形で、処理を書く事ができる。 例として、、、route内に以下の文を書く Route::get('tests/test', 'TestController@index'); すると、tests/test内にあるTestController@indexが呼び出されるという訳である。 TestControllerに、飛ばした後は、Testcontroller内に、以下の文を記述する。 public function index(){ 表示したい内容(今回は↓にする) return view('tests.test'); } return view('tests.test');は、viewに飛ばすといった指示なので、(事前にresourse/viewsの中に、testsというフォルダを作って、その中にtest.blade.phpを作る事で)移動することが出来る。 ワンポイントアドバイス ・viewフォルダの中にあるファイルは、.bladeを基本的にはつけるようにすること。 例えば、作ったtest.blade.phpの中に、testと入力すると、、、 こんな感じで、入力された文が、routeを伝って、表示される
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel ~Mvcモデル Viewsの仕組み~

✧MVCモデル編(第2幕)✧ 前回の続き(前回をご覧になってない方は、第3章を読むことをお勧めします) 今回は、routeフォルダの中から、接続先を変える方法について学んでいきます。 Routeの書き方 Route::get('アクセス先', '飛ばした先のアクセス先'); といった形で、処理を書く事ができる。 例として、、、route内に以下の文を書く Route::get('tests/test', 'TestController@index'); すると、tests/test内にあるTestController@indexが呼び出されるという訳である。 TestControllerに、飛ばした後は、Testcontroller内に、以下の文を記述する。 public function index(){ 表示したい内容(今回は↓にする) return view('tests.test'); } return view('tests.test');は、viewに飛ばすといった指示なので、(事前にresourse/viewsの中に、testsというフォルダを作って、その中にtest.blade.phpを作る事で)移動することが出来る。 ワンポイントアドバイス ・viewフォルダの中にあるファイルは、.bladeを基本的にはつけるようにすること。 例えば、作ったtest.blade.phpの中に、testと入力すると、、、 こんな感じで、入力された文が、routeを伝って、表示される
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelでLINE BOTを作成する

はじめに Laravelを使用してLINE BOTを作成します。 完全なコード LINE BOT完成イメージ 選択肢を選んでいって最終的に選択した内容をもとにニュースを表示させます。 1. リッチメニューをタップすると"pick a news type"と送信される 2. "pick news type"を検知し言語選択メッセージが送信される 3. 言語選択を選択すると国選択のメッセージが送信される 4. 国選択を選択するとカテゴリ選択のメッセージが送信される 5. 言語、国、カテゴリを基にNewsを検索し表示する シーケンス図 Laravelのインストール・環境構築 Laravel8を使用します。 バージョンはLINE BOT SDKがインストールできれば何でも◎ LINE BOT SDKの導入 GitHubのREADMEに従ってインストールします。 composer require linecorp/line-bot-sdk SDK リポジトリ SDKを使用するClassを作成する SDKを使用しLINE APIを叩くClassを作成します。 どこでもいいですが今回はServicesというディレクトリにしましょう。 (Facadeに登録しておくと便利になるかもしれませんね) app/Services/LineBotService.php LineBotService.php <?php namespace App\Services; use Illuminate\Http\Request; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; class LineBotService { /** * @var CurlHTTPClient */ protected $httpClient; /** * @var LINEBot */ protected $bot; public function __construct() { $this->httpClient = new CurlHTTPClient('<channel access token>'); $this->bot = new LINEBot($this->httpClient, ['channelSecret' => '<channel secret>']); } /** * Reply based on the message sent to LINE. * LINEに送信されたメッセージをもとに返信する * * @param Request * @return int * @throws \LINE\LINEBot\Exception\InvalidSignatureException */ public function eventHandler(Request $request) : int { return 200; } } 簡単にLine APIを叩くためコンストラクタ内でBotのクライアントのインスタンスを作成しています。 このインスタンスを使用し以下のようにAPIをCallでき、LINEにメッセージを送信できるようになります。 例 $response = $this->bot->replyText('<reply token>', 'hello!'); Serviceを呼び出すControllerの作成 先ほど作成したServiceを使用するためContollerを作成します。 php artisan make:controller Api/LineBotController Controllerのコンストラクタ内でServiceのインスタンスを作成します。 LINEアカウントにメッセージが送信されると Webhookでこちら側のAPIにリクエストが送信されreply()が実行されます。 reply()内ではとりあえず疎通確認のためリクエストの内容をログに書いているだけです。 LineBotController.php <?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Services\LineBotService; class LineBotController extends Controller { /** * @var LineBotService */ protected $line_bot_service; public function __construct() { $this->line_bot_service = new LineBotService(); } /** * When a message is sent to the official Line account, * The API is called by LINE WebHook and this method is called. * * Lineの公式アカウントにメッセージが送られたときに * LINE Web HookにてAPIがCallされこのメソッドが呼ばれる * * @param Request */ public function reply(Request $request) { // Requestが来たかどうか確認する $content = 'Request from LINE'; $param_str = json_encode($request->all()); $log_message = <<<__EOM__ $content $param_str __EOM__; \Log::debug($log_message); $status_code = $this->line_bot_service->eventHandler($request); return response('', $status_code, []); } } apiルートを定義する /api/line-bot/replyでリクエストを受け取り、LineBotControllerのreply()を実行させます。 Laravel8の記法になります。 routes/api.php <?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; +use App\Http\Controllers\Api\LineBotController; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- | | Here is where you can register API routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | is assigned the "api" middleware group. Enjoy building your API! | */ +Route::post('/line-bot/reply', [LineBotController::class, 'reply']); 一旦デプロイ HerokuにあげてLINE側からAPIをCallできるようします。 ※このときngrokの存在を知りませんでしたm(__)m LINEの設定 1.LINE Official Account Managerからアカウントを作成します。 2.作成したらそのアカウントページに行き右上の設定をクリックします。 サイドメニューのMessaging APIへ行き、 Channelを作成します。 3.作成すると以下の画面になるのでWebhook URLに先程api.phpに定義したpathを記載します。 4.次にサイドメニューの応答設定にて、以下画像のように設定します。 5.LINE DeveloperのConsoleに行き先程作成したチャネルを開きます。 6.Messaging APIの設定のWebhook設定からWebhook URLを先程と同様に設定、Webhookの利用にチェックを入れます。 7.同ページ最下部のチャネルアクセストークンを発行しておきます。 8.自分の作ったアカウントを友だち追加する 疎通・ログ確認 LINEのチャットルームに適当にメッセージを送信するとLaravelが以下のようなログを出力します。 LINEからのRequestの中身ですね。 これらのデータを使用すればLINEに返信を送ることが可能になります。 [2022-01-11 12:41:10] production.DEBUG: Request from LINE {"destination":"Uxxxxxxxxxxxxx","events":[{"type":"message","message":{"type":"text","id":"xxxxxxxxx","text":"ここにLINEに送信したメッセージ"},"timestamp":1641872469897,"source":{"type":"user","userId":"Uxxxxxxxxxxxxxxxxx"},"replyToken":"xxxxxxxxxxxxxxx","mode":"active"}]} 環境変数を定義 LINE Developer consoleからチャネルを開き 以下の値をコピーし.envに貼り付けます。 チャネル基本設定->チャネルシークレットをLINE_CHANNEL_SECRET Messaging API設定->チャネルアクセストークン(長期)をLINE_CHANNEL_SECRET .env + LINE_CHANNEL_ACCESS_TOKEN= + LINE_CHANNEL_SECRET= configに追加 config/app.php <?php return [ + 'line_channel_access_token' => env('LINE_CHANNEL_ACCESS_TOKEN'), + 'line_channel_secret' => env('LINE_CHANNEL_SECRET'), ]; 先程作成したServiceのBOTクライアントのインスタンス生成箇所を修正します。 LineBotService.php public function __construct() { - $this->httpClient = new CurlHTTPClient('<channel access token>'); - $this->bot = new LINEBot($this->httpClient, ['channelSecret' => '<channel secret>']); + $this->httpClient = new CurlHTTPClient(config('app.line_channel_access_token')); + $this->bot = new LINEBot($this->httpClient, ['channelSecret' => config('app.line_channel_secret')]); } DB/Model周り 回答を保存しておくテーブルを定義します。 <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateAnswersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('answers', function (Blueprint $table) { $table->id(); $table->string('line_user_id'); // LINEのユーザーID $table->integer('step'); // なんステップ目の回答か $table->string('answer')->nullable(); // 回答 $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('answers'); } } モデルも作成 php artisan make:model Answer app/Models/Answer.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Answer extends Model { use HasFactory; protected $fillable = [ 'line_user_id', 'step', 'answer', ]; /** * Database used by this model * * @var string */ protected $connection = 'sqlite'; // お好みで /** * Tables associated with the model * * @var string */ protected $table = 'answers'; } これで先程のLINEアカウントにメッセージを送信する準備が整いました! LINEに送信する前に署名を確認する 指定したLINEアカウントからのリクエストしか受けつないようにするため Signatureを使用してリクエスト元を判別します。 LineService.php <?php namespace App\Services; use Illuminate\Http\Request; use LINE\LINEBot; use LINE\LINEBot\HTTPClient\CurlHTTPClient; class LineBotService { ... /** * Reply based on the message sent to LINE. * LINEに送信されたメッセージをもとに返信する * * @param Request * @return int * @throws \LINE\LINEBot\Exception\InvalidSignatureException */ public function eventHandler(Request $request) : int { // 署名を検証しLINE以外からのリクエストを受け付けない。 $this->validateSignature($request); return 200; } /** * LINEの署名確認 * * @param Request * @return void * @throws HttpException */ public function validateSignature(Request $request) : void { // リクエストヘッダーについてくる実際の署名 $signature = $request->header('x-line-signature'); if ($signature === null) { abort(400); } // LINEチャネルシークレットとリクエストボディを基に署名を生成 $hash = hash_hmac('sha256', $request->getContent(), config('app.line_channel_secret'), true); $expect_signature = base64_encode($hash); // 実際の署名と生成した署名が同じであれば検証OK if (!hash_equals($expect_signature, $signature)) { abort(400); } } } リクエストを処理して返信する リクエストを処理する部分を記述します。 LineBotService.phpを以下のように編集します。 LineBotService.php /** * Reply based on the message sent to LINE. * LINEに送信されたメッセージをもとに返信する * * @param Request * @return int * @throws \LINE\LINEBot\Exception\InvalidSignatureException */ public function eventHandler(Request $request) : int { // 署名を検証しLINE以外からのリクエストを受け付けない。 $this->validateSignature($request); // リクエストをEventオブジェクトに変換する $events = $this->bot->parseEventRequest($request->getContent(), $request->header('x-line-signature')); foreach ($events as $event) { // Reply token無しでは返信できないため定義しておく $reply_token = $event->getReplyToken(); // 無効な操作があったときに送るメッセージ $message_builder = new TextMessageBuilder('Invalid operation. 無効な操作です。'); // アクションした人のLINEのユーザーID $line_user_id = $event->getUserId(); switch (true){ // テキストメッセージを受信した場合 case $event instanceof TextMessage: break; // 選択肢を選んだ場合 case $event instanceof PostbackEvent: break; } } // LINEに返信 $response = $this->bot->replyMessage($reply_token, $message_builder); // 送信に失敗したらログに吐いておく if (!$response->isSucceeded()) { \Log::error('Failed!' . $response->getHTTPStatus() . ' ' . $response->getRawBody()); } return $response->getHTTPStatus(); } これで何かしらのメッセージを送ったら"Invalid operation. 無効な操作です。"と 返信が帰ってくるようになります。 選択肢付きメッセージを送る 選択肢メッセージを送るため、Switch文に追記します。 リッチメニューを押すと'pick news type'と送信されるように LINE Official Account Managerから編集したので 'pick news type'というテキスト送信をトリガーに 選択肢メッセージを返信します。 LineBotService.php switch (true){ // テキストメッセージを受信した場合 case $event instanceof TextMessage: // "pick news type"と送信された場合 if ($event->getText() === 'pick news type') { // 国選択メッセージを定義 $message_builder = $this->buildStep0Msg(); } break; // 選択肢を選んだ場合 case $event instanceof PostbackEvent: break; } LineBotServiceクラスにメソッドを追加 LineBotService.php /** * Step0用のTemplateMessageBuilderを生成する * @param void * @return TemplateMessageBuilder */ public function buildStep0Msg() : TemplateMessageBuilder { return new TemplateMessageBuilder( "Select Language / 言語選択", // チャット一覧に表示される new ConfirmTemplateBuilder( "Select Language / 言語選択", // title [ new PostbackTemplateActionBuilder("Engish", "en"), // option new PostbackTemplateActionBuilder("French", "fr"), // option ] ) ); } ConfirmTemplateBuilderを使用することでこちらを 簡単に生成できます。 選択肢部分をPostbackTemplateActionBuilderとすることで 選択したときに同じエンドポイントにリクエストが送信され Switch文のcase $event instanceof PostbackEvent:に入ってきます。 選択肢の回答を保存し次のステップのメッセージを生成する 回答し次のステップに進んだことをDBに保存しておき 回答自体もDBに保存します。 LineBotService.php switch (true){ // テキストメッセージを受信した場合 case $event instanceof TextMessage: // "pick news type"と送信された場合 if ($event->getText() === 'pick news type') { // 今までの回答をリセット $this->answer_model->resetStep($line_user_id); // 国選択メッセージを定義 $message_builder = $this->buildStep0Msg(); // 次のステップに進んだことを示すフラグを立てておく $this->answer_model->storeNextStep($line_user_id, 0); } break; // 選択肢を選んだ場合 case $event instanceof PostbackEvent: // 回答を定義 $postback_answer = $event->getPostbackData(); // 未回答のレコードを取得 $current_answer = $this->answer_model->latest()->where('answer', '')->first(); switch ($current_answer->step) { case 0: // 言語選択時 selected language // 回答をDBに保存 $this->answer_model->storeAnswer($current_answer, $postback_answer); // 次のステップに進んだことを示すフラグを立てておく $this->answer_model->storeNextStep($line_user_id, 1); // 次のメッセージを生成する $message_builder = $this->buildStep1Msg(); break; default: break; } default: break; } 次に送信する選択肢メッセージを生成します。 LineBotServiceクラスにメソッドを追加します。 LineBotService.php /** * Return TemplateMessageBuilder for step1. * Step1用のTemplateMessageBuilderを生成する * @param void * @return TemplateMessageBuilder */ public function buildStep1Msg() : TemplateMessageBuilder { return new TemplateMessageBuilder( "Which country do you watch the news for?", // チャットルーム一覧に表示される new ButtonTemplateBuilder( "Which country do you watch the news for?", // メッセージのタイトル "Select A Country / 国選択", // メッセージの内容 "", [ new PostbackTemplateActionBuilder("United States", "us"), // 選択肢 new PostbackTemplateActionBuilder("Japan", "jp"), // 選択肢 new PostbackTemplateActionBuilder("Canada", "ca"), // 選択肢 ] ) ); } ButtonTemplateBuilderを使用することでこちらを 簡単に生成できます。 Modelのメソッド追加 app/Models/Answer.php /** * Reset step * * @param string * @return void **/ public function resetStep(string $line_user_id) : void { $this->where('line_user_id', $line_user_id)->delete(); } /** * Store record for next step * * @param int * @return void **/ public function storeNextStep(string $line_user_id, int $step) : void { $this->line_user_id = $line_user_id; $this->step = $step; $this->answer = ''; $this->save(); } /** * Store answer replied by LINE user. * * @param Answer * @param string * @return void **/ public function storeAnswer(Answer $answer, string $postback_answer) : void { $answer->answer = $postback_answer; $answer->save(); } 次のステップも同様 Swich文にcase1を追加します。 LineBotService.php switch ($current_answer->step) { case 0: // 言語選択時 selected language ... break; + case 1: // 国選択時 selected country + $this->answer_model->storeAnswer($current_answer, $postback_answer); + + $this->answer_model->storeNextStep($line_user_id, 2); + + $message_builder = $this->buildStep2Msg(); + break; default: break; } メッセージ生成メソッドも先程と同様です。 LineBotService.php /** * Return TemplateMessageBuilder for step2. * Step2用のTemplateMessageBuilderを生成する * @param void * @return TemplateMessageBuilder */ public function buildStep2Msg() : TemplateMessageBuilder { return new TemplateMessageBuilder( "Which category?", new ButtonTemplateBuilder( "Which category?", "Select A Category / カテゴリ選択", "", [ new PostbackTemplateActionBuilder("Business", "business"), new PostbackTemplateActionBuilder("General", "general"), new PostbackTemplateActionBuilder("Science", "science"), new PostbackTemplateActionBuilder("Tech", "technology"), ] ) ); } 最後に結果を送信する Switch文にcase2を追加します。 LineBotService.php switch ($current_answer->step) { case 0: // 言語選択時 selected language ... break; case 1: // 国選択時 selected country ... break; case 2: // カテゴリ選択時 selected category(end) $this->answer_model->storeAnswer($current_answer, $postback_answer); // Step 0 ~ 2までの回答を取得 $answers = $this->answer_model->where('line_user_id', $line_user_id)->get(); // それぞれ定義 $category = $answers->whereStrict('step', 2)->first()->answer; $language = $answers->whereStrict('step', 0)->first()->answer; $country = $answers->whereStrict('step', 1)->first()->answer; // ニュースを取得 $news = $this->newsapi_client->getSources($category, $language, $country); // 取得したニュースを基に結果メッセージを生成 $message_builder = $this->buildResultMsg($news->sources); break; default: # code... break; } 今までの回答を基にNews APIを叩いています。 News APIから取得したニュースデータをメッセージに埋め込んで送信します。 LineBotService.php /** * ニュース取得結果のTemplateMessageBuilderを生成する * @param array * @return TemplateMessageBuilder|TextMessageBuilder */ public function buildResultMsg(array $sources) : mixed { // Newsデータがない場合 if (empty($sources)) { return new TextMessageBuilder('No result / ニュースがありませんでした'); } else { $columns = []; // 5個までアイテムを生成する foreach ($sources as $num => $source) { if ($num > 4) { break; } // バックスラッシュ削除 // httpsにする必要がある $replacement = [ '\\' => '', 'http:' => 'https:' ]; // 置換 $url = str_replace( array_keys($replacement), array_values($replacement), $source->url ); // URL部分を定義(ボタン部分) $link = new UriTemplateActionBuilder('See This News', $url); // アスペクト比を適当に変えてそれぞれ違う画像にする $acp = $num * 200 === 0 ? 100 : $num * 200; // アイテムをColumnとして配列に入れておく $columns[] = new CarouselColumnTemplateBuilder( $source->name, // Title mb_strimwidth($source->description, 0, 59, "...", 'UTF-8'), // 60文字までOK "https://placeimg.com/640/$acp/tech", // ランダムな画像のURL [$link] // 先程のURL部分 ); } // カラムをカルーセルに組み込む $carousel = new CarouselTemplateBuilder($columns, 'square'); return new TemplateMessageBuilder("News results", $carousel); } CarouselTemplateBuilderを使用するとこちら を簡単に作成できます。 以上になります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ConoHa VPSで複数サイト(今回はlaravel )を管理する

ConoHaで複数サイトを管理する手順 初めに 既にVPSサーバーを持っているので他のサーバーを借りるとお金がかかるのでポート番号を解放して公開したい スクールでやったけど言われるがままだったので改めて学習。今回はLaravelのプロジェクトを公開したい。 全体的に以下記事を参考 https://qiita.com/ChairoHack/items/06a2e1357b646acb41c7 ポートを解放 ssh root@kazpp.com #ssh接続 cd /etc/httpd/conf vi httpd.conf #ポート番号の8081を今回対象にしたいので以下の内容を追加 Listen 8081 <VirtualHost *:8081> ServerName 118.27.14.189 DocumentRoot /home/kazuki/laravelpractice ErrorLog "logs/wordpress.com-error_log" CustomLog "logs/wordpress.com-access_log" common <Directory "/home/kazuki/laravelpractice"> Require all granted </Directory> </VirtualHost> # ポート8081を解放 firewall-cmd --zone=public --add-port=8081/tcp --permanent #️ リロード firewall-cmd --reload #ポートが解放されたか確認 firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: dhcpv6-client http ssh ports: 8080/tcp 8081/tcp ?8081が存在することを確認 protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: #プロジェクトを置くディレクトリを作成 mkdir /home/kazuki/laravelpractice #サイトが表示されるかテスト touch /home/kazuki/laravelpractice/test.php #念のため、一般ユーザーへ切り替え su kazuki #Apacheの再起動 systemctl restart httpd 参考:https://qiita.com/inakadegaebal/items/14b2884389712e89b4a6 composerのインストール # Composerのインストーラーをダウンロード [root@ ~]sudo wget https://getcomposer.org/installer -O composer-installer.php # Composerのインストール [root@ ~]php composer-installer.php --filename=composer --install-dir=/usr/local/bin # Composerのアップデート [root@ ~]composer self-update # Composerのバージョンの確認 [root@ ~]composer --version Composer version 2.2.4 2022-01-08 12:30:42 公開サーバにGitをダウンロード CentOSのサーバにGitを導入する時の備忘録。yum install git で入る Git は少し古いので、新しいバージョンを入れる方法を記載 依存関係があるライブラリ(curl、zlib、openssl、expat、libiconv あたり)を導入する sudo yum -y install gcc curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker autoconf yumからインストールする場合、インストール可能なGitのバーションを確認する。デフォルトのyumのデフォルトのレポジトリではバーションが古いのでiusレポジトリを一時的に使用する。 [root@ ~]vi /etc/yum.repos.d/ius.repo # [ius] # name = IUS for Enterprise Linux 7 - $basearch # baseurl = https://repo.ius.io/7/$basearch/ # enabled = 1 # repo_gpgcheck = 0 # gpgcheck = 1 # gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-IUS-7 # [ius-debuginfo] # name = IUS for Enterprise Linux 7 - $basearch - Debug # baseurl = https://repo.ius.io/7/$basearch/debug/ # enabled = 0 # repo_gpgcheck = 0 # gpgcheck = 1 # gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-IUS-7 # [ius-source] # name = IUS for Enterprise Linux 7 - Source # baseurl = https://repo.ius.io/7/src/ # enabled = 0 # ↑0であることを確認 # repo_gpgcheck = 0 # gpgcheck = 1 # gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-IUS-7 # 可能なGitのバージョンを確認 [root@ ~]# yum list --enablerepo=ius | grep git2 # git224.x86_64 2.24.4-1.el7.ius @ius # git224-core.x86_64 2.24.4-1.el7.ius @ius # git224-core-doc.noarch 2.24.4-1.el7.ius @ius # git224-perl-Git.noarch 2.24.4-1.el7.ius @ius # bluez-tools.x86_64 0.2.0-0.7.git20170912.7cb788c.el7 # bluez-tools-debuginfo.x86_64 0.2.0-0.7.git20170912.7cb788c.el7 # Gitをダウンロード [root@ ~]# yum -y install --enablerepo=ius git224 [root@ ~]# git --version git version 2.24.4 GitへSSH接続するようにする このままgit cloneすると以下のようなエラーが発生する [kazuki@ laravelpractice]$ git clone https://github.com/■/laravelpractice.git fatal: could not create work tree dir 'laravelpractice': 許可がありません [kazuki@ ~]$ ssh -T git@github.com The authenticity of host 'github.com (52.69.186.44)' can't be established. ECDSA key fingerprint is SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM. ECDSA key fingerprint is MD5:7b:99:81:1e:4c:91:a5:0d:5a:2e:2e:80:13:3f:24:ca. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'github.com,52.69.186.44' (ECDSA) to the list of known hosts. Permission denied (publickey). サーバ上でGitHubを使えるようにするためには、GitHubと本番サーバがSSH接続できるように設定しないといけない。 秘密鍵・公開鍵を作成する。 [kazuki@ ~]$ cd .ssh # 秘密鍵・公開鍵の作成を行う [kazuki@ ~]$ ssh-keygen -m pem # 以下enter連打 Generating public/private rsa key pair. Enter file in which to save the key (/home/kazuki/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/kazuki/.ssh/id_rsa. Your public key has been saved in /home/kazuki/.ssh/id_rsa.pub. The key fingerprint is: SHA256:ylUI/765qmMHMAqmK3c01M6kHQl9VmhdFHo3enCUIS0 kazuki@ # 公開キーを確認 [kazuki@ ~]$ cat ~/.ssh/id_rsa.pub # 以下ファイルに転記 [kazuki@ ~]$ vi ~/.ssh/authorized_keys [kazuki@ ~]$ cat ~/.ssh/authorized_keys ここまでできたらGitHubに公開鍵を登録する。 GitHub 右上のプロフィール画像をクリックして「Settings 」メニューを開いて「SSH and GPD keys」メニューを開くと「New SSH Key」ボタンがあるのでクリック。その画面で先ほど公開鍵 (id_rsa.pub) の文字列を登録 # 再度SSH接続できるかチェック [kazuki@ ~]$ ssh -T git@github.com Warning: Permanently added the ECDSA host key for IP address '13.114.40.48' to the list of known hosts. Hi ■! You've successfully authenticated, but GitHub does not provide shell access. 再度git cloneしたがまた怒られた sh [kazuki@ ~]$ git clone https://github.com/■/laravelpractice.git Cloning into 'laravelpractice'... Username for 'https://github.com': ■ Password for 'https://■@github.com': remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead. remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information. fatal: Authentication failed for 'https://github.com/■/laravelpractice.git/' アクセストークンの設定をする必要があるようなので設定。 GitHub 右上のプロフィール画像をクリックして「Settings 」メニューを開いて「Developer settings」メニューを開くと「Personal access tokens」ボタンがあるのでクリックしてアクセストークンを取得。アクセストークンを以下のようにURLに組み込んで再度clone [kazuki@ ~]$ git clone https://[アクセストークン]@github.com/■/laravelpractice.git Cloning into 'laravelpractice'... remote: Enumerating objects: 323, done. remote: Counting objects: 100% (323/323), done. remote: Compressing objects: 100% (259/259), done. remote: Total 323 (delta 43), reused 323 (delta 43), pack-reused 0 Receiving objects: 100% (323/323), 646.85 KiB | 9.95 MiB/s, done. Resolving deltas: 100% (43/43), done. [kazuki@ ~]$ ls composer-installer.php laravelpractice portfolio laravelプロジェクト公開の下準備
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

やっと分かった「インスタンス化」

■よく分かんないけどnewする プログラミングを始めてから、ずっと分からなかったんです。 インスタンス化。 なんだかよく分かんないけど、 newしないとできないことがあって、 newするとできるようになることがある。 どうやらこれがインスタンス化って言うらしい。 ふーん? newするって何なの...って思いながらいつもnewしてました。 調べると記事は色々出てきますよね。 設計図を実体化するみたいな感じ、とか大体そんなふうに。 ふむふむなるほど、、、、 わ〜、全然ピンと来ないなあ ? あ、決してわたしの見た記事がダメだったとかそういうことはなくて わたしの理解力のなさがピンと来なかった原因なんですが、 つい先日ようやく開眼(?)いたしまして、 今回はそれを記事にしたいと思います。 ■インスタンス化っていうのは 思ったんですよ。 インスタンス化っていうのはもしかして、 召喚獣を召喚するのと同じなんじゃない??  って。 いきなり召喚獣とか言い出して大丈夫でしょうか。 大丈夫です。 (あまりゲームに馴染みのない方には意味不明ですね、すみません汗) さてここに魔術書があることにします。 魔術書にはありとあらゆる召喚獣を呼び出すための魔術が書かれていますが その中から召喚獣をひとつピックアップしてみましょう。 tsuyoi_dragon.php class TsuyoiDragon { public function flame_breath ($energy, $anger) { $flame_power = $energy*$anger; return $flame_power; } public function blizzard_breath ($eneregy, $sadness) { $blizzard_power = $eneregy*$sadness; return $blizzard_power; } } 旅の途中で敵に遭遇して、 このツヨイドラゴン(強い)を呼び出して敵をやっつけたい!と思ったとき 魔術書に向かって「flame_breath!!!」と叫んでも 本に向かって何やら大きい声を出している人 に なってしまうだけなのですが それはちょっと恥ずかしいので、ここで代々伝わる詠唱方法を使います。 そうです、それが「new」です。 newとは言い換えると、「出でよ!!」なのであります。 「出でよ!ツヨイドラゴン!flame_breathだ!」 をphp風に記述すると summon_spell.php $tsuyoi_dragon = new TsuyoiDragon; $attack = $tsuyoi_dragon->flame_breath($energy, $anger); こんな感じになるかと思います。 いかがでしょう。伝わりますでしょうか。 魔術書に書かれているだけの状態ではツヨイドラゴンの必殺技は使えないので、 「new(出でよ)して召喚獣を出現させてから任意の必殺技を指示できる状態にする」 これがインスタンス化なのだと理解したとき、 ようやくわたしのなかで腑に落とすことができまして 大変スッキリしました。 ■さいごに この記事に辿り着いて頂いた方に、 スッキリが少しでもシェアできましたら嬉しいです。 最後までお読み頂きありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel + Docker の環境で、PostgreSQLに接続するためにやったこと

はじめに docker-composeを使用してLaravelの環境を構築し、PostgreSQLに接続するためにやったことを備忘録としてまとめておきます。 なお、docker-composeを使用したLaravelの環境は、下記の記事を参考に構築しました。 Dockerを使ってLaravelのローカル開発環境を作る(Apache版) ファイルパスなどは少し変更している箇所がありますので、ご自分の環境に合わせて読み換えてください。 環境 OS: MacOS Big Sur Docker: 20.10.11 docker-compose: v2.2.1 やったこと 下記の二つを行いました。 環境変数 DB_CONNECTION の値を変更 コンテナ内に、PHPの拡張機能 pdo_pgsql をインストール 以下で詳しく説明していきます。 環境変数 DB_CONNECTION の値を変更 Laravelで使用するDBを設定しているのは、config/database.php ファイル内の下記の箇所になります。 config/database.php(一部) 'default' => env('DB_CONNECTION', 'mysql'), Laravelの env() 関数は、第一引数で取得する環境変数の値を指定し、第二引数にデフォルト値(環境変数に第一引数で指定した値がない場合の値)を指定することができます。(参考) そのため、MySQL以外のDBを使用したい場合は、環境変数 DB_CONNECTION に何かしらの値を設定する必要があります。(参考) 今回はPostgreSQLを使用したいので、pgsql を設定します。 コンテナ内の環境変数の設定は、docker-compose.yml ファイル内で行っているので、そこに追記します。 docker-compose.yml(一部) version: "3.8" services: web: build: context: . dockerfile: ./docker/app/Dockerfile ports: - ${WEB_PORT:-80}:80 volumes: - ./src:/work/src environment: - DB_CONNECTION=pgsql # ここを追記 コンテナ内に、PHPの拡張機能 pdo_pgsql をインストール Laravelでは、PHPの拡張機能であるPDOを使用してDBを操作していますが、PDOは使用するデータベースのドライバをインストールしなければ動きません。 そのため、コンテナ起動時に docker-php-ext-install コマンドを使用して pdo_pgsql をインストールします。(pdo_pgsqlについてはこちら) 加えて、pdo_pgsql は、libpq-dev パッケージが必要なので、こちらもインストールします。(参考) 上記処理を Dockerfile に記述します。 docker/app/Dockerfile FROM php:7.4-apache SHELL ["/bin/bash", "-oeux", "pipefail", "-c"] ENV COMPOSER_ALLOW_SUPERUSER=1 \ COMPOSER_HOME=/composer COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer RUN apt-get update && \ apt-get -y install git unzip libzip-dev libicu-dev libonig-dev postgresql libpq-dev && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ a2enmod rewrite && \ docker-php-ext-install intl pdo_pgsql zip bcmath COPY ./docker/app/php.ini /usr/local/etc/php/php.ini COPY ./docker/app/httpd.conf /etc/apache2/sites-available/000-default.conf WORKDIR /work/src
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む