20190413のPHPに関する記事は14件です。

php-master-changes 2019-04-12

今日は gcc のバグ回避、opcache のファイルキャッシュに関するバグ修正の 7.2 系以降へのバックポート、オブジェクトの new に関する処理のリファクタリング、コールフレーム初期化の修正の 7.4 系へのバックポート、テストの並列実行対策、Travis の設定で travis_wait を利用するようにする修正、mb_convert_encoding() のメモリリーク修正、各所のコンパイラ警告潰し、リリースビルドでも gcc で -Wall を付けるようにする修正、pdo_pgsql でテストの期待出力を英語じゃない版を考慮しての修正、pgsql で Windows 版でも libpq-fs.h を include するようにする修正、get_cfg_var() で ini の配列エントリにアクセスするテストの追加、iconv の怪しい最適化コードの修正、pgsql での無駄に複雑だった処理の修正があった!

2019-04-12

nikic: Work around -Walloc-size-larger-than bug

weltling: Fix potential OPcache file cache related issues

dstogov: Added test

dstogov: Replace "ZEND_CALL_CTOR" hack by additional live-range

dstogov: Backported call frame initialization improvement

nikic: Avoid directory clash in realpath tests

nikic: Run compile step under travis_wait

nikic: Use EMPTY_SWITCH_DEFAULT_CASE in php_unicode.c

nikic: Fix key leaks in mb_convert_encoding()

nikic: Mark zend_bailout() as a noreturn function

nikic: Fix uninitializde heredoc_tag use in readline

nikic: Avoid potentially-uninitialized warnings in readline

nikic: Regroup expressions in php_schema.c to avoid array bounds warnings

nikic: Fix potentially uninitialized warnings in phpdbg

nikic: Remove odd variable assignment in escape_analysis

nikic: Fix unused variable warnings in libmagic

nikic: Enable -Wall on release builds for GCC

nikic: Fix SOAP bailout handling

cmb69: Fix tests wrt. internationalization

cmb69: Include libpq-fs.h on Windows, too

nikic: Avoid unitialized variable warning in soap

nikic: Add test for get_cfg_var with array variable

nikic: Avoid uninitialized variable warnings in gmp

nikic: Avoid misc uninitialized variable warnings

nikic: Avoid uninit warning in dtoa

nikic: Avoid uninit warnin in http_fopen_wrapper

nikic: Remove dubious memcmp optimization in iconv

nikic: Avoid uninit warning in ftp

nikic: Fix uninit warning in gd.c

nikic: Don't use php_strtok_r in build_tablename

nikic: Fix strict aliasing violation in phpdbg

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

【Symfony4】PHPフレームワークの初期設定

こんにちは。
イエノカドです。
今日は今更ですが、忘れてしまうこともあるので
Symfony4.2で初期画面を表示させるまでをやってみました。

Symfonyとは

  • PHP上で動作するフレームワーク
  • EC-CUBEでも採用されているフレームワーク
  • 個人的にはLaravelより使いやすい印象

環境

  • windows 10 pro
  • Docker Quickstart Terminal
  • PHP 7.3.3(PHPのインストール設定は省きます)
  • composer 1.8.5

目次

  • Composerのインストール
  • Symfonyのインストール
  • 結果
  • まとめ

Composerのインストール

cd /c/php

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"

Symfonyのインストール

symfony用のディレクトリを作成

$ mkdir /c/workspace/symfony_sample

先ほどインストールしたcomposer.pharを移動

$ mv /c/php/composer.phar /c/workspace/symfony_sample/composer.phar

symfony4をインストール

$ php composer.phar create-project symfony/website-skeleton my-project

インストール完了後に移動

$ cd my-project/

symfony4を起動させるためにphpでサーバ立ち上げ

$ php bin/console server:run

結果

http://localhost:8000/ にアクセス

image.png

まとめ

  • composer インストールからSymfony初期画面表示まで5分程度でできました。
  • ここからControllerやEntityやらRoutingなど設定していき、何か処理を作っていかないといけないので、ここからです。

出典

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

平成最後はじめてのWebサービスを作った

大学4年の春、就職活動をはじめて1次面接を5社くらい落ちたところでなんとなくはじめてWebサービスを作りたくなったのでhtmlもcssもJavaScriptもPHPもろくにわからない状態で0から独学で勉強をし1ヶ月弱で「Ash00le.Tk」というwebサービスを作ってみました。

top

なにができるのか

エロ動画を探してお気に入り

Fanza(旧DMM)、Avgle、Pornhub、Redtube、Youpornなど有名どころからエロ動画を引っ張ってきてランダムに表示します。お気に入りの動画があればお気に入りすることでマイページからいつでも見ることができます。キーワードで検索することもできます。

URLから保存する。

GoogleやTwitter、Facebookで自分好みのエロ動画を見つけたときにURLを入力することで保存をし、同じようにマイページでいつでも見ることができます。

どんなキーワードで検索されてるのか見る。

どんなキーワードで他のユーザーが検索したかを見ることができます。

