20210129のPHPに関する記事は19件です。

vscodeでxdebug3のdocker環境を作る

はじめに

2020年11月25日にxdebug 3.0.0がリリースされました。
それを知らずにdockerでxdebugの環境を作って、「ブレイクポイントで止まってくれない、なんでやねん」ってなったのでまとめます。

フォルダ構成

xdebug2からxdebug3に移行のために、編集するのはphp.iniだけですがDockerfilやvscodeのlaunch.jsonの解説もします。
docker-composeは省略。

php
├── Dockerfile
└── php.ini

php.ini

xdebug3ではxdebug2と記述方法が異なるようです。

xdebug2のphp.iniのxdebugの設定

xdebug.remote_host = docker.host.internal
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 0
xdebug.remote_enable = 1
xdebug.remote_handler = "dbgp"
xdebug.remote_port = 9000

xdebug3のphp.iniiのxdebugの設定

xdebug.client_host = docker.host.internal
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.discover_client_host = 0
xdebug.remote_handler = "dbgp"
xdebug.client_port = 9000
xdebug2 xdebug3の変更点
xdebug.remote_host xdebug.client_host に置き換え
xdebug.remote_autostart xdebug.mode=debug と xdebug.start_with_request=yes で設定
xdebug.remote_enable xdebug.mode=debugで設定
xdebug.remote_connect_back xdebug.discover_client_host に置き換え
xdebug.remote_handler  変更無し
xdebug.remote_port xdebug.client_port に置き換え

これら以外にも変更点があるので、詳しくはこちらを参照
https://xdebug.org/docs/upgrade_guide

Dockerfile

FROM php:7.4-fpm
SHELL ["/bin/bash","-c"]

COPY ./php.ini /usr/local/etc/php/php.ini

RUN apt-get update && \
    apt-get -y install git unzip libzip-dev libicu-dev libonig-dev && \
    pecl install xdebug && \ #xdebugのインストール
    docker-php-ext-enable xdebug  #

WORKDIR /work

ポイントはpecl install xdebugdocker-php-ext-enable xdebug

  • 2021年1月29日、現在ではpecl install xdebugを行うとxdebug3がインストールされます。

  • xdebugを使うにはイントールされた、xdebug.soのパスをphp.iniにzend_extension = パスを追記して、登録しなければなりません。docker-php-ext-enable xdebugのコマンドを叩くと自動でこの作業を行ってくれます。

launch.json

vscode側の設定になります。

"configurations":[
 {
   "name": "XDebug on docker",
   "type": "php",
   "request": "launch",
   "port": 9000,//php.iniで設定したポート番号
   "pathMappings": {
      // {docker上のdocument root}:{ローカルのdocument root}
      "/work":"${workspaceRoot}/src"
    }
  }
]

これをlaungh.jsonの中に追記します。

これでxdebugを動かすための環境ができました。

参考にさせて頂いた記事

Dockerで構築したPHP環境をxdebugでデバッグ(vscode)
Xdebug3.0.0がリリースされたので、ver2からの雑な設定コンバート

最後に

"port:9000"のポート番号はvscodeが開いてるんですね。
xdebugが開いているものと思ってました。

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

【macOS×XAMPP】sendmail.iniなんてないけど、どうやってPHPでメール送るの??(Gmail経由)

環境

OS → macOS Big Sur ver 11.1
サーバ/DB → XAMPP 7.4.13-0
エディタ → Visual Studio Code
メール →  Gmail

ターゲット(この記事を読むべき人)

  • PHPを用いてローカル環境からメールを送りたいけど、送れずに悩んでいる人
  • sendmailというメールエージェントが見当たらず先に進めない人
  • macOSの記事が少なく自分に合う情報が見つからず困っている人

ペルソナは私と同じような初学者向けの記事となっているので、現役のエンジニアの方々は「こんなところでお前つまづいたのか」と笑いながら読み進めていただければ...

自分が陥った状況

ローカル環境にあるPHPアプリケーションからメールを自分のGmailに飛ばそうとした結果、飛ばせない。
メールの飛ばし方をググるとたくさん記事が出てくる。
参照してみると、まずphp.iniをいじってポート番号や宛先を変える。その後どうやらsendmail.phpというファイルをいじるとのこと。

しかし、このsendmail.iniがどうやらmacOS上を漁っても出てこない...
そこからsendmailの設定ファイルであるsendmail.iniの実態を掴むまで数日かかり苦労した。

sendmail.iniはmacOSのどこにある?

結論から申すと、
sendmailはmacOSにはない。

もう少し調べてみると、どうやら違うメールサーバがmacには標準搭載されているらしい。
その名前は、「postfix」である。

そもそもメールサーバってなんぞや

sendmailやpostfixの実態を掴むためにまずはメール送信の仕組みについて話していく。

メールの送受信というものは、SMTPPOP(IMOP)というプロトコルを用いて行われる通信のことである。
プロトコルというのは、通信の手段を明確に定めた規格である。
サーバとクライアントでお互い扱うデータの種類や通信の手法をあらかじめ統一しておくためのルールみたいなもの。
メールでのやりとりをするときは常にsmtpやpop.imopが使われている。

メール配送の様子を簡易化した図がこちら。
mail-1.png.jpg

引用元: 【図解】初心者にも分かるメールの仕組み~SMTP/POP/IMAPの違い, リレーの構成, 用語について~

MTA(Mail Transfer Agent)
メールを配送するためのプログラムで、ホスト間でのメールの配送や配送されてきたメールを受け取る機能をもっています。代表的なMTPは、sendmail,qmail,Postfixなどがあります。

MDA(Mail Delivery Agent)
MTAがメールを受け取ると、各ユーザのメールボックスにメールを配信する機能を持っています。代表的なMDAは、mail.local,procmail,qmail-localなどがあります。

MUA(Mail User Agent)
主にユーザがメールを読み書きし、送受信する機能を持っています。メーラーとも言われ、アドレス帳やメールの振り分け機能を持っているアプリケーションが多く存在ます。また、インターネットメールの仕様に合わせたコード変換などを自動的に行います。代表的なMDAは、Becky!,Outlook Express,Eudora,Muleなどがあります。

引用元: SMTP配送の仕組みとsendmail

厳密にいうと、メールサーバ内にあるMTAがsendmailやpostfixである。
phpを動かすapacheサーバにメール配送機能があるのではなく、メールサーバ内にあるエージェントが相手のメールサーバに配送しているという認識だけ頭に入れて欲しい。

今回は
postfix → gmailサーバ → 相手のメールサーバ
というgmail経由でのリレー転送方法を解説していく。

転送方法

postfixの役割とメール送信の流れについて把握したところで、以下のアクションプランを提示する。今回はローカル環境での送信テストなので、必要最小限の手順のみ紹介。

  1. php.iniを編集しpostfixに対してコネクションをとる
  2. postfixの設定ファイルを開き宛先を記述する
  3. saslの設定

前提条件

ファイル編集はvimというエディタで行う。
vimの使い方がわからない人は、こちらの記事で基礎動作を把握しておいてほしい。
https://qiita.com/okamos/items/c97970ab34ff55ff3167

1 php.iniを編集する

この部分を編集。smtpのポート番号とホストを設定。

[mail function]
; For Win32 only.
; http://php.net/smtp
SMTP=localhost /* ← ここをlocalhostに */
; http://php.net/smtp-port
smtp_port=25 /* ←ここを25に */

2 postfixの設定

ここからはpostfixをいじる。
まずターミナルを使いpostfixディレクトリに移動。パスは以下の通り

cd /etc/postfix/

root権限を用いてmain.cfをvimで開く

sudo vi main.cf

main.cfにて以下の場所を探す

