Study & Practice

北海道札幌市のプログラマによる技術とか雑記のブログ

ReactRouter~子コンポーネントでthis.porps.history.push()がTypeError: Cannot read property 'push' of undefinedになる

そこそこハマったけど意外と情報が出てこなかったので記録

react等のバージョンは以下(package.json)

{
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-router-dom": "^5.2.0",
    "react-scripts": "3.4.3"
}

今回発生したパターンの発生条件としては子コンポーネントにpropsを渡すためにcomponentではなくrenderを使ったことで、解決策としては子コンポーネントのexport時にwithRouterを使うことでした

以下の手順でサンプルの環境を作りました

npm create-react-app trial-router
cd trial-router
npm install react-router-dom

src/App.jsを以下の内容に更新

import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import Base from './BaseComponent';
import Moved from './MovedComponent';

function App() {
  return (
    <div className="App">
      <h1>HOME</h1>
      <BrowserRouter>
        <Route
          exact path="/"
          render={() =>
            <Base text={"Base"} />
          }
        />
        <Route
          path="/moved"
          render={() =>
            <Moved text={"Moved"} />
          }
        />
      </BrowserRouter>
    </div>
  );
}
export default App;

src/ChildComponent.jsを以下の内容で作成

import React from 'react';

class Base extends React.Component {
  move = () => {
    this.props.history.push("/moved");
  }
  render() {
    return (
      <>
        <div>{this.props.text}</div>
        <button onClick={this.move}>
          Move
        </button>
      </>
    );
  }
}
export default Base);

src/MovedComponent.jsを以下の内容で作成

import React from 'react';
class Moved extends React.Component {
  move = () => {
    this.props.history.push("/");
  }
  render() {
    return (
      <>
        <div>{this.props.text}</div>
        <button onClick={this.move}>
          Back
        </button>
      </>
    );
  };
}

export default Moved;

ファイルを作成して

npm start

すると以下のようなページができるはず
f:id:carametal:20201008153129p:plain
このページでMoveボタンを押すと
f:id:carametal:20201008153217p:plain
みごと「TypeError: Cannot read property 'push' of undefined」が発生する

解決策としてはChildComponent.jsとMovedComponent.jsをそれぞれ以下のように変更する
v

// ChildComponent.js
import React from 'react';
// withRouterをimport
import { withRouter } from 'react-router-dom';

class Base extends React.Component {
  move = () => {
    this.props.history.push("/moved");
  }
  render() {
    return (
      <>
        <div>{this.props.text}</div>
        <button onClick={this.move}>
          Move
        </button>
      </>
    );
  }
}
// withRouterの引数にBaseを指定
export default withRouter(Base)
// MovedComponent.js
import React from 'react';
// withRouterをimport
import { withRouter } from 'react-router-dom';

class Moved extends React.Component {
  move = () => {
    this.props.history.push("/");
  }
  render() {
    return (
      <>
        <div>{this.props.text}</div>
        <button onClick={this.move}>
          Back
        </button>
      </>
    );
  };
}
// withRouterの引数にMovedを指定
export default withRouter(Moved);

2ファイルとも修正は同じ

withRouterを追加したらボタンを押すことでChildとMovedを行き来できるはず

ちなみにクラス構文を使わずにReact Hooksを使っても同様のエラーが発生した。

コンポーネントにpropsを渡しつつhistory.push()するときはwithRouterは必須みたいですね

ASP.NET Core MVCにPostgreSQLを導入する

本記事はASP.NET Core は3.1、PostgreSQLは12.0で行っています
ASP.NET CoreでPostgreSQLを使えるようにするまでなのでPostgreSQLのインストールなどは割愛してあります。

こちらのチュートリアルをベースに進めていきます
docs.microsoft.com

ASP.NET Core 3.0に更新してないと書いてあるのでこちらの内容も織り交ぜてあります。
docs.microsoft.com

プロジェクトの作成