他のユーザーがお気に入りした動画を見れる。

他のユーザーがどんな動画をお気に入りにしたか見ることができます。

なんで作ろうと思ったか

ふとしたときに「エロ動画さがすのってめんどくせーな」と思い、できるだけ効率的にエロ動画を探したいと思ったことがきっかけです。
また、どこかの記事で「日本人はポルノが大好きで、本名や顔を公開するのを躊躇う、ITリテラシーが低い」というのを見て「これだ!!」と思いこれらの要素をできるだけ詰め込んだWebサービスを作ろうと思いました。

サービスの名前に意味はない

Ash00le.Tkに特に意味はないです。適当です。
Ash00leっていうのは「asshole」をもじったものです。

HTML,CSS

Bootstrap4を利用しテンプレートも利用しています。正直いまいちわかってない部分もあるのでこれからも勉強が必要です。

なんでPHPか?

いろいろなWebサービスを見ているとわりとRuby on Railsを使っていると思います。なので普通に考えたらRubyがいいのかなと思ったんですが、そもそも今までhtmlやcssすらろくに使ったことない自分はフレームワークもまったくわかってなかったので「なにか1つのものを作るのにものすごい時間がかかる」と思い、とりあえずPHPを選びました。というのも個人的にRubyを使うのはRailsありきだと思っているのでフレームワークもしらないやつがRuby使ってもしょうがないと思ったからです。違ったら教えてください。
フレームワークに関しては「必要になったら使お」くらいの気持ちでした。
大学ではJavaをメインに使っていたので最初はPHPに戸惑いましたが慣れたら簡単に書けていいと思いました。

問題点

1. 著作権、商標権の問題

サイト内で当たり前のようにFanzaやPornhubなど有名な海外サイトのロゴ画像を利用しています。著作権、商標権的にアウトなんじゃないかと思いましたが

僕は、”比較口コミサイト”での、ロゴやブランド名の掲載、という部分では、”商標権侵害”に当たるかどうかは、消極的な意見です。なぜなら、商標というのは、そのロゴ等の掲載により”顧客吸引力”が発揮されているかどうか、が大切なポイントだと思うから(≒消費者が、そのロゴを目印に買い物をするかどうか)。比較サイトは、決して、掲載ロゴの1つを見て、”あ、このサイトは、○○というロゴの企業が運営しているのね”とは、消費者も勘違いしないでしょ?

これ読む限りでは別にいいんじゃないかと思いましたがよくわからないのでよく調べます。

2. セキュリティ

クロスサイトスクリプティングやクロスサイトリクエストフォージェリ、SQLインジェクション、クリックジャッキングなど有名な攻撃に関しては簡単に対策をしているつもりです。またクロスサイトリクエストフォージェリに関してGETも対策する必要があるのかないのかいまいちわからないです。GETはキーワード検索とページ指定にしか使っていないのでなんとなくいらない気がしてますが、浅はかな考えだと思うのでよく調べます。

どこかで「簡単にwebサービスを公開するな」みたいな記事を読みましたが、なにごとも経験だと思ったのでリスクを承知でフレームワークは理解が追いつくまで使わずに調べながら自分で実装しました。

Ajaxにおけるクロスサイトリクエストフォージェリ

「Twitterはセッション単位でトークンを使いまわしている」という記事を読んだので今の段階ではセッション単位でトークンを使いまわしています。ただ、その記事自体が3年以上前であることと、自分がTwitterのソースコードみた限りでは更新するたびにトークンが変わっているように見えました。なのでセキュリティ的に問題があるのではないかなと思ったのですがよくわからないのでよく調べます

これからの課題

1. フレームワークを使う

セキュリティの問題においてもフレームワークを利用したほうがいいのはわかっているので勉強をして移行させたいです。フレームワークを使わない実装は「脆弱性の温床」らしいので1秒でもはやく実装したいです。

2. テンプレートエンジンの必要性がいまいちわかってない

勉強不足のせいですべてinclude関数で済みそうって思ってしまっています。

これからやりたいこと

ユーザーページを作る。

いまいち理解してない部分はありますが、フレームワークのルーティング処理を利用すれば簡単に実装できると思っています。Slim3のような軽量フレームワークにするか、いきなりLaravelに手を出すか迷っているところです。フレームワークについてわかっていない部分があるのでまずはSlim3で基本的なことを簡単におおまかに理解するのも手だなと思っています。

ユーザーが好みの動画を推測する。

ポルノサイトのAPIではタグやカテゴリーが指定できるので、お気に入りしたエロ動画のタグを保存しておくことで、ある程度その人のお気に入りの傾向がわかり簡単に推測できるのではないかと思います。
また、保存したエロ動画のサムネイルを学習させて他のユーザーが保存しているエロ動画のサムネイルから類似しているサムネイルを出力してみるのは面白いかなと思います。しかしPHPでは機械学習のライブラリがあまりないので多層パーセプトロンならまだしも本格的にやろうとするとPython使わなきゃいけないのかなと思います。ただ学習データがないとできないので実装したからといってすぐに利用できるものではないかなと思います。

