20200729のPHPに関する記事は15件です。

Xampp+CakePHP4+Eclipse開発環境を作成する(Windows)

CakePHP4での開発環境をローカルに作った時の自分の作業メモです。

作成環境

OS:Windows 10
Xampp:Windows版7.4.8
CakePHP:4.1.1
Composer 1.10.9
Eclipse 2020-06 (4.16.0)

Xamppインストール

https://www.apachefriends.org/jp/index.html

特に必要がなければデフォルトのc:\xamppでいいのではないかと。
という訳でそのあとは上記のパスにインストールした前提で記載します。

php.ini編集

後で「You must enable the intl extension to use CakePHP.」って怒られるので、
先にphpの設定を編集しておきます。

C:\xampp\php\php.ini
extension=intl
を下記に変更
extension=php_intl.dll

ドキュメントルート変更

xamppを使う場合のデフォルトルートは
C:\xampp\htdocs
変更する場合はApacheのhttpd.confを変更する。
画像のL252付近の下記二行をお好みに変更。
DocumentRoot "C:/workspace"
<Directory "C:/workspace">

無題.png

Composerインストール

Composer先生ってJenkins先生と画風が似てますね…
ひとまず普通にインストールすればOKと思われます。
https://getcomposer.org/

CakePHPプロジェクト作成

コマンドプロンプトでプロジェクトを作成したい場所に移動します。
基本ドキュメントルートで作成するかなと思います。
cd c:\workspace
composer create-project --prefer-dist cakephp/app <アプリケーション名>

作成完了後、
http://localhost/<アプリケーション名>
にアクセスすると下記のページが出ればOKです。
無題.png

データベース設定

この状態だと、まだMySQLの設定をしていないので
「CakePHP is NOT able to connect to the database.
Connection to Mysql could not be established: SQLSTATE[HY000] [1045] Access denied for user 'my_app'@'localhost' (using password: YES)」
というメッセージが出ているので、これを解消する。
XAMPPコンソールからMySQLのAdminを選択して管理コンソールを開く。
無題.png

データベースとユーザーを作成する。
コンソールのGUIからも作成できるけどコマンドで作ったほうが早いかも。
(といいつつコンソールで作った…)

作成したらC:\workspace\belongings-app\config\app-local.phpを編集
無題.png

Datasourcesの下階層のusername、password、databaseの内容を編集します。
これでエラーは解消されます。

Eclipseでのデバッグ設定

Eclipseのインストール及びPHP Development Toolsの導入を行います。
https://www.eclipse.org/downloads/

file>import>Existing Composer Project
で上記で作成したプロジェクトをインポートする。

コンテキストメニューのDebug Asか上のバグアイコンから「Debug Configration」を開く
無題.png
Name:任意
File:<アプリケーション名>/webroot/index.php

Debuggerタブに切り替えて「Configure」ボタンを押下する。
無題.png
Debugger:Xdebug
Port:お好み

「Finish」押下後、Debuugerタブの設定確認
無題.png
Break at First Line:チェック外しておく(どちらでもよいが…)

ここで「Debug」を押下すると、Eclipseの内部ブラウザで表示される

外部ブラウザで表示したい場合

Window > Preferences
General>Web Browser
無題.png
図のようにUser External web browserを選択して、下で好みのブラウザを選択する。

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

LighthouseでInterface TypeとUnion Typeを使いこなす【Laravel + GraphQL】

LighthouseのInterfaceやUnionを実装する際にちょっとハマったのと、それらに関する情報が調べても全然出てこなかったので記事にしました。

環境

PHP: 7.2.5
Laravel: 7.0
Lighthouse: 4.13

Interface Type

GraphQLのInterfaceはJavaやPHPでいう抽象(abstruct)フィールドと同様に、Interfaceで定義したフィールドを継承したTypeでも提供することを求められます。

またInterfaceを継承したTypeではそれ以外の値は自由に付け足すことが可能です。

GraphQL:Schemas and Types#Interfaces

interface Animal {
    id: ID!
    name: String!
}

type Cat implements Animal {
    id: ID!
    name: String!
    feed: String
}

type Dog implements Animal {
    id: ID!
    name: String!
    favorite: [DogItem!]!
}

type DogItem {
    id: ID!
    name: String
}

Iterface Typeを使用するメリットはそれ自体をQueryやMutationの引数や返り値に指定できることです。

例えば以下のような動物の一覧を返すQueryを定義したとします。

schema.graphql
type Query {
    animals: [Animal!]!
}

これを実行した場合、次のようにCatDogTypeが混ざったレスポンスが得られます。

query
query {
  animals {
    id
    name
    __typename

    ... on Cat {
      feed
    }

    ... on Dog {
      favorite {
        id
        name
      }
    }
  }
}
response
{
  "data": {
    "animals": [
      {
        "id": "1",
        "name": "hoge_cat",
        "__typename": "Cat",
        "feed": "pet_food"
      },
      {
        "id": "2",
        "name": "fuga_dog",
        "__typename": "Dog",
        "favorite": [
          {
            "id": "1",
            "name": "ball"
          }
        ]
      },
      {
        "id": "3",
        "name": "piyo_cat",
        "__typename": "Cat",
        "feed": "cat_food"
      }
    ]
  }
}