#relayhost = $mydomain
#relayhost = [gateway.my.domain]
#relayhost = [mailserver.isp.tld]
#relayhost = uucphost
#relayhost = [an.ip.add.ress]

直下にrelayhostの宛先と設定を記述し保存( :wq )

relayhost=[smtp.gmail.com]:587
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
smtp_use_tls=yes
smtp_tls_security_level=encrypt
tls_random_source=dev:/dev/urandom
smtp_sasl_security_options = noanonymous
smtp_always_send_ehlo = yes
smtp_sasl_mechanism_filter = plain

relayhostに今回gmailを使うので、gmailのポート番号を使用する。
gmailをsmtpリレーとして使うためのポート番号の調べ方

saslというライブラリを使うためにその情報も記述している。
saslは、異なるプラットフォームのユーザ認証を手助けするライブラリ。
アプリケーション毎にリレーサーバに対してのアクセス方法が変わってきてしまうため、saslを用いてユーザ認証を共通化している。

3 saslの設定

saslのユーザ認証方法の流れ

gmail認証するためのパスワードを格納したファイルを作成
↓
ファイルのパーミッションを設定
↓
ファイルをDB化する

まずはgmail認証データをpostfixディレクトリ内にsasl_passwdというファイル名で作成。
(ここのファイル名は、main.cfに追記したsmtp_sasl_password_mapsのファイル名と一致させる)

sudo vi sasl_passwd

sasl_passwdには以下のフォーマットで必要な情報を記述

[smtp.gmail.com]:587   GMAILメールアドレス:パスワード

保存したら、sasl_passwdファイルのパーミッションを指定

sudo chmod go-rx sasl_passwd

最後にsasl_passwdをハッシュマップ データベースファイル化する。

sudo postmap hash:/etc/postfix/sasl_passwd

これでsaslの設定は終了。
最後にpostfixを起動、または再起動させます。

起動
sudo postfix start

再起動
sudo postfix reload

まとめ

macOSに関する情報がwindowsに比べて少なかったので、自分がローカル環境でメールを送信できた手法を紹介した。
「phpで簡単にメールを送れる」という情報をよく目にするが、根底にあるLinuxなどOSに関する知識やプロトコルを理解していないとテスト環境の構築は難しいと感じた。

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

初心者必見!固定値(キー、URLなど)は.envファイルに書いて再利用しよう!!(Laravel偏)

皆さんこんにちは!

3日前くらいに書いた記事(初心者必見!固定値(キー、URLなど)は.envファイルに書いて再利用しよう!!)が中々好評だったので、改めてenvファイルについて書いていこうと思いました。

前回書いた記事では、Vue.jsでenvファイルの使用方法を書きました。

今回はタイトルにも書いてる通り、「Laravel」偏です。

今一度、envファイルについて説明しようと思います。

知っている方は、スルーで結構です。

Javascriptでバックエンドとやり取りを行うとき、恐らく多くの方が以下のように書かれると思います。

axios.get('http://127.0.0.1')

ここで問題なのが、これを実際にサーバーにアップロードする時って、http://127.0.0.1のようなローカルホストとは接続を行いませんよね?

また、その都度バックエンドのURLをコピーしてくるのもナンセンス。

そんなこんなで出てくるのがenvファイル!!

・一度値を設定してしまえば、使いまわしOK!

・シークレットキーなどのセキュリティ面でも活躍!(ファイルに直接キーを入力するのは、githubにあげるときに見られてしまうため)

・ローカルと本番環境の使い分けができる!(今回はここはやりません)

こんなに魅力的なんです!

まぁ話はこの辺にしておいて、当然の如くVue.jsとLaravelではやり方が違うので、使い方を一緒に見ていきましょう!

envファイルに定数を設定

プロジェクト直下に.envというファイル名があると思うので、それを開いてみてください。

そしたら、以下を例に値を設定して見て下さい。

RECAPTCHA_SECRET_KEY = 'ciascihsiachuhewurvuvurw'

定数名は、自分で分かりやすいように設定してください!

configファイルで値の設定

次に、configディレクトリを開き、app.phpを開いてください。

Vue.jsでは.envファイルに記述して終わりだったのですが、Laravelでは.envファイルを読み込まない設定なので、configで設定します。

config/app.php
'RECAPTCHA_SECRET_KEY' => env('RECAPTCHA_SECRET_KEY')

先ほどenvファイルで設定した名前をenv(name)で呼び出し、'RECAPTCHA_SECRET_KEY'のように適当に名前を付けて下さい!

呼び出し

最後に、ここで設定した値を呼び出します。

の前に、いったんキャッシュを消去します。

コマンドプロンプトにて、以下のコマンドをうちます

php artisan config:cache

最後に呼び出していきます。

index.php
$secret = config('app.RECAPTCHA_SECRET_KEY');

このapp.は何かというと、configディレクトリのapp.phpRECAPTCHA_SECRET_KEYを呼び出すという意味です。

このようにして、固定値を呼び出すことができます。

いかがだったでしょうか?

簡単かつ作業効率もあがるのでぜひこの機会にガンガン使ってください!!

以上、「初心者必見!固定値(キー、URLなど)は.envファイルに書いて再利用しよう!!(Laravel偏)」でした!

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも毎日初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!

Thank you for reading

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

Ruby学習者がPHPを最新版(v8)にアップデートしてみた

プログラミングでRubyおよびRuby on Railsをメインに学習中ですが、Rubyの復習も兼ねてPHPの基礎も学習することにしました。

パッと見だと通じる部分も多いようなので、PHPを勉強することでRubyの復習にもなるかな…と考えたからです。

今回は、Macに標準でインストール済みのPHPをバージョンアップします。

対象&前提

・Ruby学習者でPHPもかじってみたい人
・Macユーザー(私はMacOS Catalina(10.15.7)使ってます)
・シェルはzshを使用

まずは現在のバージョンを確認

ターミナルを起動して、PHPのバージョンを確認するコマンドを叩きます。

% php -v              
PHP 7.3.11

どうやら、私のPCにはPHP7.3.11というバージョンが入っているようです。

PHP公式 によると、2021年1月現在は「v8.0.1」が最新とのこと。
早速、バージョンアップしていきます。

Homebrewを使ってインストール

Macのパッケージ管理ツールであるHomebrewを使ってインストールしました。
※Homebrew導入済みの前提で書きます。Homebrewのインストール方法は一番下の補足を参照。

% brew search php@8    # Homebrewに存在するPHPv8のパッケージを確認

==> Formulae
php@8.0 ✔
==> Casks
homebrew/cask/eclipse-php                          homebrew/cask/netbeans-php

Homebrewにv8があるようなので、インストールコマンド実行。

% brew install php@8.0

インストールにはしばし時間がかかります。
インストール中にたびたび出てくるビールマークの誘惑。

インストールが完了したら、バージョンアップされているか確認します。

% php -v              
PHP 7.3.11

…おや?バージョンアップされてない??

% cd /usr/local/opt/    # いろいろ調べて辿りついたこのディレクトリにはv8いるっぽいが…
% ls
 :
php
php@8.0
python@3.9    # 余談:あらMacにはデフォルトでPythonも入ってるのね!
 :

これまでの数少ない環境構築の経験から、PHPの古い方を参照し続けているのかと仮定。
設定ファイルにパスを追記することにしました。

ターミナルからviエディタを起動して、以下の1行を書きこみ。

export PATH="/usr/local/opt/php@8.0/bin:$PATH"

escして:wq(書き込み保存してから終了)。
設定の再読み込みのため、以下のコマンドを実行。

% source ~/.zshrc    # 設定再読み込み

再度、PHPのバージョン確認コマンドを打ってみる。