JavaScriptを勉強する。

UI・UXを高めるのはJavascriptは欠かせないものだと思います。しかしまだまだ勉強不足なので「おそらくJavascriptで実装できるんだろうけどどうやるのかわからない」ことが多いのでこれからも勉強したいと思います。

まとめ

おそらくいろいろな問題があると思いますが、はじめてのWebサービスということでお手柔らかによろしくおねがいします。

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

PHPのPassword_hash関数をcrypt関数で再現する(メモ)

PHPのpassword_hashを詳しくみる

PHPのpassword_hash関数の暗号化アルゴリズムがblowfishというのはPHPerなら誰でも知っていると思います。
その詳細を調べたらパスワードごとにsaltを個別に持つことが可能でかつ、DB内に個別にsalt用カラムを保つ必要がないということをマニュアルを読んで知ったのメモ。

$hoge = "password";
$hash = password_hash($hoge, PASSWORD_BCRYPT);
// 暗号化されたパスワード:$2y$10$FCcP.mohAJhrvV0LeAgExutz.wPmInQ9R3Pme89QBVnJmujpZ4Ygi

if (password_verify($hoge, $hash)) {
    echo("認証");
}

本来であれば、何も迷わずpassword_hashを使えばいいのでしょうけど、
crypt関数でも代用可能だと知ってちょっとためしてみました。

$hoge = "password";
$algo = '$2a$04$dummysalt/upto22characters';
$hash = crypt($hoge, $algo);
// $2a$04$dummysalt/upto22charaOlqk5u.LapVt7D9UokdVw2kezh9.edIq

// blowfishのsalt形式は3つ目の$を含めた以降の文字列のサイズが22byteであることが
// 仕様であるため、23文字目以降はむしされる模様。
// つまり、暗号化された文字列を第二引数に渡すことで同じhash値を計算することができる
// という仕様のようです。
if(crypt($hoge, $hash) === $hash) {
   echo ("認証");
}

blowfishで暗号化するためには規定のSALT形式があるのでその仕様をみると

blowfish salt形式のフォーマット

CRYPT_BLOWFISH - Blowfish ハッシュ。salt の形式は、 "$2a$" か "$2x$" あるいは
"$2y$"、2 桁のコストパラメータ、"$"、そして文字 "./0-9A-Za-z" からなる 22 文字と
なります。
この範囲外の文字を salt に使うと、crypt() は長さゼロの文字列を返します。 
2 桁のコストパラメータは反復回数の 2 を底とする対数で、 これは Blowfish 
ベースのハッシュアルゴリズムで使います。 この値は 04 から 31 までの範囲でなければならず、
それ以外の値の場合は crypt() は失敗します。 
5.3.7 までのバージョンの PHP では、salt のプレフィックスとして "$2a$" だけしか使えませんでした。
PHP 5.3.7 で新たなプレフィックスが導入され、 Blowfish の実装にあった
セキュリティ上の弱点に対応しました。
セキュリティ修正の対応の詳細については » この文書 を参照ください。
簡単にまとめると、PHP 5.3.7 以降しか使わないのなら "$2a$" ではなく "$2y$" を
使うべきだということです。

この仕様に則ってsaltをいろいろと変更してみましたが、
\$(2a)\$(04)\$とある(04)のコストパラメータをマックスの31にするとまったく計算が
完了せず使い物になりませんでした。
よっぽどの強固な暗号が必要で無い限りということでしょうけど、こんなに戻り値が
帰ってこないのに、使う場面あるの?とも思いましたが。
やはり、最小の04でやるとすんなり計算がおわるので、特に考えずに04を使っていこうと
思いました。

さて、このcrypt関数で作成したハッシュ値もpassword_verify関数に渡してやることで
パスワードの成否を検証することができるようです。

$hoge = "password";
$algo = '$2a$04$dummysalt/upto22characters';
$hash = crypt($hoge, $algo);