まずはVisual Stadioで新しいプロジェクトの作成→ASP.NET Core Webアプリケーションと選択します。
プロジェクト名はPostgreSQLTrialとしました。

フレームワークが「.NET Core」バージョンが「ASP.NET Core 3.1」になっていることを確認し、Webアプリケーション(モデルビューコントローラー)を選択します。

作成ボタンを押せばプロジェクトが作成されます。

パーケージのインストール

Entity Framework CoreとEntity Framework CoreでPostgreSQLを扱うためのパッケージをインストールします。
パッケージマネージャーコンソールで下記のコマンドを実行

Install-Package Microsoft.EntityFrameworkCore.Tools
Install-Package Npgsql.EntityFrameworkCore.PostgreSQL

正常にインストールされれば完了です。

コードの追加

モデルの作成を作成します。
プロジェクト直下のModels配下に以下の内容でStudent.csを追加

namespace PostgreSQLTrial.Models
{
    public class Student
    {
        public int Id { get; set; }
        public string FirstMidName { get; set; }
        public string LastName { get; set; }
    }
}

次にContextを作成します。
プロジェクト直下にDataディレクトリを作成し、Dataディレクトリ配下に以下の内容でShoolContext.csを追加します。

using Microsoft.EntityFrameworkCore;
using PostgreSQLTrial.Models;

namespace PostgreSQLTrial.Data
{
    public class SchoolContext: DbContext
    {
        public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
        {

        }

        public DbSet<Student> Students { get; set; }
    }
}

ConnectionStringの設定

次はPostgreSQL接続用のConnectionStringを設定します。ConnectionStringはappsettings.jsonとappsettings.Development.jsonで定義します。appsettings.jsonは本番構成時、appsettings.Development.jsonデバッグ構成時に利用されます。

それぞれに以下を追加します。

"ConnectionStrings": {
    "SchoolContext": "Host=my_host;Database=my_db;Username=my_user;Password=my_pw"
}

追加後のappsettings.jsonは私の環境では以下のようになっています。

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
    "ConnectionStrings": {
        "SchoolContext": "Host=my_host;Database=my_db;Username=my_user;Password=my_pw"
    }
}

my_host、my_db、my_user、my_pwとなっている箇所は自分のPostgreSQLの設定に合わせて適宜変更が必要です。

次にStartup.csにSchoolContextを追加する処理を加えます
以下のコードをConfigureServicesに追加してください。

services.AddDbContext<SchoolContext>(options => 
{
    options.UseNpgsql(Configuration.GetConnectionString("SchoolContext"));
});

追加後のConfigureServicesは以下のようになります。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddDbContext<SchoolContext>(options => 
    {
        options.UseNpgsql(Configuration.GetConnectionString("SchoolContext"));
    });
}

Migrationの作成と実行

まずはPostgreSQLにSchoolデータベースを作成します。

PostgreSQLで以下のSQLを流します

create database school;

データベースの作成もコードファーストで行いたい方は
docs.microsoft.com
こちらを参考にしてください。

データベースの作成が完了したら以下のコマンドをパッケージマネージャーコンソールで流します。
このコマンドで移行の作成とデータベースへの適用が完了します。

Add-Migration InitialMigration
Update-Database

スキャフォールディングでControllerとViewを追加する

ソリューションエクスプローラーでControllersディレクトリを右クリック→追加→新規スキャフォールディングアイテムと選択します。

「新規スキャフォールディングアイテムの追加」ダイアログでは「Entity Framework を使用したビューがあるMVCコントローラー」を選択し、「追加」を押します。

モデルクラスに「Student」、データコンテキストクラスに「SchoolContext」を選択します。

コントローラー名は任意でいいですが本記事ではデフォルトの「StudentsController」としました。

「追加」を押します。

スキャフォールディングが完了するとControllers配下に「StudentsController.cs」がViews配下に「Students」ディレクトリがあり、Index、Create,Edit、Details、Deleteのcshtmlファイルがあるはずです。

動作確認

F5を押す、もしくはIIS Expressボタンを押してデバッグ実行します。

