20191204のPHPに関する記事は25件です。

PHPからJavaScriptへの値渡し

はじめに

PHPからJavaScriptへの値の渡し方を、phtmlで書いてまとめます。
なるべく同じような型として解釈されるように変換しています。

PHP(string) → JS(string)

test.phtml
<?php
    $foo = 'abcde';
?>

<script>
    let bar = '<?php echo $foo; ?>';
    console.log('typeof: ' + typeof bar);
    console.log('value: ' + bar);
</script>
console.log
typeof: string
value: abcde

PHP(integer) → JS(number)

test.phtml
<?php
    $foo = 12345;
?>

<script>
    let bar = <?php echo $foo; ?>;
    console.log('typeof: ' + typeof bar);
    console.log('value: ' + bar);
</script>
console.log
typeof: number
value: 12345

PHP(boolean) → JS(boolean)

test.phtml
<?php
    $foo = true;
?>

<script>
    let bar = Boolean(<?php echo $foo; ?>);
    console.log('typeof: ' + typeof bar);
    console.log('value: ' + bar);
</script>
console.log
typeof: boolean
value: true

PHP(array) → JS(object)

test.phtml
<?php
    $foo = [1, 2, 3, 4, 5];
    $foo = json_encode($foo);
?>

<script>
    let bar = JSON.parse('<?php echo $foo; ?>');
    console.log('typeof: ' + typeof bar);
    for (let i = 0; i < bar.length; i++) {
        console.log('value: ' + bar[i]);
    }
</script>
console.log
typeof: object
value: 1
value: 2
value: 3
value: 4
value: 5

PHP(array) → JS(object) [連想配列]

test.phtml
<?php
    $foo = ['key' => 'value', 'aaa' => 'bbb'];
    $foo = json_encode($foo);
?>

<script>
    let bar = JSON.parse('<?php echo $foo; ?>');
    console.log('typeof: ' + typeof bar);
    for (let key in bar) {
        console.log(key + ': ' + bar[key]);
    }
</script>
console.log
typeof: object
key: value
aaa: bbb

まとめ

Bool or Array を渡すときは、ひと手間必要です。

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

Laravel6 ViewからControllerへ渡されたget/post データの取得の仕方 パターン整理

Laravelでviewからpost/get したデータをControllerで記述形式がいくつかあって、よくわからないので整理します。

とりあえず、思いつく限りでどんな記述形式がるか書き出してみます。
仮にview側でpostかgetでデータが送られたときに、3パターンくらい取得方法がある気がします。
記述形式はどれでもいいのかと思いきや、エラーではじかれる組み合わせがあるっぽいので整理します。

形式は1個でいい気がするけど、どうしていくつもあるのでしょう?
たぶん、整理していくうちに分かるかもしれません。

Controller
function example(Request $request){
 $request->input('name');
 $request->name;
 $request('name');
}

例えば、View側からPOST形式でデータを渡した場合

View
<form method="POST" action="/index">
   <input type="text" name="name">
   <input type="text" name="pass">
   <input type="submit">
</form>

コントローラー側で正しく動作する記述は

Controller
function example(Request $request){
 $request->name;
 $request->input('name');
}

の2つでした!

$request('name');

を使用すると

image.png
こんなエラーが出ちゃいました。

次にget形式ではどうなるか調べてみます。

View
<form method="GET" action="/index">
   <input type="text" name="name">
   <input type="text" name="pass">
   <input type="submit">
</form>

postの時と同じ結果になりました(笑)
ということは、単純に自分の勘違いで使えないコードを覚えてしまったようです。。
どうして、こんな勘違いをしていたのか?
それは2つの記述方法が、混同して記憶違いで直感的に書きやすい記述が刷り込まれてしまったからだと思います(言い訳)
結局、形式が2つある理由はよくわかりませんでした。
1つだけなら、勘違いすることもないのにと思いました。

Laravelでは
ページ表示にview()とredirect()があって、
どちらを使うと便利なのかわからずにいます。

redirect()は記述形式がroute()を使う場合と使わずに記述する方法があるので、
どれがどういうときに向いている記述なのか?
調べたいと思います

以上、勘違いしていましたという記事になりました。

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

PHPカンファレンスに参加してきました!

PHPカンファレンスに参加してきました!

先日12月1日(日)にPHPカンファレンスに参加しましたので、
そのレポートというか感じたこと記事をまとめておきます。

PHP Conference Japan 2019

全体の感想

PHPに特化したというよりは、周辺の技術、アーキテクチャなど様々な部分のセッションがあり、
視野が広がるようなカンファレンスだったなと感じました。
と同時に自分より年下の人が話していたりと、
すごいなーとひたすら関心です。

個人的には「MVCにおける「モデル」とはなにか」が、
哲学的で面白かったと感じますし、
今までMVC=model:データベース/view:フロント/Controller:他全部
的なざっくりとして捉え方がどれだけ浅はかだったかを痛感致しました。。。

アーキテクチャ=インフラ構成のイメージが強かったのですが、
アプリケーションアーキテクチャとしてフレームワークをどのように扱うかの意識次第で
運用保守、改修のスピードに結構な差が出るという点を認識しなければと反省しました。
一発ではあまり理解ができなかったので、
今後も継続してインプットしようと思います。

参加したセッションとその記事(一部)

MVCにおける「モデル」とはなにか

トーク内容

日本の開発者の間でドメイン駆動設計の話題が盛り上がっています。
ドメイン駆動設計の話が出てくるたびに「モデルとはなにか」という話がでてきますが、多くの話は実装に寄った話になりがちです。

Model-View-Controllerパターン提唱者のトリグヴェ・リーンスカウク博士は「モデルは知識の表象である」と定義しています。
このトークでは、「モデル」とはそもそも何であるのかについて、リーンスカウク博士のModel-View-Controllerパターンを参照しながら詳しく検討します。開発以前にどんな基本的な問題が存在し、何を解決するべく「モデル」という概念は提示されたのか?についてお話します。

1言メモ

哲学的で面白かったですが、難しかった。。
感じたこと記事

PHPerのためのテストコード入門

トーク内容

皆さんは普段テストコードを書いていますか?もしくはこれから導入しようと奮闘していますか?はたまたテストコードというのを初めて聞きましたか?
テストコードと一口に言っても、ユニットテスト、featureテスト、APIテスト、E2Eテストなどたくさんの種類のテストコードがあります。
テストコードを導入する前に「なぜそのテストコードを書くのか」を話せることを目的として、テストそのものやテストコードについてお話ししていきます。

1言メモ

サテライト視聴していたのですが、
途中で切れてしまったので残念でした、、、
発表者が年下というのには尊敬の念しか抱きません。
感じたこと記事

プログラム未経験からたった3ヶ月で圧倒的な開発力を身につける ~ スクラッチ開発の重要性

トーク内容

数百以上のプロジェクト開発経験を踏まえ、プログラマに必要なスキルとは?
数年後、10年後先を見据えどのようなスキル・考え方を身につければ
プログラマとして圧倒的に成長できるか?

上記について徹底的に分析し、成長するためのエッセンスを凝縮した
教育カリキュラムを紹介いたします。

1言メモ

スピーカーの前田さんは1ヶ月で400時間ほど開発を行っていたそうです。
さすがに起業するレベルの人は熱量が違うなーと感じつつ、
今の自分は業務(8時間×20日)+ 自習(2h×30日)って感じなので、
全然足りないなーと反省もありました。

また、スキルエンジンというプログラミングスクールをやっているようなのですが、
そこでのフルスタックエンジニアには、
進捗・スケジュールの報連相といったタスク管理的な部分や、
思考体力、タイピングといった基礎体力も含めてできる人を指すとのこと。
で、この進捗・スケジュールの報連相といったタスク管理的な部分によって、
フリーランスなどでは仕事の取れ方が結構変わってくるとのことでした。
経験者ならではの考え方で参考になす。

時間の関係もあって、
技術的、具体的な話はあまりなかったのは少し残念でした。。

Laravel × クリーンアーキテクチャ 開発中の現状をお伝えしたい

トーク内容

「クリーンアーキテクチャ」とは、DDDの文脈における「ドメインモデル」をシステムの中心にすえ、「入力」「永続」「出力」などの多方面で抽象化を行うことで、高度に変化への強さを獲得できるアーキテクチャです。昨今の変化の早さに対応するべく「アジャイル開発」や「マイクロサービス」が叫ばれているように、「クリーンアーキテクチャ」もまた日増しにその注目度は上がっているように感じます。

しかし、やや取っつきにくいアーキテクチャであることからか、現状参考になる資料が無数に転がっているというわけでもありません。そこで、エキテンで現在Laravelベースで開発中の新しい予約システムを題材に、実際にアーキテクチャを形作っているコンポーネントの紹介や、開発する上で行ってみたちょっとした工夫、開発フェーズにおける現場の生の声などをお話しようと思います。

1言メモ

正直クリーンアーキテクチャとは?状態だったので、
言わんとする事はなんとなくわかるけど本質的には全然理解できていないといった状態でした。
クリーンアーキテクチャについてはさくっと理解できなさそうでしたので、
後日まとめようと思います。。。

オニギリペイのセキュリティ事故に学ぶ安全なサービスの構築法

トーク内容

安全なインターネットサービスを提供するにあたっては、ソフトウェアバグとしての脆弱性対策だけではなく、ビジネスモデル・サービス仕様・アーキテクチャ設計・ソフトウェア設計・実装・サーバーなどの多方面からセキュリティ検証が重要となります。本セッションでは、架空のQRコード決済サービス「オニギリペイ」のセキュリティ事故を題材として、サービスの企画・要件定義・設計・実装の各フェーズに起因する問題とその対策を具体的に紹介します。

1言メモ

概念的な話と、そこから具体的な方法論まで落とし込んでお話頂いたので、
今後どうすべきかがわかりやすかったです。
そういう意味ではある種どこで何をするかがふわっと把握していた状態であったセキュリティ対応というものに、
具体的にこのタイミングでこれをやるべきというのが理解できたなと感じました。

感じたこと記事

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

入社1年目のWEBエンジニアが、コードレビューで教わったことを振り返ってみる

アドベントカレンダー何書こうかな〜と考えていたところ、フロントエンドエンジニア1年目はコードレビューでどんな指摘を受けるのかという投稿を読み、私も良い機会なので書いてみることにしました。

私のステータス

  • 昨年11月にqnoteに入社
  • コールセンターからエンジニアにジョブチェンジ
  • 学生時代にプログラミング未学習
  • Laravel + Vue.js を使ったプロジェクトに参画
  • フロントエンド / バックエンド共に行い、機能別に issue を立てて、issue 毎に担当。

初歩的なこと

typo

私はこれがひどい。

  • datedata を間違える
  • 変数名が camelCase なのに snake_case で書いて値が取れないと騒ぐ
  • deletedetele と書く

エディタでスペルチェックをしてもらうのが良い。
Sublime Text なら、 spell_check: true にするか F6 でスペルチェックをしてくれる。
VSCode でもプラグインを入れればスペルチェックしてくれる。

真偽値の統一

true'1'1 は全て true と判断できるが、コーディング規則に従い統一する

rand ではなく mt_rand

テストで乱数を生成するときに、rand を使用した。理由はググったら最初に出できたから。
しかし、rand の上位互換である mt_rand を使用するように教わった。
理由は mt_rand の公式ドキュメントにある。

古い libc の多くの乱数発生器は、怪しげであるか特性が不明であったりし、 また低速でした。 mt_rand() 関数は、古い rand() の代替品となるものです。 この関数は、その特性が既知の乱数生成器 » メルセンヌ・ツイスター を使用し、 平均的な libc の rand()よりも 4 倍以上高速に乱数を生成します。
PHP: mt_rand - Manual

命名規則に従う

変数名などの表記方法は一般的に以下の3つになる。

  • camelCase キャメルケース
  • PascalCase パスカルケース(キャメルケースの頭文字大文字版)
  • snake_case スネークケース

参画したプロジェクトでは、変数名は camelCase、クラス名とファイル名は PascalCase にすることになっていた。
これはプロジェクト毎で規則があると思うが、変数やファイル名などの規則がバラバラにならないように気をつける。

エラーを読む