% php -v              
PHP 8.0.1

% which php                                                        
/usr/local/opt/php@8.0/bin/php

PHP v8.0.1に変わっていることを確認できました!
以上で、PHPのアップデートは完了。

Rubyの復習

そういや今回はRubyの復習がほぼない。
しいて言えば、バージョン確認コマンドくらい。
Rubyもバージョン3が出たようなのでアップデートしなきゃ。

% ruby -v    # Rubyのバージョンを確認する
ruby 2.6.5

補足: Homebrewをインストール

そもそもHomebrewを導入しておらず、インストールする場合の方法を備忘録として残します。

インストールするためのコマンドは Homebrew公式 のトップページに明記されてます。
ページ見るたびビール飲みたくなる。

% cd       # ホームディレクトリに移動する
% pwd      # 本当にホームディレクトリにいるかどうか念のため確認

# Homebrew公式にも載ってるコマンドを叩く
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"  

% brew -v       # インストールできたか、バージョン確認コマンドを使って確認
Homebrew 2.5.1  # バージョンが表示されたのでインストール完了

% brew update  # 念のためアップデート

% sudo chown -R `whoami`:admin /usr/local/bin  # Homebrewの権限変更を実施
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

日付関数と誕生日を用いて、年齢を算出する方法(PHP)

外部のAPIを叩いて、年齢を算出する処理を書く必要があったので、その時に実行した関数のことを記録しておく。

答えのコード

sample.php
date_default_timezone_set('Asia/Tokyo');
$currentDate = date('Y/m/d');  //2020-01-29
$birthday = "あなたの誕生日 例:1980-01-01";
$fc = (int)date('Ymd', strtotime($currentDate)); //20200129
$fb = (int)date('Ymd', strtotime($birthday));    // 19800101
$age = (int)(($fc - $fb) / 10000);  //40

解説

まず、タイムゾーンの設定をして基準の時間を日本にします。

date_default_timezone_set('Asia/Tokyo');

次に、date関数で現在の日時の算出します。加えて、あなたの誕生日を入力してください。
date関数は第一引数で指定したフォーマットでその日時を出力します。
この時のデータ型はstringです。

$currentDate = date('Y/m/d');
$birthday = "あなたの誕生日 例:1980-01-01";

次に、先ほどの$currentDate$birthdaystrtotimeでタイムスタンプとして出力したものをint型に書き換えます。
この時dateのフォーマットをYmdに指定することで日付を数値として出力させることができます!
例えば、1980-01-0119800101として変換されます。
加えて、int型に変換することで整数値かつ数値として変換されます。

$fc = (int)date('Ymd', strtotime($currentDate));
$fb = (int)date('Ymd', strtotime($birthday));

最後に、引き算をして10000で割ります。

引き算のフロー: 20200129 - 19800101 = 400028
10000でわる: 400028 / 10000 = 40.0028

つまり、西暦の足し算で年齢の10000倍算出して、それを10000で割ることで年齢だけを整数値で変数に納めています。

$age = (int)(($fc - $fb) / 10000);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelでほんの少しハイレベルな検索機能を作ってみた。(初心者向け)

こんにちは、しろうです。

現在、Laravelで小説サイトを作成しています。

そんな中で、(自分的には)ちょっとだけハイレベルな検索機能を作ってみたので、忘れないようにメモとして残しておきます。

検索機能を実装したい人はぜひ、参考にしてください。

もしミスとかあればコメントして頂けると大変有り難いですm(_ _)m

前置き

・クラス名とかひどいのあるかと思いますが、気にしないで頂けると幸いです。
・Formファサードを使ったり、素のformを使ったり混在していますが、許してくださいm(_ _)m
・cssは貼り付けていないので、皆さん側で好きなように変更してください。

今回作る検索機能

・複数条件での絞り込み検索ができる。(例:キーワードとジャンルで絞り込む。)
・現在の検索条件がタグとして表示される。
・タグを削除すれば、検索条件から削除される。

検索機能のイメージ動画

ちなみにイメージ動作は下記の通りです。

ezgif.com-gif-maker.gif

下記のように、他のページからジャンルとかをクリックしたら、そのジャンル名で検索してくれる機能もつけてます。

ezgif.com-gif-maker (1).gif

さて、じゃあどんどん作っていきます。

とりあえず検索機能を作る

viewファイルの作成(検索項目の部分)

スクリーンショット 2021-01-29 13.53.31.jpg

とりあえず検索項目を作成していきます。

今回は「キーワード検索」と「ジャンル検索」のみを作成しています。
また、CSSは貼り付けないので、皆さんの方で好きなように変更よろしくお願いしますm(_ _)m

search.blade.php
{{ Form::open(['route'=>'search','method'=>'GET','id'=>'side_search_form','autocomplete'=>"off"]) }}
<div class="search_keyword">
    <div class="search">
        <input name="keyword" value="{{request('keyword')}}" type="search" class="searchTerm" placeholder="キーワード検索">
        <button type="submit" class="searchButton" form="side_search_form">
            <i class="fa fa-search fa-xs"></i>
        </button>
    </div>
</div>

<div class="search_genre search_side_item_border">
    <h4>ジャンル</h4>
    <div class="ripples_radio">
        {{ Form::radio('genre','', isset(request()->genre) ? false :true, ['id'=>'search_genre_none'])
        }}
        {{ Form::label('search_genre_none', '指定なし', []) }}
    </div>
    @foreach ($genres as $index => $genre)
    <div class="ripples_radio">
        {{ Form::radio('genre',$genre, $genre == request()->genre ? true :false,
        ['id'=>'search_genre'.$index]) }}
        {{ Form::label('search_genre'.$index, $genre, []) }}
    </div>
    @endforeach
</div>

{{ Form::close() }}

解説していきます。

'autocomplete'=>"off"・・・これをつけると検索履歴が表示されなくなります。お好みでどうぞ。
value="{{request('keyword')}}"・・・このようにするとvalue値が「keywordというパラメーター(クエリ文字列)の値」になります。
requestメソッド・・・リクエストデータを取得できるやつです。

@foreach ($genres as $index => $genre)・・・この$genresはコントローラーから検索できるジャンル名を返しています。単純にジャンル名を1つずつ処理しているだけです。

下記少しわかりにくいかと思います。

{{ Form::radio('genre',$genre, $genre == request()->genre ? true :false,
        ['id'=>'search_genre'.$index]) }}

Form::radioは第三引数がtrueならcheckedをつけるので、ジャンル名とパラメーターのジャンル名(現在検索しているジャンル名)が一致するなら、checkedをつけるようにしています。

例えば、http://127.0.0.1:8000/search?genre=恋愛(現世)とかなら、request()->genreによって、恋愛(現世)という文字列を取得できます。

なので、$genre == request()->genreとすることで、現在検索しているジャンルボタンにのみcheckedをつけることができます。

指定なしというラジオボタンもほしいので、下記コードで作成しています。

{{ Form::radio('genre','', isset(request()->genre) ? false :true, ['id'=>'search_genre_none'])}}
{{ Form::label('search_genre_none', '指定なし', []) }}

value属性''(空文字)にしておけば、コントローラー側の処理でいい感じにできます。(解説は後ほど。)

web.phpにルーティングを追加

とりあえず、なんでもいいのでルーティングを追加します。

web.php
Route::get('search', 'UsersController@search')->name('search');

ジャンル用のファイルを作成

今回はconfig/getValue/radio.phpにジャンル用の配列を作成しました。