ブラウザが立ち上がったらアドレスバーに「/Students/Index」を追加します。

追加後のアドレスは私の環境では「https://localhost:44345/Students/Index」となりました。

Studentの一覧画面が表示されていると思いますので追加、編集、削除を実行します。

それぞれ正常に動作すればASP.NET Core MVCへのPostgreSQL導入は完了です

ドラッカーの「マネジメント」入門|「もし高校野球の女子マネージャーがドラッカーの『マネジメント』を読んだら」を読んでみた

f:id:carametal:20200927214747p:plain

ブログ「最も早くオシャレになる方法KnowerMag」のMBさんが成功の要因としてドラッカーのマネジメントを読み込んで徹底的に実践しているという話をしていました。マネジメントは組織経営のあり方についてまとめられている本ですが、MBさんの話を聞いていると自分自身をキャリアを形成することにもとても良い効果をもたらす模様。

読んでみたいと思ったものの、分厚く内容も非常に難解な本らしいので、まずはわかりやすく読みやすい本から始めるということで約10年前に流行った「もし高校野球の女子マネージャーがドラッカーの『マネジメント』を読んだら」、通称「もしドラ」を読んでみることにしました。

敏腕マネージャーと野球部の仲間たちが甲子園を目指して奮闘する青春小説。高校野球の女子マネージャーのみなみちゃんは、マネージャーの仕事のために、ドラッカーの『マネジメント』を間違って買ってしまいます。はじめは難しくて後悔するのですが、しだいに野球部のマネジメントにも生かせることに気付きます。これまでのドラッカー読者だけでなく、高校生や大学生、そして若手ビジネスパーソンなど多くの人に読んでほしい一冊。

出版元であるダイヤモンド社さんより引用

ドラッカーのマネジメントの内容を著者の岩崎夏海さんが非常に重要視しているもののみを厳選して引用しながら、ストーリーに絡めて読みやすく書いているという印象です。まだ本元のマネジメントを読んでいないので、実際にどの程度わかりやすくなっているかなどはわかりませんが、マネジメントはAmazonのレビューなどでも非常に難解だというコメントが多いのでもしドラはかなり読みやすくなっているのだと思います。本記事では読んでいて重要だと感じたところをまとめていきます。

マネージャーの資質

本書で一番に解説されていたの「マネージャーの資質」についてでした。

マネジャーの仕事は、体系的な分析の対象となる。マネジャーにできなければならないことはそのほとんどが教わらなくても学ぶことができる。しかし、学ぶことのできない資質、後天的に獲得することのできない資質、始めから身に着けていなければならない資質が、一つだけある。才能ではない。真摯さである。

真摯さと一言でいっても本書から読み解けるのは顧客のことを考えるというような単純なことではなく、顧客に価値を提供したうえで働いている人自身も目標を叶えられる。そんなWin-Winの状態を常に目指し続けるというようなレベルで求められます。この辺は7つの習慣の公的成功や、人格主義に通じるところがあります。

本書の著者である岩崎夏海さんはこの「真摯さ」をかなり重要視しているらしく、本書のド頭に出てくることに加えストーリーの終盤でも「真摯さ」について語る重要なシーンがあったり、本編後の著者への解説インタビューでも「真摯さ」について結構な分量で語られています。「真摯さ」はマネジメントを読む際のキーポイントになりそうです。

組織の定義づけ

本書で「真摯さ」の次に語られていたのが組織の定義付けについてでした。それは「われわれの事業は何か?」という問いで語られます。

野球部なのだから野球をすることがわれわれの事業になりそうですがドラッカーはこう語っているようです。

自らの事業は何かを知ることほど簡単でわかりきったことはないと思われるかもしれない。鉄鋼会社は鉄を作り、鉄道会社は貨物と乗客を運び、保険会社は火災の危険を引き受け、銀行は金を貸す。しかし実際には、「われわれの事業は何か」との問いは、ほとんどの場合、答えることが難しい問題である。わかりきったことが正しいことはほとんどない。