if(password_verify($hoge, $hash)) {
    echo ("true");
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelでのBrowsersyncを理解して外部開発WebサーバーにあるSSLのLaravelプロジェクトでも自動リロードを実現したい!

各自におかれましてはLaravelで本日もごにょごにょ楽しんでおられることと思い、嬉しく思います。
最近はLaravelを納品に使うことも増えましたので気持ち良い開発環境を構築したい今日このごろです。
さて、今回はファイル変更を検知してブラウザの自動リロードをしたいです。
私の環境ではちょっとしたコツが要りましたのでまとめ。
公式ドキュメントを詳らかに読んだわけではないので、とりあえず、こうやったらうまく動くよ、という記事となります。

公式ドキュメント
https://browsersync.io/docs/options

環境

下記環境で確認しています

  • Laravelプロジェクトは自マシンではなく、外部の開発サーバーに存在
  • 開発サーバーでは本番同等にphp-fpmなどを使ってWebサーバー経由でプロジェクトを配信
  • 開発サーバーでは本番同等に常時SSL化している

開発サーバーというよりステージングサーバーに近い環境です。
私は自マシンを信用していないのでバックアップスクリプトも走っている開発サーバーで作業することが多いです(客のチェックもリアルタイムにできるのでプロジェクトも進めやすい)。
自マシンでやる場合はもうすでに他の方の記事があるのでGoogle検索してください。ただし、この記事を読めばわりと柔軟に対応できると思います。まずLaravelをBrowsersyncなしで動作させ、それにappendでBrowsersyncをくっつけるイメージでいけばだいたいなんとかなります。

Browsersyncとは

Laravelを標準的にインストールしたら一緒に入ってくるファイル変更検知で自動ブラウザリロードの仕組みです。

LaravelプロジェクトでBrowsersyncを使ったリクエストをさばく仕組み

Browersyncは下記のような動作でリクエストをさばきます。

リクエストをインターセプト

BrowserSyncはListenしているhost、portでリクエストをインターセプトします。

proxy配下へリクエストをバケツリレー、なんか付加してブラウザへレスポンスを返却

  • proxy配下へリクエスト内容をバケツリレーします(ここがProxyのこと)
  • 配下から返却をBrowserSyncが取得
  • BrowserSyncはリロードの仕組みを返却に付与
  • レスポンスをブラウザへ返却

自動リロードの仕組み

わかれば簡単なのですが下記の動きをします。(前項にてサーバー側からブラウザへ命令を送信できる仕組みができています。)

チェック設定のファイルの変更を検知

設定ファイルのfilesに設定した内容でファイルシステムの変更をチェックします。

変更があればブラウザリロード命令を発行

  • レスポンスに付与した仕組みを使ってブラウザへリロード命令を送ります。
  • ブラウザは画面のリロードを実行

やったね。

実際の設定/コマンド

実際の設定/コマンドは下記となります。

webpack.mix.jsの内容

最小構成で下記となります。

mix.js('resources/js/app.js', 'public/js') // ただのmixだな
   .sass('resources/sass/app.scss', 'public/css') // ただのmixだな
   .browserSync({ // ここから
     proxy: {
        target: "http[s]://あなたのLaravelプロジェクトトップへアクセスできるURL" // 最後に/は不要
     },
     https: true, // httpsのサイトをproxyするならtrueをセット
     files: [ // チェックするファイルは下記で十分ではないかな。
       './resources/**/*',
       './app/**/*',
       './config/**/*',
       './routes/**/*',
       './public/**/*'
     ],
     open: false, //BrowserSync起動時にブラウザを開かない
     reloadOnRestart: true //BrowserSync起動時にブラウザにリロード命令おくる
});
  • proxy.targetのURLがhttpsのサイトの場合はhttpstrueにしてください
  • filesに'./*/'とかしているとファイル多すぎてBrowsersyncが落ちます

設定(Firewall)

デフォルトの3000番でBrowserSyncのListenが入りますので3000番をFireWallで通してください。

$ sudo ufw allow 3000
$ sudo ufw reload

npm run watchでBrowsersyncの起動

$ cd [your project path]
$ npm run watch

npm run watchにてデフォルトポート3000番でBrowsersyncが動作開始します。
下記のような表示がコンソールにでますので

[Browsersync] Proxying: https://xxxxxxxxxxxxx
[Browsersync] Access URLs:
 ---------------------------------------
       Local: https://localhost:3000
    External: https://192.168.xxx.xxx:3000

External:のURLにアクセスすればOKです。

他設定例

php artisan serveで起動したLaravelへアクセスする場合

webpack.mix.jsは下記になります。

mix.js('resources/js/app.js', 'public/js') // ただのmixだな
   .sass('resources/sass/app.scss', 'public/css') // ただのmixだな
   .browserSync({ // ここから
    proxy: {
        target: "http://127.0.0.1:8000" // 最後に/は不要
    },
    files: [ // チェックするファイルは下記で十分ではないかな。
       './resources/**/*',
       './app/**/*',
       './config/**/*',
       './routes/**/*',
       './public/**/*'
    ],
    open: false, //BrowserSync起動時にブラウザを開かない
    reloadOnRestart: true //BrowserSync起動時にブラウザにリロード命令おくる
});

ターミナル1つ目でphp artisan serve

$ (sudo) php artisan serve --host 0.0.0.0

場合によってはsudoいるかも。既存で動いているLaravelプロジェクトをいじっているプロセスがあればパーミッションデナイドでエラー画面になりました。

ターミナル2つ目でnpm run watch

$ npm run watch

まとめ

Browsersyncの待受ポートとか変更したい場合は公式ドキュメントにあるので参考にしてください。
調べてみると既存記事よりもずっとシンプルな設定に落ち着きました。
enjoy.

参考

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

Lumen のjsonレスポンスを拡張する

Laravelではレスポンスマクロというものがある。

いろいろなルートやコントローラで、再利用するためのカスタムレスポンスを定義したい場合はResponseファサードのmacroメソッドが使用できます。

https://readouble.com/laravel/5.5/ja/responses.html

しかしLumenで試すとエラーが出る。そんなものなどないらしい。

Uncaught BadMethodCallException: Method error does not exist. in /var/www/html/src/vendor/illuminate/support/Traits/Macroable.php:74

この記事にかいてある通りResponseファサードがLaravelとは違うみたいですね。

Responseファサードがありません。
Responseファサードのクラス自体はあるのですが、getFacadeAccessor()が返すResponseFactoryContractクラスがDIコンテナに登録されていないので使えません。

https://qiita.com/crhg/items/2ca642904955a2846de7

けどなんとか拡張したいので下記のようにresponseヘルパーのjsonメソッドを追ってみる。
/vendor/laravel/lumen-framework/src/Http/ResponseFactory.php
→ /vendor/illuminate/http/JsonResponse.php

お、何かMacroableトレイトを使てるっぽい。JsonResponseに追加すればよさそう。

/vendor/illuminate/http/JsonResponse.php
class JsonResponse extends BaseJsonResponse
{
    use ResponseTrait, Macroable {
        Macroable::__call as macroCall;
    }

試す

サービスプロバイダを作成

app/Providers/ResponseMacroServiceProvider.php
    public function boot()
    {
        JsonResponse::macro('success', function ($data) {
            $rows = [
                'message' => 'success',
                'option_params' => '',
                'data' => $data,
            ];
            return JsonResponse::create($rows);
        });
    }

    public function register()
    {

サービスプロバイダーを登録。

bootstrap/app.php
$app->register(App\Providers\ResponseMacroServiceProvider::class);

あとはルーティングやコントローラーを追加する。

app/Http/Controllers/BlogContloer.php
    /**
     * ブログ一覧取得
     * @return JsonResponse
     */
    public function getBlogList(): JsonResponse
    {
        $data = [
            'id' => 1,
            'title' => '楽しいゆるふわPHPer'
        ];
        return JsonResponse::success($data);
    }

curlで確認。

curl -s "http://localhost:8080/api/blog" | jq

{
  "message": "success",
  "option_params": "",
  "data": {
    "id": 1,
    "title": "楽しいゆるふわPHPer"
  }
}

まとめ

Lumenにはレスポンスマクロはない。しかし、再利用するためのカスタムレスポンスを定義したい場合はJsonResponseクラスのmacroメソッドが使用できるよって話。(MacroトレイトをuseしてるならResponseクラスとかでもできる)

(参考)
https://qiita.com/crhg/items/2ca642904955a2846de7

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

DockerでLaravel環境を構築する②~MySQL、laravelの導入~]

DockerでLaravel環境を構築する②~PHPの導入~の続きです。これで最後です。

MySQLのインストール

次にDBを使えるようにするため、MySQLをインストールしていきます。

docker-compose.yml
services:
# 省略
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: sample
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
volumes:
  mysql-data:

environmentはDockerコンテナ内で使用する環境変数を指定できます。
ただしこれで終わりではなく、最後に(laravelをインストールした後に)
今設定したこれらの値を、laravelのアプリ内に設定することで、実際にmysqlを使えるようにしていきます。

また、volumesによって、mysqlのデータを永続化しています。
最終的なdocker-compose.ymlは以下のようになります。

docker-compose.yml
version: '3'
services:
  web:
    image: nginx:1.15.6
    ports:
      - "8000:80"
    depends_on:
      - app
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html
  app:
    image: php:7.2-fpm
    depends_on:
    - mysql
    volumes:
      - .:/var/www/html
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: sample
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
volumes:
  mysql-data:

Laravelのインストール

次は、Laravelをインストールします。

laravelのインストールにはcomporserが必要ですが、最初に作成したPHPにはそれがありません。なので,
imageを取得してPHPを立ち上げるのではなく、「phpのimage+comporserのインストール」ができるDockerfileを作成します。
dockerディレクトリの下にphpというディレクトリを作り、そこにDockerfileを作成し、内容を以下のようにします。

docker/php/Dockerfile ↓

FROM php:7.2-fpm

# install composer
RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer
RUN apt-get update \
&& apt-get install -y \
git \
zip \
unzip \
vim

RUN apt-get update \
    && apt-get install -y libpq-dev \
    && docker-php-ext-install pdo_mysql pdo_pgsql

WORKDIR /var/www/html

次に、docker-compose.yml内のappサービスを以下のように書き換え、「build: ./docker/php」で、Dockerにホストされているimageからではなく、
作成したDockerfileからビルドするようにします。

docker-compose.yml
app:
    build: ./docker/php
    depends_on:
      - mysql
    volumes:
      - .:/var/www/html

そして、Nginxの設定(docker/default.conf)のroot(ドキュメントルート、4行目あたり)を書き換えて以下のようにします。

root  /var/www/html/my-laravel-app(自分の作成したlaravelアプリの名前)/public;

これで、nginxをリスタートします。

docker-compose restart

再度アクセスし、

スクリーンショット 2019-04-13 13.57.55.png

このようになればOKです!

最後に、(MySQLのインストールの続き)
環境変数の各値を、Laravel内のプロジェクトの .envファイルに記入します。

$ cd my-laravel-app(作成したlaravelのアプリに移動)
$ vi .env 

こんな感じで、.envファイルを開き、

以下のようになっている箇所を

.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

docker-compose.ymlで定義した内容に合わせ、このように変更してください。

DB_HOSTのところは、docker-composeで定義したサービス名になります。

.env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=sample
DB_USERNAME=user
DB_PASSWORD=password

以上で、作成したlaravelアプリで、mysqlが使えるようになっています。

nginxをリスタートし

$ docker-compose restart

再度アクセスして、コンテナの中に入ります。

$ docker-compose exec app bash
root@xxxxxxxxx:/var/www/html# 

#で入力待ちになっていればOKです。

作成したlaravelのアプリに移動して、マイグレーションを実行し、以下のようになれば完成です!!

root@xxxxxxxxx:/var/www/html#  cd my-laravel-app(作成したlaravelのアプリに移動)
root@xxxxxxxxx:/var/www/html#  php artisan migrate
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table

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

MAMPのPHP7にssh2拡張を使えるようにする

なんか山ほどハマったんで、もしかしたら下記意外にも必用なのあったかも…

wget https://pecl.php.net/get/ssh2-1.1.2.tgz
tar zxvf ssh2-1.1.2.tgz
cd ssh2-1.1.2
/Applications/MAMP/bin/php/php7.2.14/bin/phpize 
./configure --with-php-config=/Applications/MAMP/bin/php/php7.2.14/bin/php-config
make 
sudo make install
  • phpize をフルパスで実行しないとmacOSのphpizeが使われるのでフルパスで実行してます。
  • ./configure でphp-configまでのパスを指定しないとダメ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コンストラクタインジェクションされたクラスのprivate メソッドでもテストファーストしたい

テストファーストで開発するなら手を動かしながら軽い気持ちで書きたい。
例えそのクラスがprivateメソッドで依存関係があっても。

実装

例えば文字列を加工する処理のテストをTestクラスで実装する。

ServiceTest.php
    // テストしたいメソッド
    private function convertWord(string $keyword): string
    {
        $cv_word = trim($keyword);
        $cv_word = mb_convert_kana($cv_word,'Kas');
        return $cv_word;
    }

    public function testConvertWord()
    {
        // トリム処理 半角カナ->全角カナ(K)
        $word = ' 全角カタカナ ';
        $result = $this->convertWord($word);
        $this->assertSame('全角カタカナ', $result);
        // 全角英数字->半角英数字(a) 全角スペース->半角スペース(s)
        $word = 'Aiueo123 ';
        $result = $this->convertWord($word);
        $this->assertSame('Aiueo123 ', $result);
    }

移動方法

しかしこのメソッドは別のクラスで使うために書いてるので、メソッドを移動させる。

Service.php
    private $repository;
    public function __construct(RepositoryInterface $repository)
    {
        $this->repository = $repository;
    }

    private function convertWord(string $keyword): string
    {
        $cv_word = trim($keyword);
        $cv_word = mb_convert_kana($cv_word,'Kas');
        return $cv_word;
    }

移動させたらprivateメソッドなのでReflectionクラスを使ってprivateメソッドにアクセスできるようにして、
コンストラクタを起動せずにインスタンスを作成する。

ServiceTest.php
    public function testConvertWord()
    {
        $reflection = new \ReflectionClass(Service::class);
        $method = $reflection->getMethod('convertWord');
        $method->setAccessible(true);
        $not_construct_service = $reflection->newInstanceWithoutConstructor();

        // トリム処理 半角カナ->全角カナ(K)
        $word = ' 全角カタカナ ';
        // $result = $this->convertWord($word);
        $result = $method->invoke($not_construct_service, $word);
        $this->assertSame('全角カタカナ', $result);
        // 全角英数字->半角英数字(a) 全角スペース->半角スペース(s)
        $word = 'Aiueo123 ';
        $result = $method->invoke($not_construct_service, $word);
        $this->assertSame('Aiueo123 ', $result);
    }

移動できたことを確認するためにphpunitを起動。

Time: 757 ms, Memory: 8.00 MB

OK (1 test, 2 assertions)

Process finished with exit code 0

まとめ

privateメソッドをテストするのは、クラス設計が悪い、別クラスやヘルパーとして切り出せとか賛否両論あるかもだけど、スコープを抑えたいとかどうしても設計を変更できない場合などもあると思うので知識として知っておいて良いと思う。まあ他言語だとReflectionクラスが無いとかあるし、後に設計変更したいと思っても、テストがあることで安全に変更できるので、まずは動くものとテストを書きたい。

(参考)
https://qiita.com/suin/items/a1c3d96050cb7e51424d
https://qiita.com/mpyw/items/b3d974c073e6484d51a4

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

HTML5またはPHPでの著作権表記

書き方を迷ってる方のためにHTML5や、PHP5.4以降で、著作権表示をする場合の書き方をメモしておきます。

著作権表記

著作権発行年を2018年、現在の年を2019年として、
昔、著作権表記は
Copyright © 2018-2019 ○○ All rights reserved.
など書かれているサイトが多かったのですが、実際表記するのは
© 2018 ○○ または © 2018-2019 ○○
だけで大丈夫です。

PHPで出来て、HTMLで出来ないこと

HTMLでは現在の年を手動で更新しなければいけませんが、PHPでは自動更新ができます。
つまり、「© 2018-2019 ○○.」この2019の部分が実際の年に合わせて自動更新できます。

タグ

著作権表記に使用するタグが用意されています。
それは、<small>タグです。(免責、注意などにも使用できます。)
<p>タグと<small>タグを合わせて著作権表記します。

書き方

HTML (© 2018 ○○)

HTML
<p><small> &copy; 2018 ○○ </small></p>

中央寄せにしたい場合

HTML
<p align="center"><small> &copy; 2018 ○○ </small></p>

CSSを使って中央寄せにしたい場合

HTML
<p class="copy"><small> &copy; 2018 ○○ </small></p>
CSS
p.copy {
    text-align: center;
}

PHP (© 2018-2019 ○○)

PHP
<p><small> &copy; 2018-<?=date('Y')?> ○○ </small></p>

中央寄せにしたい場合

PHP
<p class="copy"><small> &copy; 2018-<?=date('Y')?> ○○ </small></p>

CSSを使って中央寄せにしたい場合

HTML
<p class="copy"><small> &copy; 2018 ○○ </small></p>
CSS
p.copy {
    text-align: center;
}

いらないと思いますが、echoで書く場合

ダブルクオーテーションで囲む場合

PHP
echo "<p><small> &copy; 2018-".date('Y')." ○○ </small></p>\n";

中央寄せにしたい場合

PHP
echo "<p align=\"center\"><small> &copy; 2018-".date('Y')." ○○ </small></p>\n";

CSSを使って中央寄せにしたい場合

PHP
echo "<p class=\"copy\"><small> &copy; 2018-".date('Y')." ○○ </small></p>\n";
CSS
p.copy {
    text-align: center;
}

シングルクオーテーションで囲む場合

PHP
echo '<p><small> &copy; 2018-'.date('Y').' ○○ </small></p>'."\n";

中央寄せにしたい場合

PHP
echo '<p align="center"><small> &copy; 2018-'.date('Y').' ○○ </small></p>'."\n";

CSSを使って中央寄せにしたい場合

PHP
echo '<p class="copy"><small> &copy; 2018-'.date('Y').' ○○ </small></p>'."\n";
CSS
p.copy {
    text-align: center;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[WIP] nginx とは? ~ 初心者が調べた時の記事まとめ ~

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

phpdotenvが複数行に対応

phpdotenvがV3から

NAME="VALUE
VALUE
VALUE"

に対応しました。

.env

TEXT="aaa
bbb
ccc"
phpdotenv2.php
<pre>
<?php
include('autoload.php');
use Dotenv\Dotenv;

$dotenv = new Dotenv(__DIR__);
$dotenv->load();
var_dump($_ENV);
?>

/*
array(1) {
  ["TEXT"]=>
  string(3) "aaa"
}
*/
phpdotenv3.php
<pre>
<?php
include('autoload.php');
use Dotenv\Dotenv;

$dotenv = Dotenv::create(__DIR__);
$dotenv->load();
var_dump($_ENV);
?>

/*
array(1) {
  ["TEXT"]=>
  string(11) "aaa
bbb
ccc"
}
*/

ちなみに.envが

TEXT="aaa

だと上記コードの出力は

V2
array(1) {
  ["TEXT"]=>
  string(3) "aaa"
}

V3
array(0) {
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 開発環境の構築(CentOS7)

①Laravelのインストールとディレクトリ構成

下記を参考にphp開発環境の構築及びDBの設定が済んでいることを前提とします.

参考:Vagrantでphp開発環境を構築(CentOS7.2)

  • 下記コマンドを実行してください(Laravelをインストールします).
仮想マシン
# laravelインストーラをインストールする
$ composer global require "laravel/installer=~1.1"
# laravelプロジェクトを作成する
$ composer create-project laravel/laravel /var/www/[プロジェクト名] --prefer-dist

ディレクトリ構成は下記のようになっており,主にコントローラであるHttp/Controllers/と,ビューであるresources/views/配下を編集することで開発を進めていきます.

ディレクトリ構成
app
  ├ Http/
  |  └ Controllers/
  |      ├ Auth/
  |      └ Controller.php
  ├ config/
  |  ├ app.php
  |  └ database.php
  ├ database/
  |  └ migrations/
  ├ public/
  |  ├ css/
  |  └ js/
  ├ resources/
  |  ├ assets
  |  └ views
  ├ routes/
  |  └ web.php
  └ .env
  • Http/Controllers/ : コントーラを配置するフォルダ.
  • config/app.php : アプリケーション全体の設定をするファイル(ロケール情報など).
  • config/database.php : 接続するデータベースに関しての設定をするファイル.
  • database/migrations/ : マイグレーションファイルを配置するフォルダ.
  • public/ : 外部からアクセス可能なフォルダ.CSSやJSはここに配置する.
  • resources/views/ : ビューを配置するフォルダ.
  • routes/ : ルーティング情報を配置するフォルダ.

②サンプルページの作成

Laravelでviewを作成する際は,Bladeというテンプレートエンジンを用います.

今回は下記のような構成で,サンプルページを作ってみることにします.

  • layouts/common.blade.php : ベースとなるテンプレートファイル
  • layouts/head.blade.php : HTMLのHeadタグの中に書き込むテンプレートファイル
  • layouts/header.blade.php : ヘッダーのテンプレートファイル
  • layouts/footer.blade.php : フッターのテンプレートファイル
  • pages/sample.blade.php : サンプルページのビューファイル(ページごとに作成します)

テンプレートファイルは,layout/ディレクトリを作ってその配下に,ビューファイルはpages/ディレクトリを作ってその配下に配置しました.これらの配置場所によって,呼び出す際の指定方法が変わってくるので気をつけてください.

参考:Blade テンプレートについて - Laravel学習帳
参考:LaravelのBladeテンプレートでレイアウト部分を共通にする

common.blade.php
<!DOCTYPE HTML>
<html lang="ja">
<head>
    {{-- Head部分 --}}
    @yield('head')
</head>
<body>
    {{-- ヘッダー部分 --}}
    @yield('header')

    <div class="container">

    <div class="main">
        {{-- コンテンツ部分 --}}
        @yield('content')
    </div>

    <div class="sub">
        {{-- サブコンテンツ部分 --}}
        @yield('sub')
        {{-- ページサブコンテンツ部分 --}}
        @yield('pageSub')
    </div>

    </div>
    {{-- フッター部分 --}}
    @yield('footer')
</body>
head.blade.php
@section('head')
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<title>Laravelサンプルサイト | @yield('title')</title>
<meta name="description" content=@yield('description')>
<meta name="author" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- テンプレート共通CSS -->
<link type="text/css" href="{{asset('/css/app.css')}}" rel="stylesheet">
@yield('pageCss')
@stop
header.blade.php
@section('header')
<header class="header">
    <h1>Laravelサンプルサイト</h1>
</header>
@stop
footer.blade.php
@section('footer')
<footer class="footer">
    <small>@created by koukibuu3</small>
</footer>
<!-- テンプレート共通JS -->
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="{{{asset('/js/app.js')}}}"></script>
@yield('pageJs')
@stop
sample.blade.php
{{-- レイアウトの読み込み --}}
@extends('layouts.common')

{{-- CSSの読み込み --}}
@section('pageCss')
<!-- ページ独自CSS -->
<link type="text/css" href="{{asset('/css/sample.css')}}" rel="stylesheet">
@stop

@section('title')
サンプルページ
@stop

{{-- Headの読み込み --}}
@include('layouts.head')

{{-- ヘッダーの読み込み --}}
@include('layouts.header')

{{-- メインコンテンツ --}}
@section('content')
    <h2>This is sample page.</h2>
    <table>
        <tr>
            <th>ID</th>
            <th>NAME</th>
            <th>EMAIL</th>
        </tr>
        <?php foreach ($data as $val) { ?>
        <tr>
            <td><?php echo $val->id; ?></td>
            <td><?php echo $val->name; ?></td>
            <td><?php echo $val->email; ?></td>
        </tr>
        <?php } ?>
    </table>
@stop

{{-- JSの読み込み --}}
@section('pageJs')
<!-- ページ独自JS -->
<script type="text/javascript" src="{{{asset('/js/sample.js')}}}"></script>
@stop

{{-- フッターの読み込み --}}
@include('layouts.footer')
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ニュートン法 Newton's method by PHP

ニュートン法をPHPで書いてる記事が見当たらなかったから書いてみた。
暇つぶし用
Qiitaの使い方が分からなくて途中でおかしくなったw

<?php
//ニュートン法 PHP
//2019_04_13
//(C)Camity

function Newton_method($target,$x1,$x2){

//666はwhileの型で書いただけ意味ない値
while($x1 < 666){

    echo $x1.'<br />';
    //ニュートン法による新しいxを求める
    $x2 =  $x1 - ($x1 * $x1 - $target) / ($x1 * $target);

    //計算後の値が誤差の範囲内になったら計算終了
    if (abs($x2 - $x1) < 0.0001){
        echo 'end';
        break;
    }

    //計算後の値をxとして計算を繰り返す
    $x1 = $x2;
}

}

$x1 = NULL;
$x2 = NULL;
$target = NULL;

//開始したい初期値の設定
$x1 = 5.0;
//今回求めたい値 ex√2なら2
$target = 3;
Newton_method($target,$x1,$x2);

exit();

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