config/getValue/radio.php
<?php
return [
    'genre' =>[
        '1' =>'恋愛(異世界)',
        '2'=>'恋愛(現世)',
        '3'=>'ラブコメ',
        '4'=>'ホラー',
        '5'=>'推理(ミステリー小説)',
        '6'=>'異世界ファンタジー',
        '7'=>'現代ファンタジー',
        '8'=>'コメディ',
        '9'=>'SF',
        '10'=>'詩・エッセイ・童話',
        '11'=>'歴史・戦国',
        '12'=>'その他',
    ],
];

このようにすることでconfig('getValue.radio.genre')とすれば、ジャンル名の配列を取得することができます。

コントローラー内でこのジャンル名の配列を取得します。

コントローラーに処理を追加

次にコントローラー側に検索処理を記述していきます。

UsersController.php
public function search(Request $request)
    {
       //SQL文を書くためにqueryメソッドを使う。
        $query = Novel::query();

       //ジャンル名を取得。(viewファイルに返すだけ。)
        $genres = config('getValue.radio.genre');

      //keywordがあるかどうか。
        if ($request->filled('keyword')) {
            //検索キーワードとタイトルが一致するレコードを絞り込む
            $query->where('title', 'like', '%'.$request->get('keyword').'%');
        }

      //genreがあるかどうか。
        if ($request->filled('genre')) {
            //検索ジャンルとジャンル名が一致するレコードのidをgenresテーブルから取得
            $genre_id = Genre::where('name', $request->genre)->first()->id;
            //genre_idが一致するレコードをnovelsテーブルから絞り込む
            $query->where('genre_id', $genre_id);
        }

       //条件に一致するレコードを作成日で降順に並び替えて取得
        $novels = $query->latest('novels.created_at')->paginate(50);

        //viewファイルは好きなファイルにしてください。
        return view("search", compact('novels', 'genres'));
    }

たぶん、ほとんど読めばわかるんじゃないかと思います。

$request->filled('genre')を使えば、リクエストに値が存在して、かつ、空でない場合にtrueを返してくれます。

似たものに$request->has('genre')というのがありますが、これだと空であってもtrueになります。

それだと、下記のような指定なし(value値が空文字列)の場合でも実行されてしまうので、今回はfilledメソッドを使用しています。

{{ Form::radio('genre','', isset(request()->genre) ? false :true, ['id'=>'search_genre_none'])}}
{{ Form::label('search_genre_none', '指定なし', []) }}

ちなみにlatest()を使えば、降順に並び替えてくれます。(下記の通り)

$query->latest('novels.created_at')->paginate(50);

あとは、好きなようにviewファイル側でデザインしてあげれOK。

試しにsearch.blade.phpとかで{{dd($novels)}}とかで中身を確認してみてください。

現在の検索条件を表示する機能の作成

スクリーンショット 2021-01-29 14.04.43.jpg

なんて説明すればいいかわかりませんが、ここからは上記の画像のやつを作っていきます。笑

方法としては、そこまで難しくありませんので、ご安心ください!!!

まずはview側に処理を追加

とりあえず、viewファイルに処理を追加していきます。

下記のようにすれば現在の検索条件を表示することができます。

search.blade.php
<div class="search_condition">
    <ul>
        @if(!empty(request()->keyword))
        <li class="search_condition_item">
            {{request()->keyword }}<a href="keyword" class="search_condition_a"><i class="fas fa-times search_condition_delete"></i></a>
        </li>
        @endif

        @if(!empty(request()->genre))
        <li class="search_condition_item">
            {{request()->genre }}<a href="genre" class="search_condition_a"><i class="fas fa-times search_condition_delete"></i></a>
        </li>
        @endif
    </ul>
</div>

見て大体わかると思いますので、ざっくり説明していきます。

まずempty()は引数が空ならtrueを返すので、!(エクスクラメーション)をつけて、中身が空ではない時にif文内のhtmlが表示されるようにします。

そしてif文の条件を「!empty(request()->keyword)」みたいな感じにすることで、現在keywordで検索をしているのかどうか、がわかります。(このkeywordというのはinputのname属性のことです。)

例えば、http://127.0.0.1:8000/search?keyword=&genre=みたいな感じで、keywordが空になっているなら、処理は実行されません。

逆にhttp://127.0.0.1:8000/search?keyword=人生楽しいね&genre=とかだと、「人生楽しいね」というキーワードで検索されていることになるので、if文内の処理が実行されます。

そして、if文内の処理は下記のようにします。

<li class="search_condition_item">
      {{request()->keyword }}<a href="keyword" class="search_condition_a"><i class="fas fa-times search_condition_delete"></i></a>
</li>

まず{{request()->keyword }}とすることで「人生楽しいね」が表示されます。
でもって、aタグのhref属性keywordと記述して、JavaScriptでこいつを操作していきます。

JavaScriptを記述

ここからはJavaScript(今回はjQuery)の出番です。

なんでもいいので、JavaScritのファイルを作って、下記のように記述してください。

search.js
$(function () {
    $('.search_condition_a').each(function () {
       //href属性を取得
        attr = $(this).attr('href');
       //初期化
        var url = new URL(window.location);
       //パラメーター削除
        url.searchParams.delete(attr);
        if (url.search) {
            $(this).attr('href', 'search' +url.search);
        } else {
            $(this).attr('href', 'search');
        }
    });
});