これに対してドラッカーは「われわれの事業はなにか」という問いの答えを導き出すには「顧客」が唯一の出発点だと語ります。

つまり、「顧客がわれわれに求めるものはなにか」ということにつながります。そしてここでもう一つ「顧客とはだれか」という問いが出てきます。

マネジメントではキャデラックが例として挙げられているらしく、本書でも以下のように引用されています。

一九三〇年代の大恐慌のころ、修理工からスタートしてキャデラック事業部の経営を任されるにいたったドイツ生まれのニコラス・ドレイシュタットは「われわれの競争相手はダイヤモンドやミンクのコートだ。顧客が購入するのは、輸送手段ではなくステータスだ」と言った。この答えが破産寸前のキャデラックを救った。わずか二、三年のうちに、あの大恐慌時にもかかわらず、キャデラックは成長事業へと変身した。

キャデラックは「顧客」を単に車が欲しい人ではなく「ダイヤモンドやミンクのコートを買う消費者」と定義し、性能やコストパフォーマンスではなく、高級でかっこいい「ステータス」となる車を顧客に届けることを「われわれの事業」として定義し、成長することができたということです。

私は現在、ソフトウェア開発を生業とする企業に勤めていますが、この「われわれの事業は何か」、「顧客とはだれか」を答えるのは非常に難しいと思いました。単に「ソフトウェアを開発すること」でも、「ソフトウェアを作ってほしい人」でもないわけです。しかも、客先常駐を長らく続けてきたこともあり、企業としての技術的な強みがなく、顧客も多岐にわたるからです。また、私個人としても「なんのためにソフトウェアを開発しているのか」と深堀りしてみると全く答えが出せません。この二つの問いについては、仮設を立てて試行錯誤しながら答えを見つけていかないといけないのかなと思いました。

マーケティング

そして顧客の定義付けができれば次はキャデラックの例で言う「ステータス」というキーワードにたどり着かなければいけません。これには

「われわれは何を売りたいか」ではなく、「顧客は何を買いたいか」を問う。

と引用されている。

そしてその時に必要になるのが「現実・欲求・価値」です。これはそれぞれ、顧客が置かれている状況、顧客が求めるもの、顧客が価値を見出すもののことです。

これは現実と欲求を調査して顧客が価値を見出すものを分析するという手順になるのかと思います。T型フォードを作ったヘンリー・フォードの「もし顧客に、彼らの望むものを聞いていたら、彼らは『もっと速い馬が欲しい』と答えていただろう。」という言葉は有名ですが、顧客が求めているのは本当に顧客が欲しいものとは限りらないからです。この辺りも仮設と検証を繰り返して顧客が真に見出すものを作り出していく必要があるのだと思います。

イノベーション

マーケティングは非常に重要であるがマーケティングだけでは大きな成果は出せない。と本書では語られており、「マネジメント」より以下のように引用されています。

マーケティングだけでは企業としての成功はない。性的な経済には、企業は存在しえない。そこに存在しうるものは、手数料をもらうだけのブローカーか、何の価値も生まない投機家である。企業が存在しうるのは、成長する経済のみである。あるいは少なくとも、変化を当然とする経済においてのみである。そして企業こそ、この成長と変化のための機関である。したがって企業の第二の機能は、イノベーションすなわち新しい満足を生み出すことである。経済的な財とサービスを供給するだけでなく、よりよく、より経済的な財とサービスを供給しなければならない。企業そのものは、より大きくなる必要はないが、常によりよくなければならない。

そしてイノベーションを起こす手法として以下のように引用されています。

イノベーションの戦略の一歩は、古いもの、死につつあるもの、陳腐化したものを計画的かつ体系的に捨てることである。イノベーションを行う組織は、昨日を守るために時間と資源を使わない。昨日を捨ててこそ、資源、特に人材という貴重な資源を新しいもののために解放できる。