実装上の注意点

Lighthouse:Types #Interface

LighthouseでInterfaceを用いて実装するには通常のディレクティブ(@allや@createなど)を使用することはできず、Resolverを使用する必要があります。

$ php artisan lighthouse:query AnimalResolver
schema.graphql
type Query {
    animals: [Animal!]! @field(resolver: "App\\GraphQL\\Queries\\AnimalResolver@list")
}

またInterfaceを継承するTypeと同名のCatDogのモデルも作成します。
この時、配列や異なる名前のモデルを使用するとbasename() expects parameter 1 to be string, array givenというエラーが発生するので注意しましょう。

$ php artisan make:model Cat
$ php artisan make:model Dog
App\GraphQL\Queries\AnimalResolver
class AnimalResolver
{
    public function list($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
    {
        $hoge_cat = new Cat;
        $hoge_cat->id = 1;
        $hoge_cat->name = 'hoge_cat';
        $hoge_cat->feed = 'pet_food';

        $fuga_dog = new Dog;
        $fuga_dog->id = 2;
        $fuga_dog->name = 'fuga_dog';

        // ※Interfaceを継承していない通常のTypeは配列でも問題ない。
        $fuga_dog_item = [
                'id' => 1,
                'name' => 'ball'
        ];

        // モデルを使用する場合は以下のようにする。
        // $fuga_dog_item = new DogItem;
        // $fuga_dog_item->id = 1;
        // $fuga_dog_item->name = 'ball';

        $fuga_dog->favorite = [$fuga_dog_item];

        $piyo_cat = new Cat;
        $piyo_cat->id = 3;
        $piyo_cat->name = 'piyo_cat';
        $piyo_cat->feed = 'cat_food';

        return [
            $hoge_cat,
            $fuga_dog,
            $piyo_cat
        ];
    }
}

Union

Union Typeは他のTypeを単に列挙する抽象Typeです。
ただしInterfaceとは異なり、フィールドを定義することはできません。

GraphQL:Schemas and Types#Union types

union Book = Novel | Comic

type Novel {
    novel_title: String!
}

type Comic {
    comic_title: String!
}

Queryの実行方法はInterfaceと同様にonを用いることでそれぞれのTypeのレスポンスを指定することができます。

schema.graphql
type Query {
    books: [Book!]!
}
query
query {
  books {
    __typename

    ... on Novel {
      novel_title
    }

    ... on Comic {
      comic_title
    }
  }
}
response
{
  "data": {
    "books": [
      {
        "__typename": "Novel",
        "novel_title": "hoge title"
      },
      {
        "__typename": "Comic",
        "comic_title": "comic title"
      }
    ]
  }
}

実装上の注意点

Lighthouse:Types #Union

Interfaceと同様にUnionを用いる場合には通常のディレクティブを使用できないため、Resolverを使用する必要があります。

またレスポンスのTypeに関してもModelを使用しないとエラーとなるので注意しましょう。

App\GraphQL\Queries\BookResolver
class BookResolver
{
    public function list($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
    {
        $novel = new Novel;
        $novel->novel_title = 'hoge title';

        $comic = new Comic;
        $comic->comic_title = 'fuga title';

        return [
            $novel,
            $comic
        ];
    }
}

参考文献

GraphQL: Schemas and Types
Lighthouse: Types

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

[PHPStorm]Local Changesで開発中の資源をグループで管理する

はじめに

PHPStormのバージョン管理のヘルパー機能である、Local Changesの使い方メモです。

詳細は公式ドキュメントを参照してください。
Gitを使用して複数の機能を同時に処理する

PHPStormの使い方シリーズ

作業用フォルダを用意する

まず、今回作業を行うフォルダを用意します。
この記事では、ローカルリポジトリ上で作業を行います。

% cd ~/Desktop
% mkdir shelf
% cd shelf

ローカルリポジトリを作成します。

% git init
% ls -la

drwxr-xr-x@  3 mitsuoka-takahiro  staff   96  7 29 21:19 ./
drwx------@ 14 mitsuoka-takahiro  staff  448  7 29 21:16 ../
drwxr-xr-x   9 mitsuoka-takahiro  staff  288  7 29 21:19 .git/

.gitフォルダがあればOK。

PHPStormでGitツールウィンドウを表示する

View > Tool Windows > Gitから開くことができます。
ショートカットはデフォルトで⌘9に設定されています。

このような感じのウィンドウが開きます。

変更リストで変更をまとめる(Local Changes)

変更リストを利用すると、開発中のファイルをグループで管理することができます。
コミットも変更リスト単位で行うことができ、1つのコミットに含めるファイルを選択する手間を省くことができます。

準備

新しいファイルを3つ追加し、ステージングします。
ステージングするのは、バージョン管理対象ファイルでないとLocal Changesに表示されなからです。

% echo hello > a1.txt
% echo hello > a2.txt
% echo hello > b2.txt
% git add .

Gitツールウィンドウはこのようになっていると思います。

変更リストでまとめる

ここで、a1.txta2.txtを機能Aの資源と仮定して、変更リストでまとめてみます。
a1.txtを右クリックし、New Changelistを選択します。
変更リストの名前を聞かれるので、機能Aを追加するという意味でadd feature Aとしておきます。
(変更リストの名前はデフォルトのコミットメッセージとなるので、コミットメッセージを意識してつけておくのがオススメです)

新しい変更リストが作成されるので、a1.txta2.txtをドラッグして変更リストに追加します。

これで、変更リストadd feature Aa1.txta2.txtを追加することができました。

変更リスト単位でコミットする

⌘Kでコミットウィンドウを開きます。
デフォルトでは、b2.txtのみが表示されています。

ウィンドウ上部のChangelistからadd feature Aを選択します。

変更リストadd feature Aを選択したので、a1.txta2.txtが表示されました。
また、コミットメッセージにadd feature Aが表示されました。
このままコミットする場合は、右下のCommitボタンをクリックしてください。

変更リストのまとめ

変更リストを使うことで、開発中のファイルをグループ化して管理し、そのまま1つのコミットとすることができます。

PHPStormの使い方シリーズ

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

PHPStormのLocal ChangesとShelfの使い方メモ

はじめに

PHPStormのバージョン管理のヘルパー機能である、Local ChangesShelfの使い方メモです。

詳細は公式ドキュメントを参照してください。
Gitを使用して複数の機能を同時に処理する

作業用フォルダを用意する

まず、今回作業を行うフォルダを用意します。
この記事では、ローカルリポジトリ上で作業を行います。

% cd ~/Desktop
% mkdir shelf
% cd shelf

ローカルリポジトリを作成します。

% git init
% ls -la

drwxr-xr-x@  3 mitsuoka-takahiro  staff   96  7 29 21:19 ./
drwx------@ 14 mitsuoka-takahiro  staff  448  7 29 21:16 ../
drwxr-xr-x   9 mitsuoka-takahiro  staff  288  7 29 21:19 .git/

.gitフォルダがあればOK。

PHPStormでGitツールウィンドウを表示する

View > Tool Windows > Gitから開くことができます。
ショートカットはデフォルトで⌘9に設定されています。

このような感じのウィンドウが開きます。

変更リストで変更をまとめる(Local Changes)

変更リストを利用すると、開発中のファイルをグループで管理することができます。
コミットも変更リスト単位で行うことができ、1つのコミットに含めるファイルを選択する手間を省くことができます。

準備

新しいファイルを3つ追加し、ステージングします。
ステージングするのは、バージョン管理対象ファイルでないとLocal Changesに表示されないからです。

% echo hello > a1.txt
% echo hello > a2.txt
% echo hello > b2.txt
% git add .

Gitツールウィンドウはこのようになっていると思います。

変更リストでまとめる

ここで、a1.txta2.txtを機能Aの資源と仮定して、変更リストでまとめてみます。
a1.txtを右クリックし、New Changelistを選択します。
変更リストの名前を聞かれるので、機能Aを追加するという意味でadd feature Aとしておきます。
(変更リストの名前はデフォルトのコミットメッセージとなるので、コミットメッセージを意識してつけておくのがオススメです)

新しい変更リストが作成されるので、a1.txta2.txtをドラッグして変更リストに追加します。

これで、変更リストadd feature Aa1.txta2.txtを追加することができました。

変更リスト単位でコミットする

⌘Kでコミットウィンドウを開きます。
デフォルトでは、b2.txtのみが表示されています。

ウィンドウ上部のChangelistからadd feature Aを選択します。

変更リストadd feature Aを選択したので、a1.txta2.txtが表示されました。
また、コミットメッセージにadd feature Aが表示されました。
このままコミットする場合は、右下のCommitボタンをクリックしてください。

変更リストのまとめ

変更リストを使うことで、開発中のファイルをグループ化して管理し、そのまま1つのコミットとすることができます。

Shelfにしまう

後日アップデート

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

PHPStormのLocal Changesの使い方メモ

はじめに

PHPStormのバージョン管理のヘルパー機能である、Local ChangesShelfの使い方メモです。

詳細は公式ドキュメントを参照してください。
Gitを使用して複数の機能を同時に処理する

作業用フォルダを用意する

まず、今回作業を行うフォルダを用意します。
この記事では、ローカルリポジトリ上で作業を行います。

% cd ~/Desktop
% mkdir shelf
% cd shelf

ローカルリポジトリを作成します。

% git init
% ls -la

drwxr-xr-x@  3 mitsuoka-takahiro  staff   96  7 29 21:19 ./
drwx------@ 14 mitsuoka-takahiro  staff  448  7 29 21:16 ../
drwxr-xr-x   9 mitsuoka-takahiro  staff  288  7 29 21:19 .git/

.gitフォルダがあればOK。

PHPStormでGitツールウィンドウを表示する

View > Tool Windows > Gitから開くことができます。
ショートカットはデフォルトで⌘9に設定されています。

このような感じのウィンドウが開きます。

変更リストで変更をまとめる(Local Changes)

変更リストを利用すると、開発中のファイルをグループで管理することができます。
コミットも変更リスト単位で行うことができ、1つのコミットに含めるファイルを選択する手間を省くことができます。

準備

新しいファイルを3つ追加し、ステージングします。
ステージングするのは、バージョン管理対象ファイルでないとLocal Changesに表示されないからです。

% echo hello > a1.txt
% echo hello > a2.txt
% echo hello > b2.txt
% git add .

Gitツールウィンドウはこのようになっていると思います。

変更リストでまとめる

ここで、a1.txta2.txtを機能Aの資源と仮定して、変更リストでまとめてみます。
a1.txtを右クリックし、New Changelistを選択します。
変更リストの名前を聞かれるので、機能Aを追加するという意味でadd feature Aとしておきます。
(変更リストの名前はデフォルトのコミットメッセージとなるので、コミットメッセージを意識してつけておくのがオススメです)

新しい変更リストが作成されるので、a1.txta2.txtをドラッグして変更リストに追加します。

これで、変更リストadd feature Aa1.txta2.txtを追加することができました。

変更リスト単位でコミットする

⌘Kでコミットウィンドウを開きます。
デフォルトでは、b2.txtのみが表示されています。

ウィンドウ上部のChangelistからadd feature Aを選択します。

変更リストadd feature Aを選択したので、a1.txta2.txtが表示されました。
また、コミットメッセージにadd feature Aが表示されました。
このままコミットする場合は、右下のCommitボタンをクリックしてください。

変更リストのまとめ

変更リストを使うことで、開発中のファイルをグループ化して管理し、そのまま1つのコミットとすることができます。

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

Windows8上でPHPのメールが送信できない(Connection Closed Gracefully)

背景