まず、$('.search_condition_a').each(function () {}とすることで、search_condition_aクラスの要素(aタグの部分)をループさせています。

attr = $(this).attr('href');とすることで、ループされたaタグのhref属性を取得しています。

例えば、下記の場合はkeywordという文字列が取得できます。

<a href="keyword" class="search_condition_a">

次にURLオブジェクトを作成し、searchParamsメソッドdeleteメソッドを使用して、先ほど取得した、href属性の初期値と一致するパラメーターを削除します。

//初期化(URLオブジェクトの作成)
var url = new URL(window.location);
//パラメーター削除
 url.searchParams.delete(attr);

もう少し詳しく解説していきます。

URLオブジェクトとは、URLを作成したり、編集したりするときに使えるメソッドが沢山入っている、JavaScriptが用意してくれている便利なやつです。()

参考:URL()

そして、引数にはwindow.location として、現在開いているURLを与えます。

次にsearchParamsで、URLのパラメーター(URLの?以降の部分)を取得、deleteメソッドで引数に与えたものと一致するパラメーターを削除します。

例えば、attrkeywordという文字列が入っている場合は、url.searchParams.delete(attr);によって、

http://127.0.0.1:8000/search?keyword=人生楽しいね&genre=恋愛(異世界)
からkeywordの部分が削除されるので、
http://127.0.0.1:8000/search?genre=恋愛(異世界)
こんな感じになります。

最後にパラメーターがあるかないかで条件分岐させています。
こうしないと、他のページから単一条件で検索ページに飛んだときに、1つのパラメーターを削除すると、全てのパラメーターがなくなり、期待通りの動作をしてくれなかったからです。(もっと良い方法もあるかもです...)

if (url.search) {
            $(this).attr('href', 'search' +url.search);
        } else {
            $(this).attr('href', 'search');
        }

url.searchとすることで、URLのパラメーターを取得できます。

あとはattrメソッドを使って、href属性の値を変更してあげればOK。

これでタグの部分は完成です。

別ページから条件検索をしたい時

別ページから検索したい時は下記のように、直接href属性にパラメーターを仕込んでおけばOK。

test.blade.php
<a href="{{route('search')}}?genre={{$novel->genre->name}}">{{$novel->genre->name}}</a>

並び替え機能も実装

スクリーンショット 2021-01-29 16.15.34.jpg

ついでに並び替え機能の紹介もしておきます。(「新着順」と「更新順」だけ)

viewファイルに追加

下記のような感じで実装しました。

search.blade.php
<div class="search_sort">
    <button
        class="sort_btn {{strpos(request()->fullUrl(), 'new') !== false  || strpos(request()->fullUrl(), 'sort') === false ? 'sort_active' : ''}}"
        name="sort" value="new" form="side_search_form" type="submit">
        <span class="spot"></span>新着順
    </button>

    <button class="sort_btn {{strpos(request()->fullUrl(), 'update') !== false ? 'sort_active' : ''}}"
        name="sort" value="update" form="side_search_form" type="submit">
        <span class="spot"></span>更新順
    </button>
</div>

順に解説していきます。

まずformタグの外側でボタンを作る時はform属性formタグのid属性を指定します。

下記の2つの部分は現在のURLによってsort_activeクラスを付与するかどうか三項演算子を利用して、決定しています。

{{strpos(request()->fullUrl(), 'new') !== false  || strpos(request()->fullUrl(), 'sort') === false ? 'sort_active' : ''}}

//省略

{{strpos(request()->fullUrl(), 'update') !== false ? 'sort_active' : ''}}

strpos()は文字列の中に指定した文字列があるかどうかを判定するメソッドです。
request()->fullUrl()で現在のURLが取得できます。

コントローラーに処理を追加

最後に下記のように処理を追加・変更します。

SearchController.php
public function search(Request $request){

//省略

  if ($request->filled('sort') && $request->sort === 'new') {
      $query->latest('novels.created_at');
  }elseif ($request->filled('sort') && $request->sort === 'update') {
      $query->latest('novels.updated_at');
  } else {
      $query->latest('novels.created_at');
  }

  //こっちのlatestは消す。
  $novels = $query->paginate(50);

  return view("search", compact('novels', 'genres'));

}

これで並び替え機能も完成です。

簡単簡単。

最後に

これで一応、イメージ動画みたいな感じの検索機能が実装できたかと思います。

昔から検索機能を作るのは苦手なので、少し苦労しました...なんか条件分岐が多いですし疲れますね。(コードのせいかも。)

駆け足だったので、わかりにくい部分があるかも・・・その時はコメントしてくださいませm(_ _)m

たぶん、もう少し仕様変更とかしますが、ひとまずこれにて終了です!お疲れ様でした。

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

【Laravel】php artisanコマンドメモ(composerも少しだけあり)

自分用のメモとして残します。
3,4年前にメモしたものをqiitaに残すだけなので、未整理です。
もしかしたら、最新のLaravelバージョンでは使えないものもあるかも。

よく使うやつは整理するかもです。

【基本】

▼Eloquentモデル作成(単数形が公式推奨)

php artisan make:model テーブル名

▼シーダー作成(ダミーデータ作成)

php artisan make:seeder テーブル名(アッパーキャメル)TableSeeder

▼シーダー実行(database\seeds\DatabaseSeeder.phpに登録されているものが対象)

php artisan db:seed

▼シーダー実行(単体)

php artisan db:seed --class=シーダークラス名

▼ルーティング確認

php artisan route:list

▼マイグレーション作成

php artisan make:マイグレーション名
例:php artisan make:migration create_users_table

▼コントローラ作成(リソース(おまかせ)を使用する場合は-rを使う)

php artisan make:controller Admin/AdminUsersController
php artisan make:controller Admin/AdminUsersController -r
php artisan make:controller Admin/AdminUsersController --resource --model=Photo

▼ページネーション作成

php artisan vendor:publish --tag=laravel-pagination

▼バッチの作成

php artisan make:command バッチ名(アッパーキャメル)Command

【その他】

▼キャッシュ削除

php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

▼DB初期化(マイグレート実行&初期データ実行)

php artisan migrate:refresh --seed

▼IDEヘルパー更新

php artisan ide-helper:generate

▼最適化まとめ

composer dump-autoload
php artisan clear-compiled
php artisan optimize
php artisan config:cache
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】peclとは何か?pecl install と docker-php-ext-installの違い

DockerにNginxとphp-fpmを使ってLaravel環境を構築する際に、php-fpm対して実行する処理の中にpeclがあったので調べてみた。

▼peclの使用例

php-fpmビルド用のDockerfile
RUN pecl install zip \
    && docker-php-ext-enable zip

RUN pecl install redis \
    && docker-php-ext-enable redis

目次

  1. peclとは?
  2. 使い方(拡張機能のインストール)
  3. 拡張パッケージの有効化
    1. dockerの場合
    2. macやwindowsの場合
  4. pecl installとdocker-php-ext-installの違い
  5. peclとpearの違い
  6. peclとapt-getの違い
  7. 参考リンク


peclとは?

PHPの拡張パッケージ(拡張モジュール)を提供しているサービス。
PHP Extension Community Libraryの略でピクルと読む。

パッケージのインストール後は有効化する必要がある。(php.iniで有効化した場合はサービスの再起動が必要)


使い方(拡張機能のインストール)

peclはPHPにバンドルされているので、すぐにコマンドとして使える。

以下コマンドでパッケージをインストールできる。

pecl install 拡張パッケージ名[-バージョン]

バージョンの指定がなければ安定版をインストール。



▼バージョン指定の例

$ pecl install extname-0.1


拡張パッケージの有効化

peclでインストールしたのみではパッケージは有効にならないので有効化する必要がある。

1. dockerの場合

docker-php-ext-enable 拡張パッケージ名

2. macやwindowsの場合

この場合2つの方法がある。

php.iniを編集する

php.iniを開いて編集する。

(1)まずはファイルの所在を確認。

php.ini
##場所を確認
$ php -i | grep php.ini

Configuration File (php.ini) Path => /etc

##ファイルの存在確認
$ ls /etc | grep php.ini
php.ini.default

##ファイルの作成
$ cp /etc/php.ini.default /etc/php.ini

上記状態だと、php.iniは存在しないので、php.ini.defaultをコピーして、php.iniを作成する。



▼php.ini.defaultとphp.iniの違いとは?
php.iniはデフォルトでは存在しない。phpをインストールした際に(OSによってはデフォルトで)php.ini.defaultがある。

php.iniのテンプレートなので、これをコピーしてファイル名をphp.iniにする。



▼grepコマンドとは?
grepコマンドは前の処理結果の中で、指定した値を含む処理結果のみを表示する絞り込みコマンド。

処理 | grep 値


(2)php.iniの編集

ファイルが出来たら、Dynamic Extensionsと書かれているところの下に;extension=拡張パッケージ名があるので、冒頭の;を外す。

拡張パッケージ名がない場合は、extension=拡張パッケージ名を追加する。

これで有効化完了。

php.iniの例
;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;

省略

;extension=bz2
;extension=curl
;extension=fileinfo

↓ curlを有効化

;extension=bz2
extension=curl
;extension=fileinfo



本番反映のため、php.iniで有効化した場合はサービスの再起動をする。


dl関数を使う

dl関数を使って指定した拡張パッケージを有効かできる。

dl ( string $extension_filename ) : bool

$ dl (curl): true

PHP公式


pecl installとdocker-php-ext-installの違い

Dockerfileによっては、pecl installdocker-php-ext-installの2つが使われている場合がある。

なぜPHP拡張パッケージをインストールにするのにコマンドがいくつもあるのか?について。

RUN pecl install redis \
    && docker-php-ext-enable redis

RUN docker-php-ext-install pdo_mysql

結論

docker-php-ext-installはPHPに標準で備わっている拡張パッケージのインストール&有効化ができる。

peclはPHPに標準で備わっていないパッケージをインストールできる。


PHPに標準で備わっている拡張パッケージ一覧

https://www.php.net/manual/ja/extensions.php

▼一例
image.png

Zip, Zlib, memcache, podなどが用意されている。


peclでinstallできる拡張パッケージ一覧

公式ページで検索できる。
https://pecl.php.net/package-search.php

image.png

redis, xdebug, memcachedなどが用意されている。


peclとpearの違い

peclもpearもPHPの拡張パッケージをインストールできるコマンド。

pearはPHP言語で書かれている。peclはC言語。peclの方が高速。

pearで用意されている拡張ライブラリはpeclでも使える。

なお、アイコンは名前にちなんで、pearは洋梨、peclはピクルスとなっている。


peclとapt-getの違い

Dockerfileによっては、apt-get installも同時に使われている場合がある。

RUN apt-get install -y zlib1g-dev libzip-dev unzip \
    && pecl install zip \
    && docker-php-ext-enable zip

aptはDebian系Linux(DebianやUbuntuなど)のパッケージ管理ツール。

なので、apt-getでインストールするのはOS用のパッケージ

peclでインストールするのはPHP用のパッケージ。


参考リンク

PHP公式 pecl入門
PHP公式 pecl installの使い方
PHP公式 php.iniディレクティブ
pecl公式 peckとは?
docker hub公式 php-fpm

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

NetCommons2でファイルダウンロード処理を自作した場合の、IEファイル名文字化け対応

旧会社HPからの転記です。

ここが参考になります。

Uploads_Viewコンポーネント _headerOutput() function
https://github.com/netcommons/NetCommons2/blob/develop/html/webapp/components/uploads/View.class.php#L337-L356

以上です。

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

NetCommons2 使用しているテンプレート名をphpで取得する

旧会社HPからの転記です。

php側でテンプレート名を使ってプラグラムの動きを変えたかったので、
やり方を調査しました。

下記PHPで実現できます。
componentsの場合

$container =& DIContainerFactory::getContainer();
$block =& $container->getComponent("blocksView");
$block_id = intval($request->getParameter("block_id"));
$block_obj = $block->getBlockById($block_id);

// $block_obj['temp_name'];    //←テンプレート名が取得できる

(2018/09/28追記)

view・actionの場合

PHP

 var $block_id = null;
 var $blocksView = null;

 function execute()
 {
     $block_obj = $this->blocksView->getBlockById($this->block_id);
     $block_obj['temp_name']; //←テンプレート名が取得できる
 }

maple.ini

[Action]
blocksView = "ref:blocksView"

参考になれば幸いです。
ではでは。

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

PHPで素数判定

何かで素数判定がどうちゃらこうちゃらみたいな記事を読んだので、自分も作ってみようと思ってパパッと1〜100までの素数判定プログラム書いてみました。

素数とは

そもそも素数とは1とその数自身以外に約数がない正の整数らしいです。
1その数自身でしか割り切れないということで約数を2つしか持ちません。
この性質を使ってプログラムを組んでいこうと思います。

コード

まずは大まかな流れです。

for ($i = 1; $i <= 100; $i++) {
  if ($iが素数なら) {
    echo $i
  }
}

次に、$iが素数かどうかを判別する方法ですが
ここで約数を2つしか持たない性質を使います。

for ($i = 1; $i <= 100; $i++) {

  $point = 0;

  for ($j = 1; $j <= $i; $j++) {
    if ($i % $j == 0) {
      $point += 1;
    }
  }

  if ($point == 2) {
    echo $i . "\n";
  }

}

$i$jで割り切れる度に$pointに1を加算していくので、 $iが素数であるなら$pointの値は2になります。出力結果は以下です。

2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97

まとめ

調べてみたら素数を判定するのにも色々な方法があるんですね。今はあまり気が乗らないので時間ある時にでも見てみようと思います。

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

[PHP] 親クラスで定義した変数を呼ぶ

子クラス共通の変数を扱いたい場合、下記のように親クラスで定義する必要があります。

class TestCase extends Illuminate\Foundation\Testing\TestCase
{
    protected static $userId = 1;
}

このように定義した後、下記のように子クラスで呼び出します。

class ControllerTest extends \TestCase
{

    public function setUp(): void
    {
        $this->user = User::find(self::$userId);
    }
}

このようにself::$userIdと書くことにより、extendsしているクラスなら扱うことができます。

参照

【PHP】継承とprotectedと参照パターン

会社の紹介

私は現在、株式会社ダイアログという物流×ITの会社に勤務しております。
様々な職種を募集しているので、Wantedlyのページをご覧ください。

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

LaravelでFullcalendarを実装する方法

はじめに

今回はLaravelでFullcalendarを実装する方法について解説します。
LaravelでFullcalendarを実装するにあたり、参考記事があまりなく、実装に苦労したので、同じような方の助けになればと思います。

-各バージョン
-Laravel 6.x
-PHP 7.4.9
-MySQL 5.7.30
-Fullcalendar v5

Fullcalendarはバージョンによって記述方法が異なるので注意してください。
v4の記事を参考にしてもうまくいかないことが多かったです。

Fullcalendarをダウンロードする

公式ドキュメントよりダウンロードできます。
https://fullcalendar.io/docs/getting-started

NPMやCDNを利用する方法がありますが、ダウンロード方法はお好きな方法で問題ないです。
今回はzipファイルをダウンロードする方法し、以下のように追加しました。

event.blade.php
<!-- fullcalendar dependencies -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.0/moment.min.js"></script>

<!-- fullcalendar script -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.0.1/fullcalendar.min.js"></script>

<!-- fullcalendar style -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.0.1/fullcalendar.min.css">

モデルとデーブルを作成する

わたしの場合はModelsファイルの中にモデルを格納したいので、以下のように書いています。必要がなければ、Modelsのところはカットして問題ないです。

php artisan make:model Models/Event -m

まずはテーブルから書いていきます。
Fullcalendarには様々なプロパティが用意されていて、以下のサイトより確認することができます。
https://fullcalendar.io/docs/event-parsing
今回はシンプルに、予定のタイトルと登録する日付、文字の色を変更できるように設定していきます。

events.table.php
public function up()
    {
        Schema::create('events', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title', 100);
            $table->date('start');
            $table->string('textColor');
            $table->timestamps();
        });
    }