つまりイノベーションを起こすにはまず初めに何かを「捨てる」ことが必要であるということです。昨今ではイノベーションは科学や技術によって起こすものと捉えられがちですが、ドラッカーの主張はそれだけではないということでしょう。

本書では「送りバント」と「ボール球を打たせる投球術」を捨てる手法を取っていた。程度の差はあるがどちらもメジャーリーグでも戦略としてあまり重要視されなくなってきている。いまだ古いセオリーに則っている高校野球に「送りバント」と「ボール球を打たせる投球術」を捨てた戦法で挑戦し結果を残すことで、高校野球界そのものにイノベーションを巻き起こそうということです。

私はイノベーションというと今まで新しいものを取り入れるという方向で物事を考えがちでしたが、捨てるという方向がイノベーションの一歩目というのは納得ができました。新しいことをする時間を作る場合でも、今まで何かをしていた時間を捨てなければいけません。日常的には無意識のうちにこういう取捨選択をしているのだと思いますが、意識的に捨てること特に「計画的かつ体系的に」というところが重要なのだと思います。

成果について

成果とは何かを理解しなければならない。成果とは百発百中のことではない。百発百中は曲芸である。成果とは長期のものである。すなわち、まちがいや失敗をしないものを信用してはならないということである。それは、見せかけか、無難なこと、下らないことにしか手をつけないものである。成果とは打率である。弱みがないことを評価してはならない。そのようなことでは、意欲を失わせ、士気を損なう。人は、優れているほど多くのまちがいをおかす。優れているほど新しいことを試みる。

「成果とは打率である。」と「優れているほど多くのまちがいをおかす」というのは矛盾しているような気がしますが、打席に立つ回数が多いからまちがいが増えるだけで打率は低くてはいけないということなのか。

それにしても「まちがいや失敗をしないものを信用してはならない」というのは強烈なメッセージかと思います。現代の日本企業は成功することよりも失敗しないことが評価されるという話を至る所で聞きますが、そのほとんどは信用してはいけない、成果を出していないということになります。これは組織作りにおいてかなり重要なポイントだと思います。しかし、個人においても失敗をするかもしれない行動を増やすというのはやはり成果を出すうえで避けては通れない道なのでしょう。

また、成果については以下のような引用もありました。

成果よりも努力が重要であり、職人的な技能それ自体が目的であるかのごとき錯覚を生んではならない。仕事のためではなく成果のために働き、贅肉ではなく力をつけ、過去ではなく未来のために働く能力と意欲を生み出さなければならない

努力してるから良い。努力していないから悪い。ではなく成果に価値を置かなければならない。そして職人的な技能を持っていることよりも実際に生み出す成果が重要である。これは我々のような技術者として生計を立てている人たちには少し耳が痛い部分であるかもしれません。いくら技術的に優れていてメンテナンス性やパフォーマンスに優れたシステムを開発しても成果が生まれなければならない。非常にシビアですが、事業においては最も重要なことだと思いました。

まとめ

「マネジメント」をストーリーに絡めて読みやすくした内容ではありますが、本書に書かれている内容を理解し自分の環境で実践することでドラッカーの恩恵を十分に受けられると感じました。

私はビジネス書として読んでいたのであまり気になりませんでしたが、小説として特別面白いものだとは感じませんでした。とはいえ、夏の西東京大会決勝戦のラストシーンは私自身も高校時代に野球部だったこともあって高揚感を覚えました。その点で言うとそこそこ楽しめる本だともいえると思います。

次はドラッカーの「マネジメント」を読んでみたいと思います。

EC2インスタンスにApacheのサーバーを立ててのテストページを表示する

今まで何回もやったことあるけど毎回忘れて調べてるので備忘録として手順を残す

VPCの作成

マネジメントコンソール上部のサービスタブからVPCを選択してVPC管理画面で「VPCの作成」ボタンを押す

VPCの設定では名前とCIDRブロックを設定する
今回は名前をtrial-vpc、CIDRブロックをデフォルトの10.0.0.0/24を選択

作成ボタンを押してVPCの作成は完了