 最近、バイト先で「ローカルネットワークで動いているサイトからGmailを使いたい」とお願いされて、こんな感じで環境を構築しました。そして、いざGメールを送信してみると、なぜか失敗してしまいます。
 自宅のWindows10のパソコンでは正常に動くのに、、、
色々見ると、XamppのSendmailフォルダにあるerror.logは

Connection Closed Gracefully

とばかり書かれています。つまり、Sendmailが正しく動作していないみたいですね。
でも、直訳すると

"接続は正常に閉じられました"

です。はぁ~(*´Д`)

このエラーコードを元に調査した結果、「Windows8がいけないらしい」とか、「Sendmailが使えない」、「stuunelをインストールすればいい」とかの記事がいくつか出てきました。以下の2つのサイトを試しましたが、だめでした。

【エラー解決方法】Windows8でxamppのsendMailが使えない!?を解決する方法

Windows8にXAMPPを配置してgmailをsendmailで送信

しかし、以下のstack overflowというサイトの英語質問&解答を試したら解決しました!

sendmail.exe opens on sending mail

解答者のYahya Uddinさん、ほんとに感謝しています!

※追記
公式ページにも書いてありました。
fake sendmail for windows

issues running on windows 8+
http://stackoverflow.com/q/21337859 details a workaround for this which involves running sendmail.exe in "windows xp sp 3" compatibility mode as administrator.

原因

 どうやら、バイト先のパソコン(Windows8)で動かす場合、Sendmailの権限の設定とかを少し変えてやる必要があるみたいです。

解決方法

 まず、XamppのSendmailフォルダにある「sendamail.ini」を右クリックします。

スクリーンショット (3).png
 そして、「プロパティ」を開いて、
スクリーンショット (4).png
 「互換性」タブの「すべてのユーザーの設定を変更」をクリックします(この時にパスワードを求められますので入力してください)
スクリーンショット (5).png
 そして「管理者としてこのプログラムを実行する」にチェックをして、
スクリーンショット (7).png
 「互換モード」をWindows7から「Windows XP (Service Pack 3)」に変更します。
スクリーンショット (9).png
 最後に「適用」をクリックして終了です。
スクリーンショット (10).png
一応Apacheの再起動をしてPHPのメール送信をしてみてください。解決するかもしれません。

最後に

 このエラーにだいたい5時間くらいとられました。お金にしてだいたい6000円ですね。もったいない。全然記事が無いので、気づくのに時間がかかりました。結果、英語の記事に答えがありましたねw
もっと英語勉強しなきゃ。。。

それでは!

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

古のエンジニアがlaravelを初めて触って習熟していく流れで、とても参考になった記事まとめ

経緯

普段はフロントエンド、vueやnuxtの開発を中心にやっています。今回はバックエンドも含めて開発する案件を受注したことをきっかけに、最近流行ってるlaravelでバックエンドを作ってみるか、ということになりました。

もともと、LAMP環境の構築やphp,mysqlは経験がある古のエンジニアです。
以前は素のphp+mysqlでフレームワークを使わずゴリゴリ書いていました。

開発環境はlinux(CentOS)をベアメタルサーバーにインストールして、phpやmysqlをソースからインストールしたりして使う、そういう時代のエンジニアです。HTTPサーバーといえばapacheでしょ?という時代から、最近のAWSは便利だよね〜という時代を生きてきた人です。

ちなみにデータセンターにオンプレミス環境を構築して月間数億PVのアクセスがあるソシャゲの開発運用とかを一人でやったりしていました。AWSに移行してからはRDSの負荷分散のためmemcachedサーバーにキャッシュレイヤーを作ったり、懐かしい。

話はそれてしまいましたが、最近はフロントエンド中心の開発案件をやっています。
バックエンドとのやり取りはAPIでやることが主流の時代になってきました。

久しぶりにバックエンド作るので、最新のモダンで人気なフレームワークをいっちょやってやるか!と思い人気のlaravelに目をつけたわけです。

laravelを選んだ理由

  1. 日本語で書かれたドキュメントやサンプルが多い
  2. AWSとの連携が組み込み済み
  3. API用のレイヤーが標準装備
  4. Model経由でのDBとの密な連携

この辺です。テーブル作成はphpmyadminで、PHPの中にSQLを直書きしていた私からすると、アプリケーション内からModelでDBと密接に結合しているのは新鮮です。

フロントエンドとはAPIで連携するので、その辺の機能も標準装備していることに魅力を感じました。

開発環境構築

https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4

Laravel環境構築はこちらの神リポジトリをcloneしてdockerで一発です。すごい便利な時代になったものですなぁ、昔はLinuxのインスト(ry

laravelのtableを作ってみて、表示させてみる

えっ!DBのテーブルってphpmyadminでチマチマ作るんじゃないんですか?

なるほど、作成、変更履歴も残せるマイグレーションと言うのがあるのか…

https://noumenon-th.net/programming/2020/01/15/laravel-mysql/

larvel passportでAPI認証のバックエンド側基本を作る→やめた

シンプルなjwtに切り替えました。

https://www.whizz-tech.co.jp/1442/

composer dumpautoloadってなんだ?

おかしくなったときはこれ。でもあまり使わない。

https://qiita.com/WebSysRider/items/e41f211f8c913e008d03

laravel上でvueベースの認証画面を作る

基本のapiのやりとり。

https://www.whizz-tech.co.jp/1453/

nodeが無いと言われたのでこちらでDockerを再構築

https://zukucode.com/2019/06/docker-laravel-nodejs.html

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

npm run devが抜けていたため、以下のファイルが見つからんかった

/css/app.css 178 KiB /js/app [emitted] /js/app
/js/app.js 1.4 MiB /js/app [emitted] /js/app

再度アクセスするとうまくいった

Personal access client not found. Please create one. エラーがでる

php artisan passport:client --personal

上記コマンドならうまくいく、

その後webで再度やるとうまく行った。なんでや?

これが回答かな?
https://stackoverflow.com/questions/56249565/why-we-have-to-create-personal-access-client-in-passport-again-and-again

makefileのinitに以下のコマンドを追加した→削除

docker-compose exec app php artisan passport:install

laravelのアクセスがやったら重いんですけど

Docker for Mac限定の問題。
色々試しましたけど、最終的には直接php artisan serveすることで解決。

dockerのvolumeのマウントが原因。 :delegatedをつけたら少し軽くなった。

https://wonwon-eater.com/mac-docker-performance/

/api/userにアクセスしてもなにも起こらない

忘れがち

なお、JSONが返されるのはLaravel5.3のデフォルトではヘッダーにX-Requested-With: XMLHttpRequestがある、またはAcceptヘッダーでjsonが指定されている場合です。(fetchにネイティブ対応しているブラウザではそれを使用した場合明示的にAcceptを指定してやらないと前者の対象にはならずにリダイレクトが発生し200になります。宇宙。)
https://blog.hinaloe.net/2016/09/15/try-passport-laravel-5-3/

Acceptヘッダとauth Bearerヘッダを追加して再確認、うまくいった。

よく考えたら、backendフォルダ内で直接laravel動かしたらいいんじゃね?

→動いた。ローカルなので応答も早い。
DBの接続情報を変更する必要がある。Dockerコンテナは環境変数を変更しているため。

DB_DATABASE=laravel_local
DB_USERNAME=phper
DB_PASSWORD=secret

.envの更新を反映させるにはコマンドが必要

php artisan cache:clear
php artisan config:cache

passportやめたい

composer.jsonを編集して composer update

https://ja.coder.work/so/laravel/545565

認証APIをjwtで作り直し

参考
https://re-engines.com/2019/06/03/laravelで認証apiを作る/
うごかないなんでや
https://github.com/tymondesigns/jwt-auth/issues/1484

replace
'expires_in' => auth()->factory()->getTTL() * 60
by
'expires_in' => auth('api')->factory()->getTTL() * 60

うごいた。ここでtokenの有効期限も設定できるっぽい

認証APIにregisterを移植した

バリデーションも合わせて実装した

userのcrudをAPIで実装する

参考
https://qiita.com/sutara79/items/cd4371b246b44a2cf87f

putのrequestが空っぽなんなんでや??

postmanの設定だった

https://qiita.com/wjtnk/items/eb2ddcc0642dc3197671

PUT時にuserが見つからない場合に出るModelNotFoundExceptionエラーをカスタマイズする

abortの第一引数にresponceを渡さないとstach traceが出るみたいだぞ?

https://laraveldaily.com/laravel-api-404-response-return-json-instead-of-webpage-error/

その他、細かく設定する場合
https://qiita.com/sakuraya/items/af38c4cf84459a8b5967

基本形

Handler.php
    public function render($request, Throwable $exception)
    {
        if ($exception instanceof ModelNotFoundException) 
        {
          abort(response()->json(['message' => 'not found'], 404));
        }
        return parent::render($request, $exception);
    }

コードフォーマッタとリンターがないので入れる

https://www.ritolab.com/entry/188#aj_3

開発用のメールサーバー

ブラックホールメールサーバーのDockerコンテナを開発用に立てる
http://127.0.0.1:1080 で送信したメールが全部見れる。なんて便利な世の中や・・

https://qiita.com/kanemu/items/1f2da063c7e5b5477502

seederでダミーデータを適当に作る。マスタデータも作れる。

https://qiita.com/shosho/items/b69db263a494edfe3b21

Route::resources で全部使わないよ!って場合

https://qiita.com/sympe/items/9297f41d5f7a9d91aa11

もはや個別にmodel,controllerとか作らなくても良くない?全部まとめて作れるで

https://qiita.com/niisan-tokyo/items/9c799989cb535489f201

管理画面をlaravel-adminで作る

https://laravel-admin.org/docs/#/
https://tac-blog.tech/index.php/2018/09/29/laravel-admin-add-crud/

管理設定をmigrationできるようにseederに追加する

https://qiita.com/ntm718/items/5ea29ee70b50320352c4

基本のDBクエリビルド

https://www.ritolab.com/entry/93#aj_11_1

Laravel debaggerを入れる

https://qiita.com/sutara79/items/9fd442a81001842aeba1

apiResource

https://www.webopixel.net/php/1526.html

純粋なAPIで使用するCRUDの場合はapiResourceを使用します。
Route::apiResource('users', 'UsersController');
これで、index,store,show,update,destroyが使用できるようになります。
複数のコントローラーをまとめて指定する場合はapiResourcesを使用します。
Route::apiResources([
'tasks' => 'Api\TaskController',
'users' => 'Api\UserController'
]);

api用のデータ整形、リレーションデータの追加。

https://yuhodev.hatenablog.com/entry/2019/11/27/121500

apiCollectionの作成

php artisan make:resource UserCollection
php artisan make:resource User

JsonResouseに追加したい

    public function toArray($request)
    {
        $data = parent::toArray($request);

        $data["staff"] = StaffResource::collection($this->staff);
        $data["doctor"] = DoctorResource::collection($this->doctor);

        return $data;

    }

apiのセキュリティ 自分のデータ以外は編集できてはいけない

Policyの設定を行う。

https://nakka-k.hatenablog.com/entry/2019/06/07/140758

$this->authorize('update', $user);

APIで返却するJSONを共通フォーマットにしたい

https://waterfalls.hatenablog.com/entry/2019/08/24/012913

Modelでバリデーションをする

https://qiita.com/kd9951/items/c06d107aa4018295aa25

中間テーブルを通した多対多リレーション

https://php-junkie.net/framework/laravel/many_to_many/

Tips: primarykeyを使わない場合
https://www.yuulinux.tokyo/15552/#i-5

多対多リレーション時のデータ修正・追加

例えばusers-> user_role -> roles というふうに
中間テーブルを経由してroleを管理している場合、roleを変更したい場合は

roleテーブルのidを配列で渡すだけで良い
roles = [1,2,3]

$user->roles()->sync($request->roles);

神か!!!

https://nextat.co.jp/staff/archives/200

この辺から自力で調べつつ、公式リファレンスを読めば大体構築イメージがつかめるようになってきました。

概ね3日でLaravelの基本は理解できたと言えます。
素晴らしいフレームワークですが、レイヤーも多いため、基本のSQLの知識も必要、PHPの基礎も。

やっぱ基礎って大事だな、と思いました。

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

PHPで大容量CSV書き出しを高速で処理する

CSVエクスポートでLaravelが用意するStorageクラスでファイル作成してループして1行ずつ書き込みすると無茶苦茶重いというか時間がかかったのでもっと早く出来ないかと調べた結果をメモ。

参考サイト

【PHP】大量データをfputcsvで瞬時にCSVファイル出力する方法

環境

FW: Laravel 6.x
PHP: 7

どのぐらい早いか

条件

レコード数: 50,000件
テーブルデータサイズ : 5.4MB
※PCのスペックとかもあるだろうけど、開発環境はDocker for Mac使っています。

結果

実行時間1回目: 16.8 sec
実行時間2回目: 25.2 sec

サンプルコード

UserController.php
public function export() {
    $users = new App\User::all();

    $filePath = storage_path(sprintf('app/%s.csv', date('ymd_hisu')));

    $stream = fopen('php://temp', 'w');

    $header = $users->first()->getFillable();
    mb_convert_variables('SJIS-win', 'UTF-8', $header);
    fputcsv($stream, $header);

    foreach ($users as $user) {
        $line = $user->toArray();
        mb_convert_variables('SJIS-win', 'UTF-8', $line);
        fputcsv($stream, $line);
    }

    rewind($stream);
    $content = stream_get_contents($stream);
    file_put_contents($filePath, $content);
    fclose($stream);

    return response()
            ->download($filePath, sprintf('サンプル%s.csv', now()->format('YmdHis')))
            ->deleteFileAfterSend();
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntu18.04に超速でLumenを入れたい

phpのインストール

sudo apt install php

・php -v

PHP 7.2.24-0ubuntu0.18.04.6 (cli) (built: May 26 2020 13:09:11) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.24-0ubuntu0.18.04.6, Copyright (c) 1999-2018, by Zend Technologies

こだわりが無いのでOS標準のリポジトリのものです。

Composerのインストール(PHPのパッケージ管理ソフトみたいなやつ)

sudo apt install composer

$ composer -V
Composer 1.6.3 2018-01-31 16:28:17

php-zipのインストール

sudo apt install php-zip
※これがないとLumen-installerで解凍できないって怒られる。

php-unitのインストール

sudo apt install phpunit
※これがないと「composer create-project laravel/lumen」でプロジェクト作るときにコケます。

Lumenのインストール

composer global require "laravel/lumen-installer"

パスを通す(これをしないとlumenコマンドが使えません。)

echo 'export PATH=$HOME/.config/composer/vendor/bin:$PATH' >> ~/.bashrc

$ lumen -V
Lumen Installer 1.3.0

プロジェクトを作ってみる(testapi)

$ composer create-project laravel/lumen

(省略)
phpunit/phpunit suggests installing ext-xdebug (*)
Writing lock file
Generating optimized autoload files
$ php artisan -V
Laravel Framework Lumen (7.2.1) (Laravel Components ^7.0)

入ったっぽい。

lumen new では?

$ lumen new testapi

In NewCommand.php line 39:

  The Lumen installer requires PHP 7.3.0 or greater. Please use "composer create-project l
  aravel/lumen" instead.

PHP7.3以上って怒られてしまった…。

とにかく起動したい

php -S 0.0.0.0:5000 -t public
これでデバックモードみたいなものが起動する。(停止はCtrl+C)
ポートはいくつでもOK。(とりあえず5000で受付する)

これでブラウザ立ち上げて、
http://127.0.0.1:5000 もしくはhttp://localhost:5000にアクセス。

そうするとLumenのバージョンだけが表示される。
Apacheに噛ませたりするのはまだわからないけど、ここから弄り倒すのだ。


まだ18.04使ってるわけですが、そろそろ20.04にしようかな。。。

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

PHPで指定桁数の最大値を取得する

もっとスマートな書き方がある気がしているので、ご教示いただきたいです。
→ (2020/07/30) コメント頂いたので、追記させていただきました!

指定桁数の最大値を取得

  • ※ 整数のみ対応
  • PHP_INT_MAXを超える桁数を$lengthに指定しないこと!

A1: str_repeat()を使う

$length = 6; // 6桁
$max = (int)str_repeat(9, $length); // 999999

A2: 累乗する

@vf8974 さんからコメント頂きました。確かにこちらの方が考え方がスマートです。

$max = 10 ** $length - 1;

注意点

当たり前なんですが、桁数$lengthに100など大きい桁を入れるとオーバーフローしますので、PHP_INT_MAX を超えない桁を指定して下さい。
https://www.php.net/manual/ja/language.types.integer.php#language.types.integer.overflow

integer型の範囲外の数を指定した場合、かわりに floatとして解釈されます。また、結果が integer型の範囲外の数となるような計算を行> うと floatが代わりに返されます。

もしそれより大きい桁が欲しいときは、string型で取得するしかありません。

$length = 30; // 30桁
$max = str_repeat(9, $length); // string(30) "999999999999999999999999999999"

(応用) 指定桁数までのランダムな整数値を取得

$rand_int = random_int(1, $max);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】モデルから配列やJsonにキャスト時、必要な属性だけ表示させる

モデルのキャスト時に、パスワードなど表示したくない属性がある。
反対に、表示したい属性のみを指定したいときもある。
その時はモデルのプロパティの$hiddenもしくは$visibleを使えばOK

User.php
protected $hidden = [
    'password'
];

役割

プロパティ 役割
$hidden 登録項目は JSON に含めない。
$visible 登録項目は JSON に含める。

場合によって使い分けましょう

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

Debugbar をインストール

Debugbarを使う。

まずは、Debugbarをインストールします。

$ composer require --dev barryvdh/laravel-debugbar

次にDebugbarの設定ファイルを作成します。

$ php artisan vendor:publish --provider="Barryvdh\Debugbar\ServiceProvider"

ここで作成された環境設定ファイル「.env」に、設定情報を記載します。

以下のいずれかを追記する。

DEBUGBAR_ENABLED=null  # デフォルト。APP_DEBUGに応じて決まる
DEBUGBAR_ENABLED=true  # 必ず有効
DEBUGBAR_ENABLED=false # 必ず無効

これでデバッグを行う準備ができました。
デバッグしたい場所に次のコードを記述すればデバッグすることができます。

 \Debugbar::info(確認したい変数など);

これでOKです!

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

【PHP】ChatworkAPIを用いてファイルを送信する

// Chatworkの送信先ルームID
$room_id = '000000';

// APIトークン
$api_token = '*********';

// ファイルの設定
$file = new CURLFile('./file.xml', 'text/xml', 'filename.xml');
    // Laravelの場合
    // $file = new \CURLFile('./file.xml', 'text/xml', 'filename.xml');

// メッセージの設定
$message = 'メッセージ';

$options = array(
    CURLOPT_URL => 'https://api.chatwork.com/v2/rooms/'.$room_id.'/files',
    CURLOPT_HTTPHEADER => [
        'X-ChatWorkToken: '. $api_token,
        'Content-Type: multipart/form-data'
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'message' => $message,
        'file' => $file,
    ],
);

$ch = curl_init();
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
curl_close($ch);

参照
https://developer.chatwork.com/ja/endpoint_rooms.html#POST-rooms-room_id-files

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

Laravel クエリビルダを用いてNULLを判定する

目的

  • クエリビルダを用いたNULLの判定方法をまとめる

実施環境

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

前提環境

  • 先に記載した実施環境に近い環境で実施すること。

前提情報

読後感

  • NULLを用いた条件を使ってクエリビルダでデータの取得をすることができる様になる。

  • 判定対象カラムがNULLであるレコードのみ取得する。

    $query = モデルファイル名::select('*');
    $query->whereNull('判定対象カラム名');
    $query->get();
    
  • 判定対象カラムがNULLではないレコードのみ取得する。

    $query = モデルファイル名::select('*');
    $query->whereNotNull('判定対象カラム名');
    $query->get();
    

具体例

  • usersテーブルの「user_name」カラムがNULLのレコードのみ取得する際は下記の様になる。
  • usersテーブルのモデルファイル名はUser.phpとして、アプリ名ディレクトリ/app直下に存在するものとする。当該モデルファイルのuse宣言はすでに実施されている物とする。

    $query = User::select('*');
    $query->whereNull('user_name');
    $query->get();
    
  • usersテーブルの「user_name」カラムがNULLではないレコードのみ取得する際は下記の様になる。

  • usersテーブルのモデルファイル名はUser.phpとして、アプリ名ディレクトリ/app直下に存在するものとする。当該モデルファイルのuse宣言はすでに実施されている物とする。

    $query = User::select('*');
    $query->whereNotNull('user_name');
    $query->get();
    

参考文献

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

composer"Updating dependencies (including require-dev)"で固まり困っている人へ

//駄文を許してください
//筆者はcomposerコマンドを使ってプロジェクトを作成しています

mac ver 10.15.6
composer ver 1.10.9

ことの発端は...

とある日,laravelを楽しもうとプロジェクトを作成した時であった...

何分待ってもprojectが作成されないのである。

Creating a "laravel/laravel" project at "----" <-ここで固まる

updating dependencies <-composer updateしていた時はここで

行動

phpやnodeなど手当たりしだいにアップデート->効果なし

composerのコマンドを打ったときの挙動だけがおかしいことに気づく

composerのアンインストールを考えたができなかった...

解決への道

参考

https://iiiso.ti-da.net/e8647248.html
https://stackoverflow.com/questions/17138319/composer-freezing-when-installing-symfony-vendors
https://github.com/composer/composer/issues/4839

公開鍵

https://composer.github.io/pubkeys.html

言われた通りに、diagnoseをコマンドの尻に付けてみる
->どうやら同じような症状である.

composer self-update --update-keys

を打ち,公開鍵をコピペしてみる.

その後、composerコマンドが通常通りに使えるようになった.
実際のところなぜこのような問題が起こったのか不明であり本質的には何が起こったのか不明であるため原因究明に力を注ぐ。

細かなこと

  • 初めて記事を制作したので細かなミスがあっても許してください
  • 解決?後再度プロジェクトを作成してみると、ターミナル上では余り変化がないので10分程度待ってみましょう.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む