マイグレーションします。

php artisan migrate

カレンダーに登録したデータを表示する

カレンダーの表示とカレンダーに登録したデータを表示するControllerとルーティングを書いていきます。

php artisan make:controller EventController

indexアクションにカレンダーの表示とDBに保存されているデータをカレンダーに表示させるコードを書きます。
今回はDBファサードを利用するので、useで宣言が必要です。

EventController.php
use App\Models\Event;

public function index(Request $request) {

  if ($request->ajax()) {
    $data = DB::table('events')->select('title', 'start', 'textColor')->get();
    return response()->json($data);
    }

return view('/event');
}

$request->ajax()でデータがajax通信かどうかを確認できるメソッドです。
if内では、eventsテーブルからデータを持ってきて、response()->json()を利用し、json形式で保存するようにしています。
このようにすることによって、PHPで保存したデータをJavaScriptで利用できるようになります。

続いて、ルーティングは以下のように設定します。

web.php
Route::get('/index', EventController@index);

カレンダーの情報を登録する

カレンダーの情報を登録するためのコードを先ほど作成したEventControllerに書いていきます。データの登録後、カレンダーが表示されているページに戻るようにしています。

EventController.php
public function store(Request $request)
    {
        $event = new Event;

        $event->title = $request->input('title');
        $event->start = $request->input('start');
        $event->textColor = $request->input('textColor');
        $task->save();

        return redirect('/event');
    }

続いてルーティングです。

web.php
Route::post('/store', EventController@store);

カレンダーの表示と登録フォームを設定する

カレンダーの表示自体はとても簡単で、カレンダーを表示させたい場所に以下のコードを書くだけで表示できます。