サブネットの作成

VPC管理画面の左側メニューから「サブネット」を選択し、上部の「サブネットの作成」ボタンを押す

サブネットの作成画面では名前、VPCアベイラビリティーゾーン、CIDR ブロックを以下に設定する

名前 trial-subnet
VPC trial-vpc
アベイラビリティーゾーン ap-northeast-1a
CIDRブロック 10.0.0.0/24

VPCは先ほど作ったVPC選択する。本記事ではtrial-vpc

アベイラビリティーゾーンはどれを選んでも問題ない。本記事ではap-northeast-1aを選択

CIDRブロックはVPC内でネットワークを分ける場合は細かく設定する必要があるが
今回は分けないで行うためVPCと同じ10.0.0.0/24を設定

作成ボタンを押してサブネットの作成は完了

インターネットゲートウェイの作成

画面左側のメニューから「インターネットゲートウェイ」を選択し、「インターネットゲートウェイの作成」ボタンを押す

名前タグに「trial-ig」を設定して「インターネットゲートウェイの作成」ボタンを押す

インターネットゲートウェイの一覧画面から「trial-ig」の行を選択し、「アクション」、「VPCにアタッチ」を選択

「使用可能なVPC」の欄で[trial-vpc]を選択して「インターネットゲートウェイのアタッチ」ボタンをおして完了

ルートテーブルの作成

画面左側のメニューから「ルートテーブル」を選択し「ルートテーブルの作成」ボタンを押す

ルートテーブルの作成画面で名前タグを「trial-rt」、VPCを「trial-vpc」を選択して「作成」ボタンを押す

ルートテーブル一覧から[trial-rt]の行を選択して、下部の「ルート」タブを選択し「ルートの編集」ボタンを押す

「ルートの追加ボタン」を押し、送信先を「0.0.0.0/0」、ターゲットを「Internet Gateway」の「trial-ig」を設定して「ルートの保存」ボタンを押す

ルートテーブル一覧から[trial-rt]の行を選択して、下部の「サブネットの関連付け」タブを選択し「サブネットの関連付けの編集」ボタンを押す

サブネット一覧から「trial-subnet」を選択して「保存」ボタンを押して完了

EC2インスタンスの作成

画面上部のサービスタブからEC2を選択してEC2の管理画面を開く。
次に画面左側のメニューから「インスタンス」を選択し、「インスタンスの作成」ボタンを押す

ステップ 1: Amazon マシンイメージ (AMI)では「Amazon Linux 2 AMI (HVM), SSD Volume Type」を選択
ステップ 2: インスタンスタイプの選択では「t2.micro」を選択し次のステップへ
ステップ 3: インスタンスの詳細の設定では以下の設定をし次のステップへ

ネットワーク trial-vpc
サブネット trial-subnet
自動割り当てパブリックIP 有効

そのほかは任意の設定で問題ない。本記事ではデフォルトのまま進める。

ステップ 4: ストレージの追加では必要な分のストレージを設定し次のステップへ。本記事ではデフォルトのままとした
ステップ 5: タグの追加では必要に応じてタグを設定して次のステップへ。本記事ではタグを1つ追加してキーを「Name」、値を「trial-ec2」のみを設定
ステップ 6: セキュリティグループの設定では新しいセキュリティグループを作成するを選択しセキュリティグループ名を「trial-ec2-sg」として以下を設定して「確認と作成」ボタンを押す

タイプ ソース
SSH マイIP
HTTP カスタム(0.0.0.0/0, ::/0)

ステップ 7: インスタンス作成の確認では入力に間違いがないかを確認し、「起動」ボタンを押す

上記を行うと「既存のキーペアを選択するか、新しいキーペアを作成します。」というダイアログが出てくる

キーペアを使いまわすことは推奨されていないので「新らしいキーペアの作成」を選択し、キーペア名を「trial-ec2-key」と設定して「キーペアのダウンロード」を押す
キーペアのダウンロードが完了したら「インスタンスの作成」ボタンを押す