これ、よくやりがち。
エラーが出た
->怖くなって先輩に質問しに行く。
->先輩がエラー見る
->先輩『エラー文言読んだ?』
->私『読んでません。(汗』

エラーは、ちゃんと問題点を書いてくれていることが多い。
先輩に聞きに行く前に、翻訳してみたり、ググってみればわかることは多い。
5分調べて、10分試して解決しなければ聞きに行く。くらいで良いと思う。

公式ドキュメントを読もう(英語でも)

困った時、ググる。
すると Qiita とか はてブ とか teratail とか どっかのオンラインスクール とかが、検索上位に出てくる。
そういう記事は、タイトルが困ってる状態と似ていることが多いのだが、自分の環境と違ったり、間違っていたりすることもある。
で、結局解決せずに、先輩に聞きに行く
->先輩『公式ドキュメント読んだ?』
->私『読んでません(汗』

内容によるが、基本的な使い方は公式ドキュメントに書いてある。
公式ドキュメントが英語のみってこともある。lodash とかね。
けど、そんな難しい言い回しはしていない。
翻訳しつつ、頑張って読んでいれば、だんだん読めるようになってくる。

可読性向上

三項演算子やエルビス演算子で済むなら、if文は使わない。

最近の流行りというのもあるかもだけど、単純な条件分岐なら、if文を使わない方が読みやすい。

countによってメッセージを変える処理.js
msg() {
  if (this.count > 10) {
    return 'カウントが 10回 を超えました。'
  }
  return ''
},

// 三項演算子
msg() {
  return this.count > 10 ? 'カウントが 10回 を超えました。' : ''
},

一行を長くしすぎない(改行する)

一行の文字が多く、横に長すぎるとコードが読みにくい。

ESLintを導入していれば、エラーで教えてくれる。
max-len - Rules - ESLint - Pluggable JavaScript linter

DRY

Don't repeat yourself(繰り返すな)。
同じような処理を複数回書くことは、修正が必要な時に修正漏れなどのリスクが増す。
また、同じような処理なら、別functionとして切り離せばテストもしやすい。

テスト

DI を使う

以下のような機能のテストを書いているときに教わった。

DIを使用していない.php
class Sample
{
    public function execute(array $params)
    {
        if ($userCd = Arr::pull($value, 'user_cd')) {
            $userId = app(GetUser::class)
                ->getUserId($userCd);

            // 何かする
        }
    }
}

このテストを書く場合、GetUser::getUserId() が未実装だとテストが行えない。

そこで DI を使用する。

DIを使用した場合.php
class Sample
{
    private $getUser;

    public function __construct(GetUser $getUser)
    {
        $this->getUser = $getUser;
    }

    public function execute(array $params): string
    {
        if ($userCd = Arr::pull($value, 'user_cd')) {
            $userId = $this->getUser
                ->getUserId($userCd);

            // 何かする
        }
    }
}

このように DI を使用すると、この Sample クラスのテストをする際に、GetUser::getUserId() をモックすれば、テストが行える。

モックオブジェクトを使ったテスト.php
class SampleTest extends TestCase
{
    $getUser = $this
        ->getMockBuilder(GetUser::class)
        ->setMethods(['getUserId'])
        ->getMock();

    $getUser->expects($this->once())
        ->method('getUserId')
        ->willReturn(123);

    $sample = new Sample($getUser);

    $parames = [
        'user_cd' => 'hogehoge123'
    ];

    $res = $sample->execute($parames);
    $this->assertEquals($res, '期待値');
}

機能を細かく分ける

理想は、1クラスに1機能。
そうすることで、テストが容易になる。

SOLID原則

敬愛なるゆいもっぷ先輩の記事をご参照ください?‍♂️
SOLID原則について簡単に書く

猫社員の見分け方

名前 特長
ふたば クリーム色
みるく 茶虎、口元が白い、尻尾が少し鍵しっぽ
はな 茶虎、全体的にシュッとしてる
ちまき 錆色、尻尾が縞様、おでこハゲ
さくら 錆色、顔の桜色の部分多め
りぼん 錆色、小さい、かわいい
みぃ 白黒

猫社員たちをご覧になりたい方は、是非遊びにきてください!
株式会社qnote

猫は腰を叩かれると喜ぶが、叩きすぎは良くない

叩きすぎるとヘルニアになる可能性がある。

最後に

いつもコードレビューや質問に応えていただいている @adwin さんや @poipoisaurus さんをはじめとする qnote の皆さんに本当に感謝しています。
ありがとうございます。
そして、来年もよろしくお願いします?

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

Google reCAPTCHA v2 導入時につまったこと

概要

Google reCAPTCHA v2 サーバ側処理の実装時に詰まった内容の備忘録

内容

実装する際に当初下記のようにgoogle側に認証のため、
file_gets_contentsを利用して結果を受け取るように実装し、
開発環境では問題なく動作していた。

$response=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".シークレットキー."&response=".レスポンスコード);

ただ、こちらの内容を今度は本番環境にリリースしたとき、何度試しても
reCAPTCHAの認証がエラーが返ってくる現象が発生。

原因

結果としては、「file_gets_contents」が原因で発生。
開発サーバ側では上記は利用できるような設定がされていたが、本番サーバ側では
利用できないように設定されていたため、認証が出来ずに常にエラーに・・・。

PHP: 実行時設定 - Manual
http://php.net/manual/ja/filesystem.configuration.php#ini.allow-url-fopen

今までは普通のこちらの設定がONになっていたため、利用できていたが
まれにOFFになっていることがあるようです。

解決策

単純に「file_gets_contents」を利用せずに「cURL」を利用して実装したところ
問題なく動作可能でした。

$url = "https://www.google.com/recaptcha/api/siteverify?secret=".シークレットキー."&response=".レスポンスコード;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
$response = curl_exec($ch);
curl_close($ch);

おわりに

PHP側で用意されている関数を利用するから問題ないだろうとろくに調べずに
「いつもどおり」で実装することは危険であることが改めて実感できました・・。

皆様もお気をつけください。

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

PHP(クッキー操作)

書いてあること

  • PHP(オブジェクト指向)
  • 忘れたとき用の自分メモ

追加

// クッキーの追加
setcookie(クッキー名, データ, 有効期限, 保存場所);

setcookie($name . 'CONDITION', $keyword, time() + (60 * 60 * 24 * 365), '/');

存在確認

// クッキーの存在確認
array_key_exists(クッキー名, $_COOKIE$) 

if (array_key_exists($name . 'CONDITION', $_COOKIE)) {
    return true;
} else {
    return false;
}

削除

// クッキーの削除(※有効期限で本日以前の日時を指定すると、クッキーが削除される)
setcookie(クッキー名, 有効期限, 保存場所)
setcookie($name . 'CONDITION', '', time() - 1800, '/');
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP Swoole学習メモ書き

PHPに非同期処理を提供してくれるSwooleプラグインについての学習メモ。
主に自分向けだけど、誰かの役に立つかもしれないので公開しておく。

About Swoole

PHPプラグイン。Peclで入れる模様。
いろんなモジュールがある。 https://www.swoole.co.uk/docs/module
TCP, UDP, UnixSocket, HTTP, WebSocket, Redisなど。 Clientも提供している。 Http/2 Clientもあるのか。
Linux Process Manager, Async File IO, etcなども。

MySQL, Redis Clientもあるな。 mysqlnd, mysqliの置き換えとして動くらしいから、 PHP -> C -> MySQL の全部を担当してくれるのか。

Install

Pecl, はmacOSだけになったらしい。Source落として自分でビルドしろと…
試したいだけならDockerfileのサンプルが用意されてるっぽい。Docker Hubに上がってないのかな?
https://www.swoole.co.uk/docs/get-started/try-docker

Server

調べることがあったら書く。
今のところphp-fpmの置き換えをしたいとは思っていないので後回し。

EventLoop

https://www.swoole.co.uk/docs/modules/swoole-event-loop
イベント駆動の処理を書けるのかな?サンプルだとSocket接続してstream処理のようなことをしてるように見える。

KafkaみたいなメッセージングツールのSubscriberをPHPで書きやすくなる…?

Coroutine

どこかのバージョンからSwooleパッケージから切り出されたっぽい。

GoのChannel相当のものもあって、ネット上のサンプルコードだとこれをよく見る気がする。 go() で非同期処理が開始されたりdefer関数を呼んでたりでだいぶGoを意識してそう。
と思ったら go() + Swoole\Event::wait() のパターンはdeprecatedになっている。Coroutine\runで置き換えられたのかな。
この辺がCoroutineとして切り出されたからこっち使ってね、的なことなのかな。
しかし4.4.0-alpha版で試したらCoroutine\Runが無いと言われてしまった。サンプルが壊れてんのかな。

所感

Serverとか TCP/UDP, WebSocket接続, Stream, プロセスやメモリ管理のようなPHPが隠蔽してくれるおかげで触らなくて(理解しなくて)済んでる低レイヤーを露出させてますね。ハイパフォーマンスなアプリケーションを作ろうと思うとこの辺の知識がどうしても必要になるということをPHPエンジニアに突きつける感じでいいですね。そんなにパフォーマンスが必要なものにPHPを使うのかというのはまぁそれはそれで。

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

php ログ

ログをとるための関数
ini_set('log_errors','on');
ログの出力ファイルを指定
ini_set('error_log','php.log');

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

PHPの画像認証ライブラリ「Securimage」を使ってみた

画像認証とは

ロボットによる迷惑投稿を防止する仕組みで画像に表示された文字を入力欄に正しく記載し送信しない限り投稿が完了しません。
今回は以下のようなよく見かけるタイプの画像認証をPHPライブラリのSecurimageで実装してみました。
キャプチャ2.png

Securimageをインストールしてみる

公式サイトにアクセスしてSecurimageをダウンロードします。
落ちてきたzipファイルを展開したらsecurimageというフォルダがあるので、それを丸ごと任意の場所へ設置するだけです。(今回はサンプルなのでドキュメントルートの直下に置きました)

HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>画像認証サンプル</title>
</head>
<body>
<?php require_once('./sample.php'); ?>
<form method="post">
<p><img id="captcha" src="./securimage/securimage_show.php"></p>
<p><input type="text" name="captcha_code" placeholder="表示されている文字を入力してください"></p>
<p><button type="button" id="button">画像再生成</button></p>
<p><input type="submit" value="認証"></p>
</form>
<script src="./sample.js"></script>
</body>
</html>

生成される画像によっては認識が困難なものもあるので、
再生成できるようにJavaScriptを設置します。

認証画像を再生成するJavaScript
const button = document.getElementById('button');
button.addEventListener('click', function() {
    const captcha = document.getElementById('captcha');
    captcha.src = './securimage/securimage_show.php?' + Math.random();
}, false);

画像認証の判定プログラムです。
$securimage->check($_POST['captcha_code'])の返り値が真偽値となっており、
その値によって認証を判定しています。

画像認証プログラム
require_once './securimage/securimage.php';
$securimage = new Securimage();

if(isset($_POST['captcha_code'])) {
  if($securimage->check($_POST['captcha_code']) === true) {
    echo '画像認証OK';
  } else {
    echo '画像認証エラー';
  }  
}

オプションについて

Securimageにはいろいろなオプションが標準で用意されています。
使い方はsecurimage_show.php$img->show();より前に、適用したいオプションを記載するだけです。securimage_show.php内には既にサンプルとしてオプションが記載されています。

画像の大きさ
// 高さで大きさを指定する
$img->image_height    = 90;
$img->image_width     = $img->image_height * M_E;
認識のしやすさ
// 文字のゆがみの比率
$img->perturbation  = .75;
// ラインの数
$img->num_lines     = 8;
各色の指定
// ラインの色
$img->line_color      = new Securimage_Color("#ff8888");
// テキストの色
$img->text_color      = new Securimage_Color("#ff6666");
// 背景の色
$img->image_bg_color  = new Securimage_Color("#ffffff");

まとめ

ライブラリを使うことで、非常に簡単に画像認証を実装する事ができました。
生成される画像についてはフォントやサイズ、色等を調整することが可能なので、サイトのイメージも損なうことなく実装する事ができそうです。
画像認証を管理画面のログインフォーム等に実装する事でセキュリティレベルの向上が期待できます。(ランディングページなどのフォームに実装する際はCVRが低下しないか検証する必要がありそうです。)
ちなみに、個人的にはgoogleのreCAPTCHAより導入のハードルは低いように感じました。

画像認証の忘備録でした!

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

CentOS8 LAMP構築

環境

CentOS Linux release 8.0.1905 (Core)
Minimal installにgcc関係・vim・gitくらい入れたもの

web

Install_and_configure_apache2.4.37
[C8LX@root ~]# dnf install httpd httpd-devel httpd-tools mod_ssl -y
[C8LX@root ~]# httpd -v
Server version: Apache/2.4.37 (centos)
Server bui lt:   Oct  7 2019 21:42:02

[C8LX@root ~]# cd /etc/httpd/conf/
[C8LX@root /etc/httpd/conf]# cp httpd.conf httpd.conf.bk

[C8LX@root /etc/httpd/conf]# cat httpd.conf.bk | egrep -v "(\#|^$)" > httpd.conf

[C8LX@root /etc/httpd/conf]# vim httpd.conf
-:Listen 80
+:Listen 0.0.0.0:80

-:    DirectoryIndex index.html
+:    DirectoryIndex index.php index.html index.cgi
(末尾に追記)
ServerTokens Prod

[C8LX@root /etc/httpd/conf]# cd

[C8LX@root ~]# firewall-cmd --list-all
  services: cockpit dhcpv6-client ssh

[C8LX@root ~]# firewall-cmd --remove-service={dhcpv6-client,cockpit} --zone=public --permanent

[C8LX@root ~]# firewall-cmd --add-serevice={http,https} --zone=public --permanent

[C8LX@root ~]# firewall-cmd --reload

[C8LX@root ~]# firewall-cmd --list-all
  services: http https ssh

[C8LX@root ~]# echo "test page" > /var/www/html/index.html

[C8LX@root ~]# chmod -R apache:apache /var/www

[C8LX@root ~]# systemctl start httpd

[C8LX@root ~]# systemctl enable httpd

ブラウザで http://サーバIP/ へアクセスして、表示されればOK。

PHP

Install_and_configure_php7.2.11
[C8LX@root ~]# dnf install php php-fpm php-mbstring \
php-devel php-mysqlnd -y

[C8LX@root ~]# php -v
PHP 7.2.11 (cli) (built: Oct  9 2018 15:09:36) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies

[C8LX@root ~]# vim /etc/php.ini
-:;date.timezone =
+:date.timezone = Asia/Tokyo
-:expose_php = On
+:expose_php = Off
-:;mbstring.language = Japanese
+:mbstring.language = Japanese
-:;mbstring.internal_encoding =
+:mbstring.internal_encoding = UTF-8
-:;mbstring.http_input =
+:mbstring.http_input = UTF-8
-:;mbstring.http_output =
+:mbstring.http_output = UTF-8
-:;mbstring.encoding_translation = Off
+:mbstring.encoding_translation = On
-:;mbstring.detect_order = auto
+:mbstring.detect_order = auto
-:;mbstring.substitute_character = none
+:mbstring.substitute_character = none

[C8LX@root ~]# echo -n '<?php\nphpinfo();\n?>' > /var/www/html/index.php

[C8LX@root ~]# cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.bk
[C8LX@root ~]# vim /etc/php-fpm.d/www.conf
-:;listen.owner = nobody
+:listen.owner = apache
-:;listen.group = nobody
+:listen.group = apache
-:;listen.mode = 0660
+:listen.mode = 0660

[C8LX@root ~]# systemctl restart httpd

ブラウザでhttp://サーバIP/index.phpへアクセスして、phpinfo()が表示されればOK。

mysql

Install_and_configure_mysql8.0
[C8LX@root ~]# dnf install mysql-server mysql-devel -y

[C8LX@root ~]# vim /etc/my.cnf.d/mysql-server.cnf
(末尾に追記)
+:character-set-server=utf8
+:bind-address=0.0.0.0
#+:collation-server=utf8_unicode_ci

[C8LX@root ~]# vim /etc/my.cnf
([client]直下に追記)
+:default-character-set=utf8
+:[mysql]
+:default-character-set=utf8

[C8LX@root ~]# cp /usr/lib/systemd/system/mysqld.service \
/etc/systemd/system/

[C8LX@root ~]# vim /etc/systemd/system/mysqld.service
-:ExecStart=/usr/libexec/mysqld --basedir=/usr
+:ExecStart=/usr/libexec/mysqld --basedir=/usr --skip-mysqlx

[C8LX@root ~]# systemctl daemon-reload

[C8LX@root ~]# systemctl start mysqld.service

[C8LX@root ~]# systemctl status mysqld.service
   Active: active (running)

[C8LX@root ~]# netstat -ant
tcp    0    0    0.0.0.0:3306    0.0.0.0:*    LISTEN

[C8LX@root ~]# mysql -u root
(※以下大文字は任意)
mysql> create database DBNAME;
mysql> create user USERNAME@localhost;
mysql> grant all privileges on testdb.* to USERNAME@localhost;
mysql> alter user USERNAME@localhost identified by 'PASSWORD';
mysql> quit;

[C8LX@root ~]# vim test.php
<?php
    try {
        $dbcon = new PDO('mysql:host=localhost;dbname=DBNAME','USERNAME','PASSWORD');
        printf("success\n");
    }
    catch(PDOException $e){
        printf("failure\n");
        exit;
    }   
?>  

[C8LX@root ~]# php test.php
success

[C8LX@root ~]# firewall-cmd --add-service=mysql --zone=public --permanent

[C8LX@root ~]# firewall-cmd --reload

[C8LX@root ~]# firewall-cmd --list-all
  services: http https mysql ntp samba samba-client ssh

ひとまずここまで。

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

laravelのmigrateができなかったときのメモ

SQLSTATE[HY000] [2054] The server requested authentication method unknown to the clientみたいなエラーを解決できたのでそのメモ。

とりあえずマイグレーションさえしてくれればよかったのでrootで動かしてみました。

mysql> select User, Host, plugin from mysql.user;
+------------------+-----------+-----------------------+
| User             | Host      | plugin                |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+

rootユーザーの認証方式をcaching_sha2_passwordからmysql_native_passwordへ変更したらマイグレーションできました。

alter user root@localhost identified with mysql_native_password by "secret";
mysql> select User, Host, plugin from mysql.user;
+------------------+-----------+-----------------------+
| User             | Host      | plugin                |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | mysql_native_password |
+------------------+-----------+-----------------------+
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】クエリビルダでWhere句にA OR (B AND C)を書く

使用する機会があり、メモ程度にまとめてみます。

環境

PHP : 5.6.30
MySQL : 10.1.21
Laravel : 5.1.46

テーブル

以下サンプルテーブルです。

id name created_date updated_date
1 Suzuki Taro 2019-01-01 12:00:00 2019-01-01 12:00:00
2 Tanka Hanako 2019-01-25 10:00:00 2019-01-29 12:00:00
3 Takahashi Jiro 2019-02-01 16:00:00 2019-02-01 16:00:00

元のSQL

SELECT name FROM users
WHERE (created_date BETWEEN '2019-01-01 00:00:00' AND '2019-01-01 23:59:59'
OR (updated_date < '2019-02-01' AND id >= 1));

クエリビルダでの書き方

$test = Users::query()
   ->select('name')
   ->where(function ($query) {
                // created_dateが2019-01-01中
                $query->whereBetween('created_date', ['2019-01-01 00:00:00', '2019-01-01 23:59:59'])
                    // またはupdated_dateが2019-02-01より前、かつidが1以上
                    ->orWhere(function ($query) {
                        $query->where('updated_date', '<', '2019-02-01')
                            ->where('id', '>=', 1);
                    });
            })
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPでMIMETYPEから拡張子を判定する用の配列

base64encodeされたデータから、MIMETYPEを取得して拡張子を判定したかった

Codeigniterに拡張子→MIMETYPEはあったけど
その逆はなかったので、配列のkeyから拡張子を判定できるような配列が欲しかった。

ユーザーのアップロードで使いそうなのはこれくらい。

$mimetypes = array();

// ZIP関係
$mimetypes["application/x-7z-compressed"]  => ".7z";
$mimetypes["application/x-zip-compressed"] => ".zip";
$mimetypes["application/x-gzip"]           => ".gz";

// 画像関係
$mimetypes["image/gif"]  => ".gif";
$mimetypes["image/jpeg"] => ".jpg";
$mimetypes["image/png"]  => ".png";

// Word
$mimetypes["application/msword"] => ".doc";
$mimetypes["application/vnd.openxmlformats-officedocument.wordprocessingml.document"] => ".docx";

// Excel
$mimetypes["application/vnd.ms-excel"] => ".xls";
$mimetypes["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] => ".xlsx";

// PowerPoint
$mimetypes["application/vnd.ms-powerpoint"] => ".ppt";
$mimetypes["application/vnd.openxmlformats-officedocument.presentationml.presentation"] => ".pptx";

// PDF
$mimetypes["application/pdf"] => ".pdf";

以下は一覧。
ただ、keyがユニークじゃないので適宜変更必要。

$mimetypes["text/h323"] => ".323";
$mimetypes["video/3gpp2"] => ".3g2";
$mimetypes["video/3gpp"] => ".3gp";
$mimetypes["video/3gpp2"] => ".3gp2";
$mimetypes["video/3gpp"] => ".3gpp";
$mimetypes["application/x-7z-compressed"] => ".7z";
$mimetypes["audio/audible"] => ".aa";
$mimetypes["audio/aac"] => ".AAC";
$mimetypes["application/octet-stream"] => ".aaf";
$mimetypes["audio/vnd.audible.aax"] => ".aax";
$mimetypes["audio/ac3"] => ".ac3";
$mimetypes["application/octet-stream"] => ".aca";
$mimetypes["application/msaccess.addin"] => ".accda";
$mimetypes["application/msaccess"] => ".accdb";
$mimetypes["application/msaccess.cab"] => ".accdc";
$mimetypes["application/msaccess"] => ".accde";
$mimetypes["application/msaccess.runtime"] => ".accdr";
$mimetypes["application/msaccess"] => ".accdt";
$mimetypes["application/msaccess.webapplication"] => ".accdw";
$mimetypes["application/msaccess.ftemplate"] => ".accft";
$mimetypes["application/internet-property-stream"] => ".acx";
$mimetypes["text/xml"] => ".AddIn";
$mimetypes["application/msaccess"] => ".ade";
$mimetypes["application/x-bridge-url"] => ".adobebridge";
$mimetypes["application/msaccess"] => ".adp";
$mimetypes["audio/vnd.dlna.adts"] => ".ADT";
$mimetypes["audio/aac"] => ".ADTS";
$mimetypes["application/octet-stream"] => ".afm";
$mimetypes["application/postscript"] => ".ai";
$mimetypes["audio/x-aiff"] => ".aif";
$mimetypes["audio/aiff"] => ".aifc";
$mimetypes["audio/aiff"] => ".aiff";
$mimetypes["application/vnd.adobe.air-application-installer-package+zip"] => ".air";
$mimetypes["application/x-mpeg"] => ".amc";
$mimetypes["application/x-ms-application"] => ".application";
$mimetypes["image/x-jg"] => ".art";
$mimetypes["application/xml"] => ".asa";
$mimetypes["application/xml"] => ".asax";
$mimetypes["application/xml"] => ".ascx";
$mimetypes["application/octet-stream"] => ".asd";
$mimetypes["video/x-ms-asf"] => ".asf";
$mimetypes["application/xml"] => ".ashx";
$mimetypes["application/octet-stream"] => ".asi";
$mimetypes["text/plain"] => ".asm";
$mimetypes["application/xml"] => ".asmx";
$mimetypes["application/xml"] => ".aspx";
$mimetypes["video/x-ms-asf"] => ".asr";
$mimetypes["video/x-ms-asf"] => ".asx";
$mimetypes["application/atom+xml"] => ".atom";
$mimetypes["audio/basic"] => ".au";
$mimetypes["video/x-msvideo"] => ".avi";
$mimetypes["application/olescript"] => ".axs";
$mimetypes["text/plain"] => ".bas";
$mimetypes["application/x-bcpio"] => ".bcpio";
$mimetypes["application/octet-stream"] => ".bin";
$mimetypes["image/bmp"] => ".bmp";
$mimetypes["text/plain"] => ".c";
$mimetypes["application/octet-stream"] => ".cab";
$mimetypes["audio/x-caf"] => ".caf";
$mimetypes["application/vnd.ms-office.calx"] => ".calx";
$mimetypes["application/vnd.ms-pki.seccat"] => ".cat";
$mimetypes["text/plain"] => ".cc";
$mimetypes["text/plain"] => ".cd";
$mimetypes["audio/aiff"] => ".cdda";
$mimetypes["application/x-cdf"] => ".cdf";
$mimetypes["application/x-x509-ca-cert"] => ".cer";
$mimetypes["application/octet-stream"] => ".chm";
$mimetypes["application/x-java-applet"] => ".class";
$mimetypes["application/x-msclip"] => ".clp";
$mimetypes["image/x-cmx"] => ".cmx";
$mimetypes["text/plain"] => ".cnf";
$mimetypes["image/cis-cod"] => ".cod";
$mimetypes["application/xml"] => ".config";
$mimetypes["text/x-ms-contact"] => ".contact";
$mimetypes["application/xml"] => ".coverage";
$mimetypes["application/x-cpio"] => ".cpio";
$mimetypes["text/plain"] => ".cpp";
$mimetypes["application/x-mscardfile"] => ".crd";
$mimetypes["application/pkix-crl"] => ".crl";
$mimetypes["application/x-x509-ca-cert"] => ".crt";
$mimetypes["text/plain"] => ".cs";
$mimetypes["text/plain"] => ".csdproj";
$mimetypes["application/x-csh"] => ".csh";
$mimetypes["text/plain"] => ".csproj";
$mimetypes["text/css"] => ".css";
$mimetypes["text/csv"] => ".csv";
$mimetypes["application/octet-stream"] => ".cur";
$mimetypes["text/plain"] => ".cxx";
$mimetypes["application/octet-stream"] => ".dat";
$mimetypes["application/xml"] => ".datasource";
$mimetypes["text/plain"] => ".dbproj";
$mimetypes["application/x-director"] => ".dcr";
$mimetypes["text/plain"] => ".def";
$mimetypes["application/octet-stream"] => ".deploy";
$mimetypes["application/x-x509-ca-cert"] => ".der";
$mimetypes["application/xml"] => ".dgml";
$mimetypes["image/bmp"] => ".dib";
$mimetypes["video/x-dv"] => ".dif";
$mimetypes["application/x-director"] => ".dir";
$mimetypes["text/xml"] => ".disco";
$mimetypes["application/x-msdownload"] => ".dll";
$mimetypes["text/xml"] => ".dll.config";
$mimetypes["text/dlm"] => ".dlm";
$mimetypes["application/msword"] => ".doc";
$mimetypes["application/vnd.ms-word.document.macroEnabled.12"] => ".docm";
$mimetypes["application/vnd.openxmlformats-officedocument.wordprocessingml.document"] => ".docx";
$mimetypes["application/msword"] => ".dot";
$mimetypes["application/vnd.ms-word.template.macroEnabled.12"] => ".dotm";
$mimetypes["application/vnd.openxmlformats-officedocument.wordprocessingml.template"] => ".dotx";
$mimetypes["application/octet-stream"] => ".dsp";
$mimetypes["text/plain"] => ".dsw";
$mimetypes["text/xml"] => ".dtd";
$mimetypes["text/xml"] => ".dtsConfig";
$mimetypes["video/x-dv"] => ".dv";
$mimetypes["application/x-dvi"] => ".dvi";
$mimetypes["drawing/x-dwf"] => ".dwf";
$mimetypes["application/octet-stream"] => ".dwp";
$mimetypes["application/x-director"] => ".dxr";
$mimetypes["message/rfc822"] => ".eml";
$mimetypes["application/octet-stream"] => ".emz";
$mimetypes["application/octet-stream"] => ".eot";
$mimetypes["application/postscript"] => ".eps";
$mimetypes["application/etl"] => ".etl";
$mimetypes["text/x-setext"] => ".etx";
$mimetypes["application/envoy"] => ".evy";
$mimetypes["application/octet-stream"] => ".exe";
$mimetypes["text/xml"] => ".exe.config";
$mimetypes["application/vnd.fdf"] => ".fdf";
$mimetypes["application/fractals"] => ".fif";
$mimetypes["Application/xml"] => ".filters";
$mimetypes["application/octet-stream"] => ".fla";
$mimetypes["x-world/x-vrml"] => ".flr";
$mimetypes["video/x-flv"] => ".flv";
$mimetypes["application/fsharp-script"] => ".fsscript";
$mimetypes["application/fsharp-script"] => ".fsx";
$mimetypes["application/xml"] => ".generictest";
$mimetypes["image/gif"] => ".gif";
$mimetypes["text/x-ms-group"] => ".group";
$mimetypes["audio/x-gsm"] => ".gsm";
$mimetypes["application/x-gtar"] => ".gtar";
$mimetypes["application/x-gzip"] => ".gz";
$mimetypes["text/plain"] => ".h";
$mimetypes["application/x-hdf"] => ".hdf";
$mimetypes["text/x-hdml"] => ".hdml";
$mimetypes["application/x-oleobject"] => ".hhc";
$mimetypes["application/octet-stream"] => ".hhk";
$mimetypes["application/octet-stream"] => ".hhp";
$mimetypes["application/winhlp"] => ".hlp";
$mimetypes["text/plain"] => ".hpp";
$mimetypes["application/mac-binhex40"] => ".hqx";
$mimetypes["application/hta"] => ".hta";
$mimetypes["text/x-component"] => ".htc";
$mimetypes["text/html"] => ".htm";
$mimetypes["text/html"] => ".html";
$mimetypes["text/webviewhtml"] => ".htt";
$mimetypes["application/xml"] => ".hxa";
$mimetypes["application/xml"] => ".hxc";
$mimetypes["application/octet-stream"] => ".hxd";
$mimetypes["application/xml"] => ".hxe";
$mimetypes["application/xml"] => ".hxf";
$mimetypes["application/octet-stream"] => ".hxh";
$mimetypes["application/octet-stream"] => ".hxi";
$mimetypes["application/xml"] => ".hxk";
$mimetypes["application/octet-stream"] => ".hxq";
$mimetypes["application/octet-stream"] => ".hxr";
$mimetypes["application/octet-stream"] => ".hxs";
$mimetypes["text/html"] => ".hxt";
$mimetypes["application/xml"] => ".hxv";
$mimetypes["application/octet-stream"] => ".hxw";
$mimetypes["text/plain"] => ".hxx";
$mimetypes["text/plain"] => ".i";
$mimetypes["image/x-icon"] => ".ico";
$mimetypes["application/octet-stream"] => ".ics";
$mimetypes["text/plain"] => ".idl";
$mimetypes["image/ief"] => ".ief";
$mimetypes["application/x-iphone"] => ".iii";
$mimetypes["text/plain"] => ".inc";
$mimetypes["application/octet-stream"] => ".inf";
$mimetypes["text/plain"] => ".inl";
$mimetypes["application/x-internet-signup"] => ".ins";
$mimetypes["application/x-itunes-ipa"] => ".ipa";
$mimetypes["application/x-itunes-ipg"] => ".ipg";
$mimetypes["text/plain"] => ".ipproj";
$mimetypes["application/x-itunes-ipsw"] => ".ipsw";
$mimetypes["text/x-ms-iqy"] => ".iqy";
$mimetypes["application/x-internet-signup"] => ".isp";
$mimetypes["application/x-itunes-ite"] => ".ite";
$mimetypes["application/x-itunes-itlp"] => ".itlp";
$mimetypes["application/x-itunes-itms"] => ".itms";
$mimetypes["application/x-itunes-itpc"] => ".itpc";
$mimetypes["video/x-ivf"] => ".IVF";
$mimetypes["application/java-archive"] => ".jar";
$mimetypes["application/octet-stream"] => ".java";
$mimetypes["application/liquidmotion"] => ".jck";
$mimetypes["application/liquidmotion"] => ".jcz";
$mimetypes["image/pjpeg"] => ".jfif";
$mimetypes["application/x-java-jnlp-file"] => ".jnlp";
$mimetypes["application/octet-stream"] => ".jpb";
$mimetypes["image/jpeg"] => ".jpe";
$mimetypes["image/jpeg"] => ".jpeg";
$mimetypes["image/jpeg"] => ".jpg";
$mimetypes["application/x-javascript"] => ".js";
$mimetypes["application/json"] => ".json";
$mimetypes["text/jscript"] => ".jsx";
$mimetypes["text/plain"] => ".jsxbin";
$mimetypes["application/x-latex"] => ".latex";
$mimetypes["application/windows-library+xml"] => ".library-ms";
$mimetypes["application/x-ms-reader"] => ".lit";
$mimetypes["application/xml"] => ".loadtest";
$mimetypes["application/octet-stream"] => ".lpk";
$mimetypes["video/x-la-asf"] => ".lsf";
$mimetypes["text/plain"] => ".lst";
$mimetypes["video/x-la-asf"] => ".lsx";
$mimetypes["application/octet-stream"] => ".lzh";
$mimetypes["application/x-msmediaview"] => ".m13";
$mimetypes["application/x-msmediaview"] => ".m14";
$mimetypes["video/mpeg"] => ".m1v";
$mimetypes["video/vnd.dlna.mpeg-tts"] => ".m2t";
$mimetypes["video/vnd.dlna.mpeg-tts"] => ".m2ts";
$mimetypes["video/mpeg"] => ".m2v";
$mimetypes["audio/x-mpegurl"] => ".m3u";
$mimetypes["audio/x-mpegurl"] => ".m3u8";
$mimetypes["audio/m4a"] => ".m4a";
$mimetypes["audio/m4b"] => ".m4b";
$mimetypes["audio/m4p"] => ".m4p";
$mimetypes["audio/x-m4r"] => ".m4r";
$mimetypes["video/x-m4v"] => ".m4v";
$mimetypes["image/x-macpaint"] => ".mac";
$mimetypes["text/plain"] => ".mak";
$mimetypes["application/x-troff-man"] => ".man";
$mimetypes["application/x-ms-manifest"] => ".manifest";
$mimetypes["text/plain"] => ".map";
$mimetypes["application/xml"] => ".master";
$mimetypes["application/msaccess"] => ".mda";
$mimetypes["application/x-msaccess"] => ".mdb";
$mimetypes["application/msaccess"] => ".mde";
$mimetypes["application/octet-stream"] => ".mdp";
$mimetypes["application/x-troff-me"] => ".me";
$mimetypes["application/x-shockwave-flash"] => ".mfp";
$mimetypes["message/rfc822"] => ".mht";
$mimetypes["message/rfc822"] => ".mhtml";
$mimetypes["audio/mid"] => ".mid";
$mimetypes["audio/mid"] => ".midi";
$mimetypes["application/octet-stream"] => ".mix";
$mimetypes["text/plain"] => ".mk";
$mimetypes["application/x-smaf"] => ".mmf";
$mimetypes["text/xml"] => ".mno";
$mimetypes["application/x-msmoney"] => ".mny";
$mimetypes["video/mpeg"] => ".mod";
$mimetypes["video/quicktime"] => ".mov";
$mimetypes["video/x-sgi-movie"] => ".movie";
$mimetypes["video/mpeg"] => ".mp2";
$mimetypes["video/mpeg"] => ".mp2v";
$mimetypes["audio/mpeg"] => ".mp3";
$mimetypes["video/mp4"] => ".mp4";
$mimetypes["video/mp4"] => ".mp4v";
$mimetypes["video/mpeg"] => ".mpa";
$mimetypes["video/mpeg"] => ".mpe";
$mimetypes["video/mpeg"] => ".mpeg";
$mimetypes["application/vnd.ms-mediapackage"] => ".mpf";
$mimetypes["video/mpeg"] => ".mpg";
$mimetypes["application/vnd.ms-project"] => ".mpp";
$mimetypes["video/mpeg"] => ".mpv2";
$mimetypes["video/quicktime"] => ".mqv";
$mimetypes["application/x-troff-ms"] => ".ms";
$mimetypes["application/octet-stream"] => ".msi";
$mimetypes["application/octet-stream"] => ".mso";
$mimetypes["video/vnd.dlna.mpeg-tts"] => ".mts";
$mimetypes["application/xml"] => ".mtx";
$mimetypes["application/x-msmediaview"] => ".mvb";
$mimetypes["application/x-miva-compiled"] => ".mvc";
$mimetypes["application/x-mmxp"] => ".mxp";
$mimetypes["application/x-netcdf"] => ".nc";
$mimetypes["video/x-ms-asf"] => ".nsc";
$mimetypes["message/rfc822"] => ".nws";
$mimetypes["application/octet-stream"] => ".ocx";
$mimetypes["application/oda"] => ".oda";
$mimetypes["text/x-ms-odc"] => ".odc";
$mimetypes["text/plain"] => ".odh";
$mimetypes["text/plain"] => ".odl";
$mimetypes["application/vnd.oasis.opendocument.presentation"] => ".odp";
$mimetypes["application/oleobject"] => ".ods";
$mimetypes["application/vnd.oasis.opendocument.text"] => ".odt";
$mimetypes["application/onenote"] => ".one";
$mimetypes["application/onenote"] => ".onea";
$mimetypes["application/onenote"] => ".onepkg";
$mimetypes["application/onenote"] => ".onetmp";
$mimetypes["application/onenote"] => ".onetoc";
$mimetypes["application/onenote"] => ".onetoc2";
$mimetypes["application/xml"] => ".orderedtest";
$mimetypes["application/opensearchdescription+xml"] => ".osdx";
$mimetypes["application/pkcs10"] => ".p10";
$mimetypes["application/x-pkcs12"] => ".p12";
$mimetypes["application/x-pkcs7-certificates"] => ".p7b";
$mimetypes["application/pkcs7-mime"] => ".p7c";
$mimetypes["application/pkcs7-mime"] => ".p7m";
$mimetypes["application/x-pkcs7-certreqresp"] => ".p7r";
$mimetypes["application/pkcs7-signature"] => ".p7s";
$mimetypes["image/x-portable-bitmap"] => ".pbm";
$mimetypes["application/x-podcast"] => ".pcast";
$mimetypes["image/pict"] => ".pct";
$mimetypes["application/octet-stream"] => ".pcx";
$mimetypes["application/octet-stream"] => ".pcz";
$mimetypes["application/pdf"] => ".pdf";
$mimetypes["application/octet-stream"] => ".pfb";
$mimetypes["application/octet-stream"] => ".pfm";
$mimetypes["application/x-pkcs12"] => ".pfx";
$mimetypes["image/x-portable-graymap"] => ".pgm";
$mimetypes["image/pict"] => ".pic";
$mimetypes["image/pict"] => ".pict";
$mimetypes["text/plain"] => ".pkgdef";
$mimetypes["text/plain"] => ".pkgundef";
$mimetypes["application/vnd.ms-pki.pko"] => ".pko";
$mimetypes["audio/scpls"] => ".pls";
$mimetypes["application/x-perfmon"] => ".pma";
$mimetypes["application/x-perfmon"] => ".pmc";
$mimetypes["application/x-perfmon"] => ".pml";
$mimetypes["application/x-perfmon"] => ".pmr";
$mimetypes["application/x-perfmon"] => ".pmw";
$mimetypes["image/png"] => ".png";
$mimetypes["image/x-portable-anymap"] => ".pnm";
$mimetypes["image/x-macpaint"] => ".pnt";
$mimetypes["image/x-macpaint"] => ".pntg";
$mimetypes["image/png"] => ".pnz";
$mimetypes["application/vnd.ms-powerpoint"] => ".pot";
$mimetypes["application/vnd.ms-powerpoint.template.macroEnabled.12"] => ".potm";
$mimetypes["application/vnd.openxmlformats-officedocument.presentationml.template"] => ".potx";
$mimetypes["application/vnd.ms-powerpoint"] => ".ppa";
$mimetypes["application/vnd.ms-powerpoint.addin.macroEnabled.12"] => ".ppam";
$mimetypes["image/x-portable-pixmap"] => ".ppm";
$mimetypes["application/vnd.ms-powerpoint"] => ".pps";
$mimetypes["application/vnd.ms-powerpoint.slideshow.macroEnabled.12"] => ".ppsm";
$mimetypes["application/vnd.openxmlformats-officedocument.presentationml.slideshow"] => ".ppsx";
$mimetypes["application/vnd.ms-powerpoint"] => ".ppt";
$mimetypes["application/vnd.ms-powerpoint.presentation.macroEnabled.12"] => ".pptm";
$mimetypes["application/vnd.openxmlformats-officedocument.presentationml.presentation"] => ".pptx";
$mimetypes["application/pics-rules"] => ".prf";
$mimetypes["application/octet-stream"] => ".prm";
$mimetypes["application/octet-stream"] => ".prx";
$mimetypes["application/postscript"] => ".ps";
$mimetypes["application/PowerShell"] => ".psc1";
$mimetypes["application/octet-stream"] => ".psd";
$mimetypes["application/xml"] => ".psess";
$mimetypes["application/octet-stream"] => ".psm";
$mimetypes["application/octet-stream"] => ".psp";
$mimetypes["application/x-mspublisher"] => ".pub";
$mimetypes["application/vnd.ms-powerpoint"] => ".pwz";
$mimetypes["text/x-html-insertion"] => ".qht";
$mimetypes["text/x-html-insertion"] => ".qhtm";
$mimetypes["video/quicktime"] => ".qt";
$mimetypes["image/x-quicktime"] => ".qti";
$mimetypes["image/x-quicktime"] => ".qtif";
$mimetypes["application/x-quicktimeplayer"] => ".qtl";
$mimetypes["application/octet-stream"] => ".qxd";
$mimetypes["audio/x-pn-realaudio"] => ".ra";
$mimetypes["audio/x-pn-realaudio"] => ".ram";
$mimetypes["application/octet-stream"] => ".rar";
$mimetypes["image/x-cmu-raster"] => ".ras";
$mimetypes["application/rat-file"] => ".rat";
$mimetypes["text/plain"] => ".rc";
$mimetypes["text/plain"] => ".rc2";
$mimetypes["text/plain"] => ".rct";
$mimetypes["application/xml"] => ".rdlc";
$mimetypes["application/xml"] => ".resx";
$mimetypes["image/vnd.rn-realflash"] => ".rf";
$mimetypes["image/x-rgb"] => ".rgb";
$mimetypes["text/plain"] => ".rgs";
$mimetypes["application/vnd.rn-realmedia"] => ".rm";
$mimetypes["audio/mid"] => ".rmi";
$mimetypes["application/vnd.rn-rn_music_package"] => ".rmp";
$mimetypes["application/x-troff"] => ".roff";
$mimetypes["audio/x-pn-realaudio-plugin"] => ".rpm";
$mimetypes["text/x-ms-rqy"] => ".rqy";
$mimetypes["application/rtf"] => ".rtf";
$mimetypes["text/richtext"] => ".rtx";
$mimetypes["application/xml"] => ".ruleset";
$mimetypes["text/plain"] => ".s";
$mimetypes["application/x-safari-safariextz"] => ".safariextz";
$mimetypes["application/x-msschedule"] => ".scd";
$mimetypes["text/scriptlet"] => ".sct";
$mimetypes["audio/x-sd2"] => ".sd2";
$mimetypes["application/sdp"] => ".sdp";
$mimetypes["application/octet-stream"] => ".sea";
$mimetypes["application/windows-search-connector+xml"] => ".searchConnector-ms";
$mimetypes["application/set-payment-initiation"] => ".setpay";
$mimetypes["application/set-registration-initiation"] => ".setreg";
$mimetypes["application/xml"] => ".settings";
$mimetypes["application/x-sgimb"] => ".sgimb";
$mimetypes["text/sgml"] => ".sgml";
$mimetypes["application/x-sh"] => ".sh";
$mimetypes["application/x-shar"] => ".shar";
$mimetypes["text/html"] => ".shtml";
$mimetypes["application/x-stuffit"] => ".sit";
$mimetypes["application/xml"] => ".sitemap";
$mimetypes["application/xml"] => ".skin";
$mimetypes["application/vnd.ms-powerpoint.slide.macroEnabled.12"] => ".sldm";
$mimetypes["application/vnd.openxmlformats-officedocument.presentationml.slide"] => ".sldx";
$mimetypes["application/vnd.ms-excel"] => ".slk";
$mimetypes["text/plain"] => ".sln";
$mimetypes["application/x-ms-license"] => ".slupkg-ms";
$mimetypes["audio/x-smd"] => ".smd";
$mimetypes["application/octet-stream"] => ".smi";
$mimetypes["audio/x-smd"] => ".smx";
$mimetypes["audio/x-smd"] => ".smz";
$mimetypes["audio/basic"] => ".snd";
$mimetypes["application/xml"] => ".snippet";
$mimetypes["application/octet-stream"] => ".snp";
$mimetypes["text/plain"] => ".sol";
$mimetypes["text/plain"] => ".sor";
$mimetypes["application/x-pkcs7-certificates"] => ".spc";
$mimetypes["application/futuresplash"] => ".spl";
$mimetypes["application/x-wais-source"] => ".src";
$mimetypes["text/plain"] => ".srf";
$mimetypes["text/xml"] => ".SSISDeploymentManifest";
$mimetypes["application/streamingmedia"] => ".ssm";
$mimetypes["application/vnd.ms-pki.certstore"] => ".sst";
$mimetypes["application/vnd.ms-pki.stl"] => ".stl";
$mimetypes["application/x-sv4cpio"] => ".sv4cpio";
$mimetypes["application/x-sv4crc"] => ".sv4crc";
$mimetypes["application/xml"] => ".svc";
$mimetypes["application/x-shockwave-flash"] => ".swf";
$mimetypes["application/x-troff"] => ".t";
$mimetypes["application/x-tar"] => ".tar";
$mimetypes["application/x-tcl"] => ".tcl";
$mimetypes["application/xml"] => ".testrunconfig";
$mimetypes["application/xml"] => ".testsettings";
$mimetypes["application/x-tex"] => ".tex";
$mimetypes["application/x-texinfo"] => ".texi";
$mimetypes["application/x-texinfo"] => ".texinfo";
$mimetypes["application/x-compressed"] => ".tgz";
$mimetypes["application/vnd.ms-officetheme"] => ".thmx";
$mimetypes["application/octet-stream"] => ".thn";
$mimetypes["image/tiff"] => ".tif";
$mimetypes["image/tiff"] => ".tiff";
$mimetypes["text/plain"] => ".tlh";
$mimetypes["text/plain"] => ".tli";
$mimetypes["application/octet-stream"] => ".toc";
$mimetypes["application/x-troff"] => ".tr";
$mimetypes["application/x-msterminal"] => ".trm";
$mimetypes["application/xml"] => ".trx";
$mimetypes["video/vnd.dlna.mpeg-tts"] => ".ts";
$mimetypes["text/tab-separated-values"] => ".tsv";
$mimetypes["application/octet-stream"] => ".ttf";
$mimetypes["video/vnd.dlna.mpeg-tts"] => ".tts";
$mimetypes["text/plain"] => ".txt";
$mimetypes["application/octet-stream"] => ".u32";
$mimetypes["text/iuls"] => ".uls";
$mimetypes["text/plain"] => ".user";
$mimetypes["application/x-ustar"] => ".ustar";
$mimetypes["text/plain"] => ".vb";
$mimetypes["text/plain"] => ".vbdproj";
$mimetypes["video/mpeg"] => ".vbk";
$mimetypes["text/plain"] => ".vbproj";
$mimetypes["text/vbscript"] => ".vbs";
$mimetypes["text/x-vcard"] => ".vcf";
$mimetypes["Application/xml"] => ".vcproj";
$mimetypes["text/plain"] => ".vcs";
$mimetypes["Application/xml"] => ".vcxproj";
$mimetypes["text/plain"] => ".vddproj";
$mimetypes["text/plain"] => ".vdp";
$mimetypes["text/plain"] => ".vdproj";
$mimetypes["application/vnd.ms-visio.viewer"] => ".vdx";
$mimetypes["text/xml"] => ".vml";
$mimetypes["application/xml"] => ".vscontent";
$mimetypes["text/xml"] => ".vsct";
$mimetypes["application/vnd.visio"] => ".vsd";
$mimetypes["application/ms-vsi"] => ".vsi";
$mimetypes["application/vsix"] => ".vsix";
$mimetypes["text/xml"] => ".vsixlangpack";
$mimetypes["text/xml"] => ".vsixmanifest";
$mimetypes["application/xml"] => ".vsmdi";
$mimetypes["text/plain"] => ".vspscc";
$mimetypes["application/vnd.visio"] => ".vss";
$mimetypes["text/plain"] => ".vsscc";
$mimetypes["text/xml"] => ".vssettings";
$mimetypes["text/plain"] => ".vssscc";
$mimetypes["application/vnd.visio"] => ".vst";
$mimetypes["text/xml"] => ".vstemplate";
$mimetypes["application/x-ms-vsto"] => ".vsto";
$mimetypes["application/vnd.visio"] => ".vsw";
$mimetypes["application/vnd.visio"] => ".vsx";
$mimetypes["application/vnd.visio"] => ".vtx";
$mimetypes["audio/wav"] => ".wav";
$mimetypes["audio/wav"] => ".wave";
$mimetypes["audio/x-ms-wax"] => ".wax";
$mimetypes["application/msword"] => ".wbk";
$mimetypes["image/vnd.wap.wbmp"] => ".wbmp";
$mimetypes["application/vnd.ms-works"] => ".wcm";
$mimetypes["application/vnd.ms-works"] => ".wdb";
$mimetypes["image/vnd.ms-photo"] => ".wdp";
$mimetypes["application/x-safari-webarchive"] => ".webarchive";
$mimetypes["application/xml"] => ".webtest";
$mimetypes["application/xml"] => ".wiq";
$mimetypes["application/msword"] => ".wiz";
$mimetypes["application/vnd.ms-works"] => ".wks";
$mimetypes["application/wlmoviemaker"] => ".WLMP";
$mimetypes["application/x-wlpg-detect"] => ".wlpginstall";
$mimetypes["application/x-wlpg3-detect"] => ".wlpginstall3";
$mimetypes["video/x-ms-wm"] => ".wm";
$mimetypes["audio/x-ms-wma"] => ".wma";
$mimetypes["application/x-ms-wmd"] => ".wmd";
$mimetypes["application/x-msmetafile"] => ".wmf";
$mimetypes["text/vnd.wap.wml"] => ".wml";
$mimetypes["application/vnd.wap.wmlc"] => ".wmlc";
$mimetypes["text/vnd.wap.wmlscript"] => ".wmls";
$mimetypes["application/vnd.wap.wmlscriptc"] => ".wmlsc";
$mimetypes["video/x-ms-wmp"] => ".wmp";
$mimetypes["video/x-ms-wmv"] => ".wmv";
$mimetypes["video/x-ms-wmx"] => ".wmx";
$mimetypes["application/x-ms-wmz"] => ".wmz";
$mimetypes["application/vnd.ms-wpl"] => ".wpl";
$mimetypes["application/vnd.ms-works"] => ".wps";
$mimetypes["application/x-mswrite"] => ".wri";
$mimetypes["x-world/x-vrml"] => ".wrl";
$mimetypes["x-world/x-vrml"] => ".wrz";
$mimetypes["text/scriptlet"] => ".wsc";
$mimetypes["text/xml"] => ".wsdl";
$mimetypes["video/x-ms-wvx"] => ".wvx";
$mimetypes["application/directx"] => ".x";
$mimetypes["x-world/x-vrml"] => ".xaf";
$mimetypes["application/xaml+xml"] => ".xaml";
$mimetypes["application/x-silverlight-app"] => ".xap";
$mimetypes["application/x-ms-xbap"] => ".xbap";
$mimetypes["image/x-xbitmap"] => ".xbm";
$mimetypes["text/plain"] => ".xdr";
$mimetypes["application/xhtml+xml"] => ".xht";
$mimetypes["application/xhtml+xml"] => ".xhtml";
$mimetypes["application/vnd.ms-excel"] => ".xla";
$mimetypes["application/vnd.ms-excel.addin.macroEnabled.12"] => ".xlam";
$mimetypes["application/vnd.ms-excel"] => ".xlc";
$mimetypes["application/vnd.ms-excel"] => ".xld";
$mimetypes["application/vnd.ms-excel"] => ".xlk";
$mimetypes["application/vnd.ms-excel"] => ".xll";
$mimetypes["application/vnd.ms-excel"] => ".xlm";
$mimetypes["application/vnd.ms-excel"] => ".xls";
$mimetypes["application/vnd.ms-excel.sheet.binary.macroEnabled.12"] => ".xlsb";
$mimetypes["application/vnd.ms-excel.sheet.macroEnabled.12"] => ".xlsm";
$mimetypes["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] => ".xlsx";
$mimetypes["application/vnd.ms-excel"] => ".xlt";
$mimetypes["application/vnd.ms-excel.template.macroEnabled.12"] => ".xltm";
$mimetypes["application/vnd.openxmlformats-officedocument.spreadsheetml.template"] => ".xltx";
$mimetypes["application/vnd.ms-excel"] => ".xlw";
$mimetypes["text/xml"] => ".xml";
$mimetypes["application/xml"] => ".xmta";
$mimetypes["x-world/x-vrml"] => ".xof";
$mimetypes["text/plain"] => ".XOML";
$mimetypes["image/x-xpixmap"] => ".xpm";
$mimetypes["application/vnd.ms-xpsdocument"] => ".xps";
$mimetypes["text/xml"] => ".xrm-ms";
$mimetypes["application/xml"] => ".xsc";
$mimetypes["text/xml"] => ".xsd";
$mimetypes["text/xml"] => ".xsf";
$mimetypes["text/xml"] => ".xsl";
$mimetypes["text/xml"] => ".xslt";
$mimetypes["application/octet-stream"] => ".xsn";
$mimetypes["application/xml"] => ".xss";
$mimetypes["application/octet-stream"] => ".xtp";
$mimetypes["image/x-xwindowdump"] => ".xwd";
$mimetypes["application/x-compress"] => ".z";
$mimetypes["application/x-zip-compressed"] => ".zip";
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP基礎 Part6

概要

PHPの独学で学んだことをアウトプットしていく

前回の内容

PHP基礎 Part5

関数

関数とは、ある処理を一纏めにして実行する為のもの
予め用意されている「組み込み関数」と、自分で定義する「ユーザー定義関数」に分けられる

組み込み関数

strlen関数は文字列の文字数を値として返す関数
関数の中に入れる値のことを「引数」と呼ぶ

sample.php
<?php
  echo strlen("function");
  // 結果:8
?>

count関数は配列の要素数を数える関数である

sample.php
<?php
  $fruits = array("りんご", "みかん", "マスカット");
  echo count($fruits);
  // 結果:3
?>

rand関数は引数の間の数値をランダムに出力する関数である

sample.php
<?php
  echo rand(1, 10);
  // 結果:(1〜10の間の数値がランダムに出力される)
?>

ユーザー定義関数

自分で関数を定義して、作成することも可能
関数を作成する際は、「function 関数名()」が基本的な書き方となる
ユーザー定義関数でも、引数を設定することが可能で、
関数内で使う引数のことを「仮引数」と呼ぶ

sample.php
<?php
  function total($price, $tax){
    echo $price * tax;
}
  total(100, 1.1);
  // 結果:110
?>

戻り値(返り値)

関数を利用する際、関数の処理結果を返すことができる

sample.php
<?php
  function sum($score1, $score2){
    return $score1 + $score2;
}
  $totalScore = sum(68, 43);
  echo $totalScore;
  // 結果:111
?>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MAMPでmysql_upgrade

MAMPを使ってSQLのお勉強と思ったら開始早々、以下のメッセージがログの中に出て、つまづいた。

Table mysql/innodb_index_stats has length mismatch in the column name table_name. Please run mysql_upgrade.

mysql_upgradeしろとあるが、コマンドラインから打ってもそのようなコマンドはありません、と返ってくる。

MAMP→Tools→Upgrade MySQL databasesからできた。

スクリーンショット 2019-12-03 15.29.55.png

スクリーンショット 2019-12-03 15.36.12.png

Upgradeを押す

スクリーンショット 2019-12-03 15.38.09.png

完了。
MAMPでサーバー再起動するとエラーメッセージが消える。

macに慣れてないせいで、こんなショボいことに気づくのに2時間も費やした・・・。

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

PHP-CS-FixerとGit フックで治安保持活動

こちらはJoolen Advent Calendar 2019 8日目の記事です。
カレンダーのURLはこちら
Joolen Advent Calendar 2019

まえがき

PHPを書いてるとコーディング規約とか守らない人出てきますよね。
私も気付かず破ってしまうことがあります。
それを防ぐためにPHP-CS-FixerとGitフックを利用して治安を保持を目指します。

PHP-CS-Fixerとは:question:

コードの整形ツールと呼ばれるものです。
.php_cs.distという設定ファイルにルールを記述することで、コマンド一つでルールに沿ったコードに整形してくれます。
ルールはPHPの配列形式で設定します。
またFinderと呼ばれるものもあり、こちらを設定すると、整形して欲しくないファイルやディレクトリを指定できます。

例:

.php_cs.dist
return PhpCsFixer\Config::create()
    ->setRiskyAllowed(true)
    ->setRules([
        ...
        'array_syntax' => ['syntax' => 'short'], // 配列の書き方を'short'にする
        ...
    ])
    ->setFinder(PhpCsFixer\Finder::create()
        ->exclude('vendor')
        ->in(__DIR__)
    );

実行結果

-        $arrRet = array();
+        $arrRet = [];

同じようなツールにPHP_CodeSnifferというツールもあります。
こちらはphpcs.xmlという設定ファイルに記述する形式になります。
こちらに関しては今回は触れません。

Git フックとは:question:

Gitには発生したアクションに応じてスクリプトを実行する仕組みがあります。
これがGit フックです。
実行するスクリプトはGitディレクトリ(普通は.git)内のhooksディレクトリフック名をファイル名にした状態で格納されます。(.git/hooks/pre-commit等)
フックはクライアントサイドフックとサーバーサイドフックの2グループに分けられます。
公式ドキュメント
pre-commitcommit-msgなど多くある中で、今回はpre-commitフックを使用します。

pre-commit

  • コミットメッセージが入力される前に実行されます。
  • このフックがゼロでない値を返すと、コミットが中断されます。
  • この検査は git commit --no-verify で飛ばすこともできます。
  • ここではコーディングスタイルの検査(lintを実行するなど)や、行末の空白文字の検査(デフォルトのフックがまさにそうです)、新しく追加されたメソッドのドキュメントが正しいかどうかの検査といったことが可能です。

PHP-CS-Fixerのインストール

composerを利用してインストールします。

$ composer require --dev friendsofphp/php-cs-fixer
 ...
$ vendor/bin/php-cs-fixer -V
PHP CS Fixer 2.16.1 Yellow Bird by Fabien Potencier and Dariusz Ruminski

PHP-CS-Fixerの設定を行う

早速設定をしていきたいところですが、PHP-CS-Fixerの設定を全てやっていると膨大な時間がかかります。
そこで、設定をパッケージ化して公開してくれている方がいるので、自分にあった物を見つけて利用しましょう。
私が公開しているものhttps://github.com/suin/php-cs-fixer-rules
などありますので、探してみてください。

探して無事インストールできたら、今度は設定を少々変えていきましょう。
ほとんどのパッケージはルールが上書きできるようになっているはずです。
php-cs-fixer-configuratorを参考にして、設定を書き換えていきましょう。

整形予定の確認。 そして整形

設定が完了したら整形!
といきたいところですが、その前に整形予定を確認して、設定の間違いがないか以下のコマンドで確認しましょう。

$ vandor/bin/php-cs-fixer fix --dry-run --diff

こちらのコマンドは
fixによって設定ファイルに沿って整形
--dry-runオプションによって整形せず整形予定ファイルの表示
--diffオプションによって整形内容の表示となっています。

実行して予期せぬ変更がなければ以下のコマンドで実際に整形します。

$ vandor/bin/php-cs-fixer fix

pre-commitフックでPHP-CS-Fixerを実行

PHP-CS-Fixerによる整形ができるようになったので、最初に紹介したpre-commitフックを利用して整形前のコードがコミットされないようにします。

.git/hooksディレクトリにpre-commitという名前でファイルを作成します。

$ touch .git/hooks/pre-commit

作成したファイルを修正してPHP-CS-Fixerを実行するようにします。

pre-commit
#!/bin/bash

# ディレクトリ定義
ROOT_DIR=$(git rev-parse --show-toplevel)
LIST=$(git status | grep -e '\(modified:\|new file:\)'| grep '\.php' | cut -d':' -f2 )

# php-cs-fixer
error=false
for file in $LIST
do
    # --path-modeをintersectionにすることで、Finderが無視されないようにします。
    $ROOT_DIR/vendor/bin/php-cs-fixer fix --path-mode=intersection --dry-run $ROOT_DIR/$file > /dev/null 2>&1
    if [ $? != 0 ]; then
        echo -e "   please, cs fix to $ROOT_DIR/$file"
        error=true
    fi
done

if "${error}"; then
    echo
    echo -e "\033[31mCommit fail\033[m please run \"vendor/bin/php-cs-fixer fix\" command"
    exit 1
fi

これで、規約を無視したコードをコミットしようとすると以下のように表示されるようになります。

please, cs fix to /path/to/invalid-file.php

Commit fail please run "vendor/bin/php-cs-fixer fix" command

これで治安保持できるようになりました!
コーディング規約にそってないコードは精神衛生上よろしくないので、駆逐していきましょう!

明日は@joolenkoyamaさんのEC-CUBE4のContainerの探検記録です。

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

Laravel の "認可" まとめ(Gate, Policy 等)

はじめに

この記事は Laravel Advent Calendar 2019 - Qiita の 4日目 の記事です?

「この認可処理はどこに書くべきか」みたいなディスカッションから
Laravel の認可機能を深掘りする機会があったので、
改めて整理してみたいと思います?

認証については、よろしければこちらも!
Laravel の Guard(認証) って実際何をやっているのじゃ?

そもそも "認可" とはなんなのか

著者に対してだけブログ記事の更新を許可する
みたいなやつが "認可" です。

"認可" を真面目に考察したら、それだけで一記事書けてしまう、深い深いテーマです:hole:

"認可" についてのざっくりとした理解

いったんここでは、以下の理解で記事を進めようと思います。
(異論あればコメントにお願いします!)

  • 特定の条件に対して、リソースに対するアクションの権限を与える
    (e.g. 「記事の著者」という条件に対して、記事を更新する権限を与える)
  • 多くの場合、認証に基づく
    (著者としてログイン済の場合に↑の認可が成り立つ)

クラスメソッドさんの以下の記事がていねいな解説でわかりやすいので、
深掘りしたい方はぜひご参考ください!
よくわかる認証と認可

Laravel で "認可" する方法

ここからが本題?
Laravel では認可のために以下の仕組みが用意されています。

  • Gate
  • Policy
  • Request -> authorize()

それぞれ詳しく見ていきます?

Gate

Gates are Closures that determine if a user is authorized to perform a given action and are typically defined in the App\Providers\AuthServiceProvider class using the Gate facade.
https://laravel.com/docs/6.x/authorization#gates

ゲートは、特定のアクションを実行できる許可が、あるユーザーにあるかを決めるクロージャのことです。
https://readouble.com/laravel/6.x/ja/authorization.html#%E3%82%B2%E3%83%BC%E3%83%88

認可について「リソースに対するアクションの権限を与える」と上述しましたが、
なんといきなりこの「リソース」が登場しないのが Gate です?

  • クロージャーでシンプルに実装できる
  • モデルやリソースに紐づかないアクションも認可できる

というのが Gate の特徴です。

Gate で認可するには、 AuthServiceProviderboot メソッド内に Gate ファサードを使って定義します。

AuthServiceProvider.php
Gate::define('edit-settings', function ($user) {
    return $user->isAdmin;
});

ドキュメントには

Gates are most applicable to actions which are not related to any model or resource, such as viewing an administrator dashboard.
管理者のダッシュボードのように、モデルやリソースとは関連しないアクションに対し、ゲートは主に適用されます。

と書かれていますが、リソースに対する認可が「できない」わけではありません。
サンプルにある通り以下のような実装も可能です。

AuthServiceProvider.php
Gate::define('update-post', function ($user, $post) {
    return $user->id === $post->user_id;
});

ただしなんでもかんでも Gate に実装すると破綻するので、原則

  • モデルやリソースに関するものは Policy
  • それ以外は Gate

のように使い分けるのが良さそうです。

Policy

policies, like controllers, group their logic around a particular model or resource.
//
Once the policy has been registered, you may add methods for each action it authorizes.
https://laravel.com/docs/6.x/authorization#writing-policies

ポリシーとは、特定のモデルやリソースに対するロジックをまとめたものです。
//
ポリシーは特定のモデルやリソースに関する認可ロジックを系統立てるクラスです。
https://readouble.com/laravel/6.x/ja/authorization.html#%E3%82%A4%E3%83%B3%E3%83%88%E3%83%AD%E3%83%80%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3

Policy については「モデルやリソースに対する」と明記されており、より "認可" らしい(?)機能です。

使い方の詳細はドキュメントに記述されているので省略しますが、
以下の手続きで使えます。

  • Policy クラスを作る
  • AuthServiceProvider で Policy クラスを登録する(省略可※後述

Policy クラスはモデルに応じて、クラス内のメソッドはアクションに応じて作ります。

以下ドキュメントより引用

PostPolicy.php
class PostPolicy
{
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

Policy は コントローラーや middleware で can cant を呼び出して利用します。

PostController.php
if ($user->can('update', $post)) {
    //
}
routes/web.php
Route::put('/post/{post}', function (Post $post) {
    // 現在のユーザーはこのポストを更新できる
})->middleware('can:update,post');

Request -> authorize()

実は Request クラスでも認可処理を書くことができます。
artisan で Request クラスを作ると以下のメソッドが作られるはず。
このメソッド内でユーザーアクションを認可できます。

    public function authorize() {
        return true;
    }

自分はこの authorize() を触ることはほぼないんだけど、どういうときに使うのかな??
「ポリシーを使いたいけど、 $user->can() を Controller に書きたくないし、 middleware として使うのにも適していない」
みたいなシーンがあれば、ここに書くと良いのかもしれない。
Request クラスの中に認可とバリデーションがまとまってると、後から見たときにわかりやすいかも?
機会があれば試してみよう?

Gate / Policy の便利機能たち

モデルポリシーの自動検出機能(Auto-Discovery Of Model Policies)

Laravel 5.8 で追加された機能です。
Policy を使うには モデルとポリシーのマッピングを AuthServiceProvider で登録する必要がありましたが、
標準命名規則に従っている場合はこの登録作業が不要になりました。

app/User.php というモデルがある場合は app/Policies 下の UserPolicy をPolicy として自動検出します。
しかしほとんどの場合、 app 直下にモデルを置くことはないでしょう。
app/Models 以下ににモデルを配置したときは app/Models/Policies に Policy を書けということになりますが、これは気持ち悪い・・・
こんなとき、 AuthServiceProviderboot() 内で以下のように定義しておけば、app/Policies 以下で自動検出してくれるようです?

AuthServiceProvider.php
Gate::guessPolicyNamesUsing(function ($modelClass) {
    return 'App\\Policies\\' . class_basename ($modelClass).'Policy';
});

認可レスポンスの改善(Improved Authorization Responses)

Laravel 6 で追加された機能です。
Gate や Policy で true / false を返す代わりに Response::allow() / Response::deny() を返し、
呼び出し側では Gate::inspect() を呼び出すことで、 Policy から認可レスポンスを受け取ることができるようになりました。
deny 時に Policy で詳細なメッセージを設定してそれを画面表示する、みたいなことが簡単にできるようになりましたね?

PostPolicy.php
public function update(User $user, Post $post)
{
    return $user->id === $post->user_id
                ? Response::allow()
                : Response::deny('You do not own this post.');
}
PostController.php
$response = Gate::inspect('update', $post);

if ($response->allowed()) {
    // アクションは認可された…
} else {
    echo $response->message();
}

ゲストユーザーゲート/ポリシー(Guest User Gates / Policies)

これまでゲートやポリシーでは、未認証のユーザーに対しては一律 false を返していましたが、
以下のようにタイプヒントで $user を nullable にすることでチェックをパスさせられるようになりました。

ドキュメントには以下の例が載っていて

AuthServiceProvider.php
Gate::define('update-post', function (?User $user, Post $post) {
    // ...
});

どう考えてもダメな使い方(未ログインなら記事を編集できちゃう)なので、「この機能いる??」と疑問が湧きます?
ユースケースとしては、以下の PR への Gary さんのコメントがわかりやすかったです。

$this->authorize('view', $promotion) -> Is it christmas time? You can view that promotion, even as a guest.
$this->authorize('view', $picture) -> Is the picture publicly viewable? You can view those pictures, even as a guest.
$this->authorize('view', $page) -> Is this page published? You can view the page, even as a guest.
$this->authorize('view', $dashboard) -> Is this guest from a known EU IP address? You can view the dashboard, even as guest.

最初に認可は「多くの場合、認証に基づく」と書きましたが、
日時・リソースの状態・IPなど、 認証に基づかない認可を実現したいときに、この機能を利用できます。

PR コメントで賛否のディスカッションが盛り上がっていて面白かったです。
[5.7] Allow Gates / Policies To Accept "Guests"

まとめ

やはり認可の基本は Gate / Policy ですね!
バージョンアップ毎に機能改善が行われているのでじゃんじゃん活用しましょう?

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

[PHP]FizzBuzzゲームをifとforを使わないで作った結果www

1.rangeで配列生成してarray_filterで抽出してからarray_fill_keysで文字を埋めてarray_replaceで合体してarray_mapで要素を出力

fizz_buzz.php
<?php
$array = range(0, 100);

$fizz_array = array_fill_keys(array_filter($array, function($value) {
    return $value % 3 === 0;
}), 'Fizz');

$buzz_array = array_fill_keys(array_filter($array, function($value) {
    return $value % 5 === 0;
}), 'Buzz');

$fizz_buzz_array = array_fill_keys(array_filter($array, function($value) {
    return $value % 3 === 0 && $value % 5 === 0;
}), 'FizzBuzz');


$result = array_replace($array, $fizz_array, $buzz_array, $fizz_buzz_array);
unset($result[0]);

array_map($result, function($value){
    echo $value . '<br>';
});

ちなみにarray_filterの代わりに

range(0, 100, 3); // rangenの第3引数を指定すると要素の増加数をしていできる。

でも可。

2.クラスを使う

fizzbuzz.php
<?php
class FizzBuzz {
    const FIZZ = 3;
    const BUZZ = 5;
    public static $counter = 0;
    private $number;
    public function __construct () {
        self::$counter++;
        $this->number = self::$counter;
    }

    public function build() {
        return self::getFizzBuzz() ? 'FizzBuzz' :
            self::getFizz() ?  'Fizz':
                self::getBuzz() ? 'Buzz' : $this->number;
    }

    private function getFizzBuzz() {
        return $this->number % self::FIZZ === 0 && $this->number % self::BUZZ === 0;
    }

    private function getFizz() {
        return $this->number % self::FIZZ === 0;
    }

    private function getBuzz() {
        return $this->number % self::BUZZ === 0;
    }
}

$array = array_fill(1, 100, 'Inori Minase');

array_walk($array, function(&$value){
    $fizz_buzz_incetance = new FizzBuzz();
    $value = $fizz_buzz_incetance->build();
});

$obj = new ArrayObject($array);
$it = $obj->getIterator();

while ($it->valid()){
    echo $it->current() . "</br>";
    $it->next();
}

FizzBuzzCounterクラスは、インスタンスが生成されるたびにカウンターを1づつ増やしていくよ。

まとめ

困ったら公式ドキュメントを読もう!

おまけ

chain of responsibility

<?php
class FizzBuzzClient {
    public static $counter = 0;
    private $number;
    public function __construct () {
        self::$counter++;
        $this->number = self::$counter;
    }

    public function getNumber() {
        return $this->number;
    }
}

abstract class Handler {
    private $next;

    public function setNext(Handler $next) {
        $this->next = $next;
    }

    public function request (FizzBuzzClient $client) {
        $this->resolve($client) ? $this->done() : $this->request($client);
    }

    abstract protected function resolve(FizzBuzzClient $client);

    abstract protected function done (FizzBuzzClient $client);

}

class NoHandler extends Handler {
    protected function resolve (FizzBuzzClient $client) {
        return false;
    }

    protected function done (FizzBuzzClient $client) {
        return false;
    }
}

class FizzBuzzHandler extends Handler {
    protected function resolve (FizzBuzzClient $client) {
        return $client->getNumber % 3 === 0 && $client->getNumber % 5;
    }

    protected function done (FizzBuzzClient $client) {
        return 'FizzBuzz';
    }
}

class FizzHandler extends Handler {
    protected function resolve (FizzBuzzClient $client) {
        return $client->getNumber % 3 === 0;
    }

    protected function done (FizzBuzzClient $client) {
        return 'Fizz';
    }
}

class BuzzHandler extends Handler {
    protected function resolve (FizzBuzzClient $client) {
        return $client->getNumber % 3 === 0 && $client->getNumber % 5;
    }

    protected function done (FizzBuzzClient $client) {
        return 'Buzz';
    }
}

class LastHandler extends Handler {
    protected function resolve (FizzBuzzClient $client) {
        return true;
    }

    protected function done (FizzBuzzClient $client) {
        return $client->getNumber;
    }
}

$array = array_fill(1, 100, 'Inori Minase');

$no_handler = new NoHandler();
$fizz_buzz = new FizzBuzzHandler();
$fizz = new FizzHandler();
$buzz = new BuzzHandler();
$last = new LastHandler();

$no_handler->setNext($fizz_buzz)->setNext($fizz)->setNext($buzz)->setNext($last);

foreach ($array as $key => $value) {
$fizz_buzz_client = new FizzBuzzClient();
    $no_Handler->request($fizz_buzz_client);
}

ここまで書いたけどメモリ足りなくて断念した。

おまけ2

「何って...俺はただif文を使っただけだが...?」キョトン

<?php
for ($i = 1; $i <= 100; $i++) {
    if ($i % 3 == 0 && $i % 5 == 0) {
        echo 'FizzBuzz</br>';
    } elseif ($i % 3 == 0) {
        echo 'Fizz</br>';
    } elseif ($i % 5 == 0) {
        echo 'Buzz</br>';
    } else {
        echo $i .'</br>';
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Moodle 3.7 マニュアル - AMP をインストールする

原文

AMP, stands for Apache, MySQL & PHP. This is not the only platform on which Moodle runs but is the most common and fine for basic installations.

(略)
Contents

1 First a word about PostgreSQL
2 Mac OS X(略)
3 Linux
4 Windows(略)
4.1 Installer packages and components(略)
5 Vista and Windows 7(略)

First a word about PostgreSQL

If you would prefer to use the PostgreSQL database (and you should consider it) you can - when using the package type installers - just install it instead of MySQL. MySQL tends to be the universal choice with the simpler 'one-click' installers. For a 'one-click' installer with PostgreSQL, Apache and PHP you can check BitNami, it supports Windows (WAPP), Linux (LAPP) and Mac (MAPP).

3 Linux

You should install the packages from your distribution's repository for Apache, PHP and MySQL. You will almost certainly need additional extensions for PHP (e.g. the extension for the database). The packaged versions of Moodle are not recommended (it's not much harder to install from moodle.org download)

See (for example):

While one-click installers (e.g. XAMPP or BitNami LAMP Stack) exist for Linux, it is so simple to install the components the "right" way that they seem pointless. Using the standard method will make it much easier for you to obtain help and support.

Of course, if you wish to (or you need a particularly new version) you can compile all or some of the elements from source. All the elements have good documentation. The tricky one is PHP and some guidance for Debian/Ubuntu is here: Compiling PHP from source

4 Windows(略)

4.1 Installer packages and components(略)

5 Vista and Windows 7(略)

カテゴリ:インストール

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

Moodle 3.8 マニュアル - AMP をインストールする

原文

AMP, stands for Apache, MySQL & PHP. This is not the only platform on which Moodle runs but is the most common and fine for basic installations.

(略)
Contents

1 PostgreSQL について一言
2 Mac OS X
3 Linux
4 Windows
4.1 Installer packages and components
5 Vista and Windows 7

1 PostgreSQL について一言

PostgreSQL データベースがお好みなら(まあ、そうであるべきなのですが)ば、単に MySQL のかわりに、パッケージタイプのインストーラで、PostgreSQL をインストールしてください。MySQL は、'ワンクリック' インストーラによる一般的な選択となっています。PostgreSQL、Apache と PHP の'ワンクリック' インストーラでは、BitNami を選択できます。BitNami は、Windows (WAPP), Linux (LAPP) and Mac (MAPP) をサポートしています。(訳者注:AWS 用の AMI もあります。)

2 Mac OS X

(略)

3 Linux

You should install the packages from your distribution's repository for Apache, PHP and MySQL. You will almost certainly need additional extensions for PHP (e.g. the extension for the database). The packaged versions of Moodle are not recommended (it's not much harder to install from moodle.org download)

See (for example):

While one-click installers (e.g. XAMPP or BitNami LAMP Stack) exist for Linux, it is so simple to install the components the "right" way that they seem pointless. Using the standard method will make it much easier for you to obtain help and support.

Of course, if you wish to (or you need a particularly new version) you can compile all or some of the elements from source. All the elements have good documentation. The tricky one is PHP and some guidance for Debian/Ubuntu is here: Compiling PHP from source

4 Windows

(略)

4.1 Installer packages and components

(略)

5 Vista and Windows 7

(略)

カテゴリ:インストール

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

Moodle 3.7 マニュアル - カテゴリ:管理者

原文

注:現在私達は、ドキュメントを再構築して、先生と管理者を一緒にしているところです。したがって、このカテゴリは消える運命にあります。Category:Site administration が、サイトの管理設定のドキュメントページとして使用されることができます。

管理者ドキュメントのページのインデックスです。
サブカテゴリ

このカテゴリには、17 のサブカテゴリがあり、全部で 17 あります。

A

Accessibility
Authentication

B

Blog

C

Course

E

Environment
Error

I

Installation

M

Mac OS X

N

Notes

P

Performance

Q

Quiz

R

Restrict access

S

Search
SQL databases

T

Themes

U

Usability

W

Workshop

Pages in category "Administrator"

The following 31 pages are in this category, out of 31 total.
A

Administrator do's and don'ts
Ajax marking block
Arguments in favour of PostgreSQL

B

Banner LMB

C

Can not log in
Code syntax highlighting
Course Management block

D

DNS

E

Elgg
error/admin/cronerrorpassword

H

Hotpot settings

I

Installation guide for Windows using EasyPHP
Installations 1000 plus
Installations 10000 plus
Installations 5000 plus
Installing APC in Windows
Installing Moodle on Debian based distributions
ISA Server

L

Linking Moodle and Docs

M

Masquerading
Mathematics tools FAQ
Migration from Moodle

P

Portable recording devices

R

RedHat Linux installation
Development:Replacing icons with CSS3

S

Search engine optimization

T

Theme directory

U

Using Moodle book

V

VMware installation

W

Development:Web services API
Windows installation using XAMPP

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

Moodle 3.7 マニュアル - Unix 又は Linux への インストール

原文

以下のページには、Unix 又は Linux に特化したインストールの情報があります。この情報は、Moodle コミュニティにより提供されたものであり、完全にはチェックされていないかもしれず、(しばしばとても)古いかもしれません。有益であればということで提供されています。

  • Step-by-step Installation Guide for Ubuntu(翻訳準備中)
  • Installation on Ubuntu using Git(翻訳準備中)
  • Red Hat Enterprise Linux へのインストール
  • FreeBSD Installing(翻訳準備中)
  • Installing Moodle on Debian based distributions (翻訳準備中)

カテゴリ:インストール

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

Wordpressページの特定の箇所だけを任意で変更できるようにする。

はじめに

WordPressサイトをなんのために作るか。
だいたいの場合その答えは「パソコンの分からない人が楽に管理できるウェブサイトをつくる」に集約される。言い換えれば、クライアントが電話で「ここ分からないんですけど……」と聞いてくるようなサイトなら、それは存在する意味がないのだ。
だからこそ、作り手には「見つけやすい、迷いにくい、操作しやすい」設定ページを作ることが求められる。と思う。筆者は。

……とはいえ、初心者にとっては設定ページを作ることさえ簡単ではないというのも事実。
ここではタイトルの通りウェブサイトの特定の箇所を素人でも簡単に変更できるシステムの作り方について説明するので、「これウチで使えそう!」と思ったら使ってみて欲しい。

やること

1575469743669.jpg

STEP1:その部分を操作するための固定ページをつくる

いつも通り、左メニューの「固定ページ」→「新規追加」から編集画面に入り、右側にある「公開」ボタンを押して専用の固定ページを作ってやればよい。
肝心なのは、このとき公開状態を「非公開」にしておくこと。というのも、この固定ページそれ自体はユーザーに見せないからだ。
あくまでここで利用するのは、ここで入力した項目のほうなのである。

1575474316481.jpg

ちなみに今回は「トップページバナー」という項目を作っている。
※このあと筆者はなんやかんやあってこの固定ページの名前を「設定:トップページバナー」に変えました。

STEP2:管理画面の見えるところに固定する

固定ページを編集画面として流用している関係上、そのままだと先ほど作った「トップページバナー」は他の固定ページに埋もれることになる。
それでは困るので、先ほど作ったページを管理画面の見やすい位置……ようは左に見えてる黒いメニューに持ってこよう。

まずは先ほど作った「設定:トップページバナー」を開いてみよう。

1575684262302.jpg

このような画面が出るはずだが、注目してほしいのは以下の部分。

1575684232542.jpg

これが必要になるのでどこかにメモしておく。
そして、functions.phpに以下のコードを記述しよう。

functions.php
//管理画面に優先度メニューを追加
function mt_add_pages() {
    add_menu_page( '設定:トップページバナー', '設定:トップページバナー', 'edit_pages', 'post.php?post=8&action=edit', '', 'dashicons-admin-customizer', 3);
}
add_action('admin_menu', 'mt_add_pages');

成功すると、管理画面が以下のように様変わりする。

1575684841650.jpg

あとは、新しく表示された「設定:トップバナー」をクリックすればいつでもこの編集画面に移動できる。

余談

ちなみに、先ほどの関数のカスタマイズ方法も載せておく。

functions.php
//管理画面に優先度メニューを追加
function mt_add_pages() {
    add_menu_page( '[管理画面で表示されるタイトル]', '[管理画面で表示されるタイトル]', 'edit_pages', '[固定ページのURL、一部分でもOK]', '', '[タイトルの左に来るアイコンを指定]', [半角数字でこのメニューを表示する順番を書く]);
}
add_action('admin_menu', 'mt_add_pages');

※アイコンはこちらのページ、表示する順番はこのページに掲載されている。
※編集画面がウチのとなんか違う!と不安になった人は「Classic Editor」でググれ。

STEP3:固定ページに入力項目を作成する

ところで今の固定ページ、そのままだと「タイトル」「パーマリンク」「本文」くらいしか入力項目がない。
ということは、この入力項目を設定することも必要となる。
方法は色々あるが、今回はプラグイン「Advanced Custom Field」、通称ACFを使って項目の設定を行おう。

1581316259382.jpg

プラグインに頼らない手もあるにはあるが、今回コレを選んだのには訳がある。
このACF、入力項目を簡単に「作る」ことができるだけでなく、「消す」こともできるからだ。

ACFの詳しい使い方はこちらのブログこのブログに載っている。
細かい部分はそちらに譲るとして、今回はざっくり説明しよう。

1581318905858.jpg

まず、フィールドタイプを選択する。
次に、フィールドに英数字でてきとうな内容を入力する。(フィールドラベルではないので注意だ。)
以上。これで終わりだ。

おまけ

上述した「消す」とは、以下の画像にあるステータスのことを指す。(下の方にあります)
1581316853370.jpg

このようにチェックを入れることで、本来あったはずの「アイキャッチ」や「コンテンツエディタ」を消すことができるぞ。
たとえばこんなふうに。
1581319101084.jpg

STEP4:出力コードをかく

1581319186014.jpg
さて、入力項目を作った以上、それを出力する必要も当然ある。
今回、独自の内容を挿入したい場所はトップページ(index.php)だから、index.phpを操作する。

1581318044646.jpg
まずは見た目を整えてやり。。。

次に、以下のコードを文章を記入したい場所に記述する。

index.php
<?php echo get_field('mycomment', 8); ?>

すると……
1581319341492.jpg
よし。うまくできた。

ところで、先ほどのコードで出てきた8、なんの数字か覚えているだろうか?

1575684232542.jpg

上の方で使ったページID。
ACFはこのように「フィールド名」と「入力画面となるページのページID」を入力することで、特定の固定ページに記入した内容を無関係な別のページに表示することができる。
この仕組みを応用することで、あたかも特定のページから別のページの一部分だけを編集できるような仕組みを作り上げることができるのだ。
なお、最終的に出来上がったのは以下のようなコードになる。

index.php
<style>
.in_the_sukima{
    background-color: #ffffff;
    border: double 6px #cd2653;
    width: 90%;
    margin: 1em auto 0 auto;
    padding: 1em 2em;
}
</style>
<div class="in_the_sukima">
    <p><?php echo get_field('mycomment', 8); ?></p>
</div>

もしあなたがこの記事を利用するつもりなら、'mycomment'のところをあなたが設定したフィールド名に、8のところを設定ページのページIDに変えればうまくいくはずだ。

おわりに

分かりにくい点などあれば編集リクエストをお願いします。

参考文献

https://qiita.com/konweb/items/330f735a899e448ef876

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

【Laravel6】日本語化

内容

laravelに追加した認証処理とかを日本語化したい

やったこと

1.設定ファイルのlangをjaに変更

2.コマンド実行
https://readouble.com/laravel/5.6/ja/validation-php.html
にある下記コマンドをコマンドプロンプト/VSCodeターミナルで実行するとディレクトリが作成される
(Windows環境ではまだ試していません。)とあるが問題なく可能

php -r "copy('https://readouble.com/laravel/5.6/ja/install-ja-lang-files.php', 'install-ja-lang.php');"
php -f install-ja-lang.php
php -r "unlink('install-ja-lang.php');"

3.jsonファイル追加

下記を追加して、それぞれの置き換え文言を追加していく

resources/lang/ja.json
{
    "Register": "参加登録",
    "Login": "ログイン",
    "Name": "名前",
    "E-Mail Address": "メールアドレス",
    "Password": "パスワード",
    "Confirm Password": "パスワード再入力",
    "Remember Me": "ログイン情報を記録",
    "Forgot Your Password?": "パスワード忘れの場合",
    "Reset Password": "パスワードリセット",
    "Send Password Reset Link": "パスワードリセットメールを送信",
    "Verify Your Email Address": "メールアドレスを認証してください",
    "A fresh verification link has been sent to your email address.": "新規の認証リンクを再度送信しました",
    "Before proceeding, please check your email for a verification link.": "送信メール内の認証リンクをから認証を行ってください。",
    "If you did not receive the email,": "メールが届いていない場合、",
    "click here to request another.": "こちらクリックで再度メール送信します。"
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelでページャーを常時表示する

やりたいこと

Laravelのデフォルトのペジネータは2ページ目がないと非表示になってしまう。
これを常時表示したい。

やりかた

php artisan vendor:publish --tag=laravel-paginationを実行し、ペジネータのテンプレートを出力する。
/resources/views/vendor/pagination/bootstrap-4.blade.phpに出力されたファイルを編集する。

bootstrap-4.blade.php
@if ($paginator->hasPages())
    <nav>
        <ul class="pagination">
            {{-- Previous Page Link --}}
            @if ($paginator->onFirstPage())
                <li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
                    <span class="page-link" aria-hidden="true">&lsaquo;</span>
                </li>
            @else
                <li class="page-item">
                    <a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">&lsaquo;</a>
                </li>
            @endif
            {{-- Pagination Elements --}}
            @foreach ($elements as $element)
                {{-- "Three Dots" Separator --}}
                @if (is_string($element))
                    <li class="page-item disabled" aria-disabled="true"><span class="page-link">{{ $element }}</span></li>
                @endif
                {{-- Array Of Links --}}
                @if (is_array($element))
                    @foreach ($element as $page => $url)
                        @if ($page == $paginator->currentPage())
                            <li class="page-item active" aria-current="page"><span class="page-link">{{ $page }}</span></li>
                        @else
                            <li class="page-item"><a class="page-link" href="{{ $url }}">{{ $page }}</a></li>
                        @endif
                    @endforeach
                @endif
            @endforeach
            {{-- Next Page Link --}}
            @if ($paginator->hasMorePages())
                <li class="page-item">
                    <a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">&rsaquo;</a>
                </li>
            @else
                <li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
                    <span class="page-link" aria-hidden="true">&rsaquo;</span>
                </li>
            @endif
        </ul>
    </nav>
@endif

最初の行のif文が、$paginator->hasPages()の条件でページがなければページャーを出力しないようになっているため、このif文をとってやれば常時出力されるようになる。

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