event.blade.php
<div id="calendar"></div>

フォームはCSSを考慮せずに書いているのでご了承ください。

event.blade.php
<form method="POST" action="{{ route('/store') }}">
   @csrf
  <input type="text" name="title">
  <input type="date" name="start">
  <input type="color" name="textColor">
  <button type="submit">登録</button>
</form>

データの登録なので、methodはPOSTを指定し、actionにはフォームが送信されたらEvercontrollerのstoreアクションにつながるようにしたいので、先ほどweb.phpで指定したroute('store')を指定しています。

type属性にはそれぞれ入力方式に適したものを入力し、name属性にはeventsテーブルで指定したカラム名を入力します。

続いてはJSを書いていきます。
今回はevent.blade.phpに直接書きましたが、便宜JSだけディレクトリを分けてもいいかと思います。

event.blade.php
<script>
  $(document).ready(function () {
    $('#calendar').fullCalendar({
      // はじめりの曜日を月曜日に変更 デフォルトは日曜日になっており、日=0,月=1になる
      firstDay: 1,
      headerToolbar: {
                     right: 'prev,next'
                     },
      events: '/home',
    });
  });
</script>

eventsにはカレンダーに保存している情報を表示するアクションが書かれている、EventControllerのindexメソッドにつながるように書く必要があります。
そのため、先ほどweb.phpで指定した/homeを指定しています。

今回はシンプルなカレンダーになっていますが、Fullcalendarには様々なオプションが用意されています。
簡単なものだと、headerToolbarはrightだけではなく、left,centerのカスタマイズもできますし、eventをドラッグしたり、日にちを選択して登録することなんかもできます。
詳しいオプションに関しては、Fullcalendarの公式マニュアルをご確認ください。
https://fullcalendar.io/docs#toc

これで、カレンダーにデータの登録と、登録したデータの表示ができるようになりました!

さいごに

今回は登録フォームを直接書いていますが、今後は日付から選択をしてデータの登録をしたりなど、いろいろとカスタマイズをしてみたいと思います!

最後まで読んでいただきありがとうございました!

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

[Laravel7.x]外部キー制約の記述に関する備忘録

今回の題

Laravelの外部キー制約について、7.xからよりシンプルに書けるようになっていた事を最近になって知ったので備忘録として書きました。
内容薄いですが勘弁してください。

前提

前提として、主テーブルusersと従テーブルpostsは1対多の関係にあるとする。
そして、postsusersのidカラムを参照するuser_idカラムを外部キーとして定義する。

何がどうなったのか

外部キーを定義するとき、6.xまでは以下の書き方だけだった。

Schema::table('posts', function (Blueprint $table) {  
    $table->unsignedBigInteger('user_id');
    $table->foreign('user_id')->references('id')->on('users');
});

ただこの書き方は冗長であるという事で、
7.xからは加えて以下の書き方も出来るようになった。

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained();
});

1行でカラムの定義と外部キーとしての設定が出来るようになったのですごく楽。

参考

readouble - 外部キー制約

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

XAMPPに同梱されてるソフトを調べてみた

この記事の意図

 プログラミング初心者が最初に迎える試練は環境構築。手っ取り早く、この難所を突破するためにXAMPPを候補に入れる。でもパソコンに何でもかんでもソフトを入れるのは抵抗がある。

 そこでXAMPPにパッケージされているソフトウェアを調べて、安心してダウンロードできるようにしたい。もし必要のないソフトが多ければ、XAMPPを入れずに個々に入れた方が後々苦労せず済むはずだし、XAMPPで入ったソフトと同じ機能が欲しくなった時、新しいソフトを調べてダウンロードする手間を省けるかもしれない。

 XAMPPのメインのソフトであるApache、MariaDB、SQLite、phpMyadmin、OpenSSLやPHP、Perlは他の詳しい記事を調べてください。なんかよくわからないソフトだけを調べました。

調べるバージョン

スクリーンショット 2021-01-28 3.20.17.png

調べたソフト一覧

Sablotron:XMLプロセッサ。XML形式の中身を解析して、中の情報を使いやすくする。エディタで書いたコードをメモ帳に貼り付けると読みにくくなる。を防止するとか。Sablotron自体の情報はほとんどない。

FreeType:PC内にインストールされているフォントファイルを表示するためのライブラリ。テキストのレイアウトとか、フォントの追加、編集はできない。フォント関連の操作をサポートしている。

libpng:png規格の画像を別のデータに変換したり、元に戻したりするライブラリ。

gdbm:dbmとはDatabase Managerの略。MariaDB、MySQL、SQLiteとかはdbms(Database Management System)でデータベース管理ソフトと言うらしい。dbmはそれより単純で、通信し合うのではなく、一方的にデータを送ることに長けている。

zlib:データの圧縮、伸張を行うための可逆圧縮アルゴリズムが入っている。zipなどの圧縮、解凍をするためのライブラリ。画像ファイルのpngはDeflateという可逆圧縮アルゴリズムが不可欠で、今でも多くのソフトで使われている。

expat:C言語用のXMLプロセッサ。プロセッサは一度読み込んでから動くDOM型とファイルを先頭から読み込んでその都度処理するストリーム型があって、expatはストリーム型。

libxml2:C++、C#、Ruby、PHP、Pythonなどでは標準で定義された関数を使う事ができるXMLプロセッサ。

Ming:C++、Python、PHPに対応するSWF(Flashのフォーマット)に出力するためのライブラリ。元々はC言語用だが、他の言語でも使えるようにした(ラッパーした)ライブラリでもある。Mingだと中国の「明」が出るので、検索するときは「Ming SWF」とかつけるとヒットしやすい。

Webalizer:webアクセス解析をするソフト。年月月日の国別の閲覧数や訪問者の入り口になったページをみたり、どのブラウザを見たのか等をまとめてくれる。google Analyticsみたいなもの

pdf class:PHPを使ってpdfを動的に生成する事ができるソフト。PHP4を最後に更新されてない。同じ機能のソフトとしてTCPDFがある。何故か重複して2回what's included?に記載されている。

ncurses:これを使うと、ターミナルとかCUI上でテキストを使ったユーザーインターフェイスが作れる。簡単に言うとvimを使ってミニゲームを作れるみたいな。初期のcRPGとか、つくれそうだ。

mod_Perl:ApacheHTTPサーバに入れる事で、Perl言語でwebサーバを記述、動的に構成できる。CGIに関わっている。

FreeTDS:webサーバにDBに格納されているデータを送信したり、サーバ側からDBのデータへアクセスしたりする事ができる。

gettext:ソフトウェアの国際化、地域化に対応させるために用いられる。これを使えば、英語で返信されたチャットを日本語に表示し直したり、標準語で書かれたページを関西弁に変えたりできるかもしれない。

IMAP C-Client:IMAPとはInternet Message Access Protocolの略。対義語?はPOP(Post Office Protocol)で両方ともメール設定で使われる。前者はサーバにメールを保管して管理する。後者は転送した先でメール管理する。このソフトはクライアント側(メールサーバ)を構築する時に使われる。

OpenLDAP:LDAPはLightweight Directory Access Protocolの略。ディレクトリサービスへアクセスするために用いられる。主な使用用途は、ログイン認証、アカウント管理とか。複数人が一つのアカウントで入れるようにするとか、逆に特定の人だけが閲覧できます、といったシステムを管理できる。

mcrypt:PHPで使われる暗号化、復号化するソフト。PHP7.1までは使われていたが、それ以降のverでは非推奨。PHPはその代替としてOpenSSLとsodiumを提示している。エニグマ暗号に近いアルゴリズムを使っているらしい。