インスタンス画面に戻りNameがtrial-ec2となっている行のインスタンスの状態が「running」になれば問題なくEC2インスタンスが起動している。
インスタンスの状態が「pending」になっている場合は数十秒から数分程度までば「running」に遷移するはず

EC2インスタンスApacheをインストールする

インスタンス画面で「trial-ec2」の行を選択して出てくる画面下部の「説明」欄からIPv4 パブリック IPをクリップボードにコピーする

ターミナルソフトを開き(本記事ではWindowsコマンドプロンプト)キーペアのあるディレクトリに移動したら下記コマンドを実行する

ssh -i trial-ec2-key.pem ec2-user@コピーしたIPアドレス

キーペア名(trial-ec2-key.pem)はキーペアのダウンロード時に設定したキーペア名を入力する
コピーしたIPアドレスの部分は本記事のようにインスタンス作成のステップ 3で自動割り当てパブリックIPを有効にした場合、EC2インスタンスを起動するごとにインスタンスIPアドレスが変わるので注意

初回ログイン時は下記のようなメッセージが出てくるがyesで問題ない

The authenticity of host 'IPアドレス (IPアドレス)' can't be established.
ECDSA key fingerprint is SHA256:Je2wxOb+fwZosDX/qZKL1AjOojfiwedHag2M/5mRe9U.
Are you sure you want to continue connecting (yes/no)?

ログインできたら下記のコマンドでApacheをインストールしてApacheを起動する

sudo yum install -y httpd
sudo systemctl status httpd

ブラウザからEC2にアクセスする

sshで繋いだのと同じIPアドレスにブラウザからアクセスしたらApacheのテストページが表示されるはず

以上で「EC2インスタンスApacheのサーバーを立ててのテストページを表示する」が完了

composer install で「Your requirements could not be resolved to an installable set of packages.」のエラーになる件

本記事の環境は以下

  • Windows10 Home
  • WSL2 Ubuntu18.04
php artisan serve

を実行すると

PHP Warning:  require(/var/www/html/pf-blog/vendor/autoload.php): failed to open stream: No such file or directory in /var/www/html/pf-blog/artisan on line 18
PHP Fatal error:  require(): Failed opening required '/var/www/html/pf-blog/vendor/autoload.php' (include_path='.:/usr/share/php') in /var/www/html/pf-blog/artisan on line 18

っていうエラーを吐いてしまう

調べてみると

composer install

で解決するらしいのだがそもそもこれがうまくいかない
最初は気づかなかったのだがログをよく見てみると

Your requirements could not be resolved to an installable set of packages.

というエラーで止まってしまっているらしい
ログを見てみるとどうやらmbstringとdomが入っていないようだ

sudo apt install php7.2-mbstring php7.2-dom

そして今度は以下のようなエラーが

Failed to download league/flysystem from dist: The zip extension and unzip command are both missing, skipping.
Your command-line PHP is using multiple ini files. Run `php --ini` to show them.
    Now trying to download from source

どうやらzipとunzipコマンドが入っていないらしい

sudo apt install -y zip unzip

もう一度

composer intall

すると

Package manifest generated successfully.
46 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

どうやら解決したようだ

php artisan serve

してhttp://127.0.0.1:8000にアクセスしてみると

f:id:carametal:20200730230739p:plain

無事テストページが表示された

AWS管理インターフェースについて調べた

5月から客先常駐ではなく在宅による受託開発になり、記念すべき一発目の仕事でクラウドを利用するとのことなので改めてAWSを学び始めた。

ひとまずAWS クラウドラクティショナーの無料トレーニング動画を見始めたのだが、気になったことがあったので調べてみた。

AWS管理インターフェース(AWS Management Interfaces)とは

AWSリソースを作成、及び管理する方法の総称で以下の3つが存在する(2020年7月10日時点)

インターフェースはこのうちの1つに絞る必要はなく、組み合わせて使うことができる
※複数のインターフェースをまたいでAWSを使用した時、一方での操作が反映されるまで時間がかかることがあるので注意


AWSクラウドラクティショナー無料トレーニング動画のかなり序盤ににAWS管理インターフェースの名前が出てくるのだが、ググっても全然出てこない。この呼称はあまり使われていないらしい

今まで個人的にEC2やS3を遊びで使っていたが、AWSマネジメントコンソールとAWSコマンドラインインターフェースしか知らなかった。

それぞれの特徴

AWSマネジメントコンソール(AWS Management Console)について
  • AWSの様々なサービスや機能をGUIを通して使用することができる
  • AndroidiOSで操作できるアプリも用意されている
  • アラームを設定してタスクを実行させることができる
AWSコマンドラインインターフェース(AWS Command Line Interface)について
AWS SDK(AWS Software Development Kit)について
  • 既存のアプリケーションでAWSを使用できる
  • システムをデプロイしてモニタリングするようなアプリケーションを1から作成できる
  • AWS CLIと組み合わせることでAWSをカスタマイズしたツールを作成できる


以上、簡単にだがAWS管理インターフェースをまとめてみた。

まだまだAWS自体を使えているわけではないので基本的な知識や使い方を学んでいきたいところではあるが、そのうちAWS SDKを使ったコアな開発というのもやってみたい。

Laravle+ApacheでDocument Root以外にアクセスすると404エラーになる際の対処法

こちらの記事にて解決しました

teratail.com

以下のコマンドでmod_rewriteを有効化するだけでDocument Root以外も表示されるようになった

cat /etc/apache2/mods-available/rewrite.load
sudo a2enmod rewrite

しかし、さっぱり何をしているのかわからなかったので少し深堀してみる

ちなみに公式ドキュメントにmod_rewiteを有効にしろと書いてあった
https://readouble.com/laravel/6.x/ja/installation.html?header=Apache

mod_rewriteとは

まず、mod_rewriteはサーバーへのリクエストに応じてURLを書き換え、リダイレクトを行ってくれる

といってもよくわからなかったのでmod_rewriteの設定ファイルである.htaccessを確認する
mod_rewriteはlaravelのプロジェクトであればpublicディレクトリの直下にある

僕の場合は以下のような設定になっていた

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>


正直よくわかっていないのだが今回重要なのが

# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

この部分

RewriteRuleは文字通りRewriteのルールを定義していて
RewriteCondはそのルールを適用する条件を設定している

RewriteCondの行の-dと-fはそれぞれディレクトリとファイルを表しており
RewriteCondが複数並んだ際はAnd条件となる

REQUEST_FILENAMEはファイルシステムにおけるフルパスのことなので

今回の場合、リクエストが指すパスの先がディレクトリでもなくファイルでもないときRerwiteを行うという条件になる

そしてRewriteRule

RewriteRuleはでは^という記号が使われている

^は正規表現において行頭を指す。
今回のRewriteRuleでいうと行頭をすべてindex.phpに置き換えるということになる

今回の設定値だと「/test」へのアクセスは「index.php/test」に変換しているということになる
この感じだと最初の/がなくなってしまっているがそこは内部的に変換しているのだと思う

ためしにmod_rewriteを無効にして「/index.php/test」にアクセスしてみるとちゃんとページが表示された
mod_rewriteを無効にするコマンドは以下

sudo a2dismod rewrite

a2enmonはenableで有効化
a2dismodはdisableで無効化ということらしい

ネット上によく見るものでは「RewriteRule ^ /index.php [L]」や「RewriteRule . /index.php [L]」ばかりなので
記載としては「RewriteRule ^ /index.php [L]」が正しいんじゃないかなと思っている

こうして振り返ってみると大した内容ではなかったが答えにたどり着くまでにも、何をしているのかを理解するのにも時間がかかってしまったが
こうして1歩ずつ成長していきたい

参考記事
html-coding.co.jphttps://murashun.jp/blog/20190215-01.html
https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
基本的な正規表現一覧 | murashun.jp