mhash:hash値、hash関数は暗号化で用いられる。パスワードを安全に管理するために暗号化する時に使われ、mhashはこのhash値を計算するためのソフトである。

cURL:HTTP、HTTPSや上に挙げたLDAP、IMAPといった通信規格をクライアント側に通信するライブラリとcurlで知られるプログラミング言語、コマンドラインツールを提供している。xamppで一番求められている機能、コードのアップロードに使う。

libxslt:libxml2のライブラリを拡張させてXSLTファイルを使えるようにするライブラリ。XSLはExtensible Stylesheet Languageの略でTはTransformationの意味。XMLファイルを他の形式に変換可能な形式に変え、また変換したファイルをXMLファイルとして出力できるようにする。

libapreq:ApacheHTTPサーバを介してクライアント要求データをやり取りするためのライブラリ。HTTPクッキー、クエリ、POSTデータの解析を行う事ができる。

FPDF:PHPデータからPDFファイルを生成するためのライブラリ。pdf classやTCPDFと同じ。

ICU4C:International Components for Unicodeの略。ソフトウェアの国際化、地域化に対応するために用いられる。gettextとは違って、コード内で生じる言語による障害を取り払うために使うようだ。

APR:Apache Portable Runtimeの略。Apache HTTPサーバを使う際に、OSやソフトウェアの環境の違いを小さくする。このOSにしかない機能を他のOSで使えるように調節でき、クロスプラットフォームなソフトウェアを作る事ができる。

APR-util:APRを扱うためのインターフェースを提供している。

GD:GIF Draw或いはGraphics Drawの略。動的に動く画像GIFを作る事ができる。ANSI CやC、PHP、Perlに対応している。

ProFTPD:FTPサーバで使われる常駐プログラム(デーモン)。FTP接続をするために待機して、接続する時に応対する。デーモンは悪魔(demon)ではなく、その語源であるギリシャ語の守護神を意味するdaemonの綴り。

まとめ

 XAMPPに同梱するソフトウェアやライブラリ、XAMPPは時代とともに、必要に感じた便利機能を組み込んで、より使いやすくする努力が続けられた。一方で、同じ機能でバージョンが遅れているようなソフトをまだ同梱し続けている事もわかった。XAMPPを調べることは、Apacheとその周辺の変遷、歴史を知る事ができ、プログラミング初心者にとって有用だと思います。

 お役立ちライブラリも多く、調べている間も、「ncurses使ってゲームブック作りたいな」とか、「チャット中に標準語を関西弁に変える機能いいな」とか、「ログイン認証にLDAPってどうだろう」、「エニグマ... ...だと」など色々アイデアが浮かんできました。

 噛み砕いて理解しようとしましたが、誤解している機能とかはあると思います。優しく指摘していただけるとありがたいです。

 最後に、私は不安があってXAMPPを調べましたが、調べる作業だけで12時間くらい掛かりました。理解するには10倍、100倍は時間がかかるでしょうし、それに時間を取られてはやるべき事が疎かになりますね。大人しく、XAMPPダウンロードしに行きます。

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

cakePHP4 ログイン時の認証条件追加

はじめに

すぐ解決できなかった、そしてピンポイント記事が無いように感じたのでここに記録しておきます!
以下認証の実装はすでに行っていることとします。
きっとここから悩んでいる方が、
記事にきてくださっている気がするので、、、、
https://book.cakephp.org/4/ja/tutorials-and-examples/cms/authentication.html

参考
https://book.cakephp.org/authentication/2/en/identifiers.html

コード

Application.php
        // identifiers を読み込み、email と password のフィールドを確認します
        $authenticationService->loadIdentifier('Authentication.Password', [
            'fields' => [
                'username' => 'email',
                'password' => 'password',
            ],
            'resolver' => [
              'className' => 'Authentication.Orm', //ここ追加
              'finder' => 'auth' //ここ追加
            ],
        ]);
Model/Table/UsersTable.php
    //チェックする取得レコード制限
    public function findAuth(Query $query, array $options)
    {
        $query
            ->where(['Users.is_temporary' => 0]); //本登録のみ ここの条件は適宜変更してください!

        return $query;
    }

最後に

何かあれば追加します(。・ω・。)
テンション高くなくて面白みにかけると思った方、
私のテンションが高くなるようにほめてください。
心の中でよしよししてください、、
いつかテンションが上がるかもしれません、、
きっとここに来てくれた方も元気が無いので、
丶(・ω・`) ヨシヨシ丶(・ω・`) ヨシヨシ丶(・ω・`) ヨシヨシ
もし少しでもこの記事で時間が開いたら身体をやすめましょう。
寝るのや、食べるの大事ですよ、、、、
丶(・ω・`) ヨシヨシ丶(・ω・`) ヨシヨシ丶(・ω・`) ヨシヨシ

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

Artisanコマンドをスクリプトから呼ぶときのメモ

Laravel外のスクリプトからArtisanコマンドを呼びたくなったときに

<?php
require_once(PATH_TO.'/vendor/autoload.php');
$app = require(PATH_TO.'/bootstrap/app.php');
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
// stdoutをstringで受け取りたいとき↓
$output = new Symfony\Component\Console\Output\BufferedOutput;
// そのままコンソールに表示したいとき↓
// $output = new Symfony\Component\Console\Output\ConsoleOutput;
$kernel->call('migrate', [ '--force'=>true, '--quiet'=>true ], $output);
// ↓ stringで取り出す
echo $output->fetch();

shell_exec('php artisan migrate')とかしてもいいのだろうけど…

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

ArtisanコマンドをLaravel外のスクリプトから呼ぶときのメモ

ArtisanコマンドをLaravel外のスクリプトから呼びたくなったときに

<?php
require_once(PATH_TO.'/vendor/autoload.php');
$app = require(PATH_TO.'/bootstrap/app.php');
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
// stdoutをstringで受け取りたいとき↓
$output = new Symfony\Component\Console\Output\BufferedOutput;
// そのままコンソールに表示したいとき↓
// $output = new Symfony\Component\Console\Output\ConsoleOutput;
$kernel->call('migrate', [ '--force'=>true, '--quiet'=>true ], $output);
// ↓ stringで取り出す
echo $output->fetch();

shell_exec('php artisan migrate')とかしてもいいのだろうけど…

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

wordpress編集時に絶対に気をつけるべきだが気づきにくい重大なポイント

wordpressは、phpや記事を直接編集できるという点でも非常に便利なCMSですが、
エディタではなくwordpress上で編集してしまうからこそ気づきにくい・陥りやすい、重大なポイントがあります。

スペースに気をつけろ!

はい。超初歩的ですが、スペースです。全角スペース/半角スペース/タブ。VSCodeやAtomなどのエディタではプラグインで視覚的にわかるようにしている方も多いかと思います。
しかし、wordpress上ではただの空白。半角スペースで打ったつもりが、全角になってしまっている、ということも。

タグのミスマッチに気をつけろ!

これも超初歩的ですが、開始divタグは消したのに終了divタグを消していなかったり。セットでコピペしたと思いきや、どちらかがミスマッチになってしまっていたり。
いやそんなミスしないよ、というミスほど、行き詰まっているときに陥りやすく、しかも見直しにくいものだと思います。(筆者だけ…?)

不具合になりそうなとこ全部直したはずなのに。直らない。そんなときこそ。

目に見える不具合箇所は全部修正した、なのに動作がおかしい。
そんなときは一回、直近の動作OKだった時点以降にwordpress上で修正した箇所のコードを見直してみましょう。
あなたの愛用のエディタに貼って、Ctrl+Sで保存。
それだけで、どこがおかしいのかひと目でわかるように整形してくれるはずです。

詰まっているときこそ、足元を見直す。これ大切ですね。

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