- 投稿日:2020-01-18T23:35:27+09:00
Laravel6でページネーションのカスタマイズ
概要
Laravelのページネーションに触れてみたので備忘録です。
基本的に公式ページに全て書いてある。
Database: Pagination - Laravel - The PHP Framework For Web Artisans環境
PHP: 7.2.22
Laravel: 6.11.0事前準備
テスト用の各種設定は以下の通りです。ユーザやルーティングを適当に設定しています。
UsersController.phpclass UsersController extends Controller { public function index() { $users = DB::table('users')->paginate(10); return view('user.index', compact('users')); } }index.blade.php<html> <head> <title>Paging Sample</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> </head> <body> <div class="container"> <h1>Paging Sample</h1> <ul class="list-group"> @foreach ($users as $user) <li class="list-group-item"> {{ $user->name }} </li> @endforeach </ul> {{ $users->links() }} </div> </body> </html>ページネーション設定
以下コマンドを実行するとresources/views/vendor以下にpaginationのビューファイルが作成されます。現在のバージョンではデフォルトはこの中にあるbootstrap-4.blade.phpが使用されているようです。
$ php artisan vendor:publish --tag=laravel-pagination Copied Directory [/vendor/laravel/framework/src/Illuminate/Pagination/resources/views] To [/resources/views/vendor/pagination] Publishing complete. Publishing complete.$ ls resources/views/vendor/pagination/ bootstrap-4.blade.php default.blade.php semantic-ui.blade.php simple-bootstrap-4.blade.php simple-default.blade.php以下のようにしても同じです。
$ php artisan vendor:publish Which provider or tag's files would you like to publish?: [0 ] Publish files from all providers and tags listed below [1 ] Provider: Facade\Ignition\IgnitionServiceProvider [2 ] Provider: Fideloper\Proxy\TrustedProxyServiceProvider [3 ] Provider: Illuminate\Foundation\Providers\FoundationServiceProvider [4 ] Provider: Illuminate\Mail\MailServiceProvider [5 ] Provider: Illuminate\Notifications\NotificationServiceProvider [6 ] Provider: Illuminate\Pagination\PaginationServiceProvider [7 ] Provider: Laravel\Tinker\TinkerServiceProvider [8 ] Tag: flare-config [9 ] Tag: ignition-config [10] Tag: laravel-errors [11] Tag: laravel-mail [12] Tag: laravel-notifications [13] Tag: laravel-pagination > 13 Copied Directory [/vendor/laravel/framework/src/Illuminate/Pagination/resources/views] To [/resources/views/vendor/pagination] Publishing complete. Publishing complete.bladeテンプレート内で呼び出しているlinks()でページネーションにのテンプレートを指定できます。
index.blade.php{{ $users->links('vendor.pagination.default') }}index.blade.php{{ $users->links('vendor.pagination.semantic-ui') }}前か次かだけのシンプルなページングを指定することも可能です。
index.blade.php{{ $users->links('vendor.pagination.simple-default') }}デフォルトでbootstrap-4.blade.phpが呼び出されている訳なので、これを編集することでページネーションの表示をカスタマイズすることもできます。
また、自身で作成したテンプレートも使用できますので、今回はbootstrap-4をちょっとだけ修正してsample-paginationというテンプレートを作成し使用してみる。
index.blade.php{{ $users->links('vendor.pagination.sample-pagination') }}sample-pagination.php@if ($paginator->hasPages()) <nav> <ul class="pagination justify-content-center pagination-lg"> {{-- Previous Page Link --}}@cannot('update', Model::class) @endcannot @if ($paginator->onFirstPage()) <li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')"> <span class="page-link" aria-hidden="true">«</span> </li> @else <li class="page-item"> <a class="page-link text-success" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">«</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 bg-success border-success">{{ $page }}</span></li> @else <li class="page-item"><a class="page-link text-success" href="{{ $url }}">{{ $page }}</a></li> @endif @endforeach @endif @endforeach {{-- Next Page Link --}} @if ($paginator->hasMorePages()) <li class="page-item"> <a class="page-link text-success" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">»</a> </li> @else <li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')"> <span class="page-link" aria-hidden="true">»</span> </li> @endif </ul> </nav> @endifまとめ
Laravelのページネーションは意外と簡単に実装できる。
スタイルの変更も分かりやすく、自由に修正できる。参考サイト
- 投稿日:2020-01-18T22:49:20+09:00
PHPで文字を画像にするやつ
ちょっと、そういうのが必要になったので。(WEBGLで日本語フォントが通らないとか・・・)
im.php?str=こんにちは,世界
にアクセスすると、カンマ区切りで改行して、こんな画像を生成します。<?php if( isset($_GET["str"]) ){ $points = explode(",",$_GET["str"]); }else{ $str = ["Hello","World"]; } $im = imagecreatetruecolor(400,600); imagefilledrectangle($im, 0, 0, 599, 399, 0x101010); $font = '/font/NotoSansCJKjp-Regular.otf'; $y = 30; foreach($points as $point){ imagettftext($im, 20, 0, 0, $y, 0xffffff, $font, $point); $y = $y + 30; } header('Content-Type: image/png;'); imagepng($im); imagedestroy($im);
- 投稿日:2020-01-18T22:31:40+09:00
CodeIgniterでPOSTをするときのセキュリティ対策(特にAjax)について
はじめに
POSTからデータベースを操作する動作は動的サイトやWebアプリを使うときには頻出する動作だと思います。しかし、第三者がこんなコードを作れば簡単にWebを改ざんできてしまいます。これを、クロスサイトリクエストフォージェリ(CSRF) と言います。
<form action="hogehoge/delete" method="post"> <input type="hidden" name="id" value="2"> <input type="submit"> </form>主たるPHPフレームワークにはCSRF対策があってCodeigniterでも実装されています。公式のドキュメントを見ればハッキリ書いてあるのですが、application/config/config.php ファイルの設定にある$config['csrf_protection'] をTrueをすれば、フォームヘルパーだけを使っているならそのまま対応できるのですが、私のようにAjaxを多用してると、2~3時間で済むつもりが一日潰して対策に追われて、仕事ならまだしも趣味のプログラミングなら、休みが潰れた徒労感だけが残りますので、できるだけ設計段階で気がついて対策をすることを強くお勧めします。
AjaxでCSRF対策するためのコード
フォームヘルパーなら勝手に挿入されるのですが、ajaxならかならず以下のようなコードを埋め込む必要があります。
コントローラー側$csrf = array( 'name' => $this->security->get_csrf_token_name(), 'hash' => $this->security->get_csrf_hash() );ビュー側<input type="hidden" id="token" name="<?=$csrf['name'];?>" value="<?=$csrf['hash'];?>" />configでホワイトリストに入れない限り全てのPOSTが絡むajaxに上のトークンの情報を入れてやらないと基本的には動きません。設計から考えておかないと殆どマイページにPOSTが絡むajaxがあると書き換えとデバッグで大変な目に遭います。(私の場合もともと書き方が悪いので作り直したかったJSを書き替えたという事情もありましたが、なぜか動かないと堂々巡りに…。)
ajaxのコードとは普段と違ってこういう風に書いてやります。
function ajax_post(elm,flg_delete){ var csrf_hash = $("#token").val(); var csrf_name = $("#token").attr('name'); var postdata = { id : {{profile.id}}, };//←普通のデータのように書く postdata[csrf_name] = csrf_hash;//トークンを入れる $.ajax({ url : elm, type: 'POST', data: postdata }) .done(function(data) { alert('OK'); }).fail(function(data) { alert('NG'); }); });application/config/config.php ファイルの設定について
先ほどの設定の下の所に
$config['csrf_regenerate']
というのがありますが、これはTRUEがデフォルトです。これは何かと言えば、トークンが一回使い切りという設定です。全てのPOST絡みの動作がページ変移だけならそれで問題ありませんが、Ajaxでは毎回再読込でもする設定にしないと2回目以降の動作ができなくなります。Ajaxを使うときにはOFFにすることをおすすめします。受け手のコントローラについて
受け側のコントローラはこういう風に作ります。
public function test(){ if ( $this->input->method(TRUE) !== 'POST' ){ show_404(); } $res = $this->input->post('request'); echo $res; }これを参考に設計段階からやるか数カ所程度なら簡単に対策ができるはずです。
まとめ
もう二度と私のような目にあう人が居なくなるように。より安全で堅牢なWeb開発を。
参考
http://web-plusplus.net/codeigniter3-csrf/ - CodeIgniter3でCSRF対策機能をONにしたらAjaxでPOSTできなかった件
- 投稿日:2020-01-18T17:17:41+09:00
CentOS 8 で PHP 7.2 から PHP 7.3 へアップグレード(AppStream)
はじめに
Application Stream(AppStream)を利用してCentOS8にPHP7.3をアップグレードインストール
参考:ユーザー空間コンポーネントのインストール、管理、および削除 Red Hat Enterprise Linux 8 | Red Hat Customer Portalサポート
各Streamのサポート期間はRed Hat Enterprise Linux 8 Application Streams Life Cycle - Red Hat Customer Portalを参照。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。LOG
PHP7.2(default)インストール
# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core) # yum install -y php ... 略 # 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 TechnologiesStream切り替え
# yum distro-sync # yum module reset php # yum module enable php:7.3 # yum distro-sync # php -v PHP 7.3.5 (cli) (built: Apr 30 2019 08:37:17) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.5, Copyright (c) 1998-2018 Zend Technologies
- 投稿日:2020-01-18T16:02:58+09:00
CentOS 8にPHP 7.3, PHP-FPM 7.3をインストール(AppStream)
はじめに
Application Stream(AppStream)を利用してCentOS8にPHP7.3をインストール
親記事:PHP, PHP-FPMの各種インストール方法とEOLまとめ
参考:RHEL8のパッケージ構成 - BaseOSとApplication Stream - 赤帽エンジニアブログサポート
本手法で導入した場合、Red Hat Enterprise Linux 8 Application Streams Life Cycle - Red Hat Customer Portalより、2021-11がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。LOG
インストール
# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core) # yum install -y @php:7.3/common ... 略php-fpm起動/停止
# systemctl status php-fpm ● php-fpm.service - The PHP FastCGI Process Manager Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; disabled; vendor preset: disabled) Active: inactive (dead) # systemctl start php-fpm # systemctl status php-fpm ● php-fpm.service - The PHP FastCGI Process Manager Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; disabled; vendor preset: disabled) Active: active (running) since Sat 2020-01-18 06:55:36 UTC; 4s ago Main PID: 236 (php-fpm) Status: "Ready to handle connections" Tasks: 6 (limit: 8989) Memory: 19.1M CGroup: /docker/91caa1db0c51e1c2f44f1270ff89519b5af389e9d5594b0bdbde9e68b9a0c03b/system.slice/php-fpm.serv> tq236 php-fpm: master process (/etc/php-fpm.conf) tq237 php-fpm: pool www tq238 php-fpm: pool www tq239 php-fpm: pool www tq240 php-fpm: pool www mq241 php-fpm: pool www Jan 18 06:55:36 91caa1db0c51 systemd[1]: Starting The PHP FastCGI Process Manager... Jan 18 06:55:36 91caa1db0c51 systemd[1]: Started The PHP FastCGI Process Manager.# systemctl stop php-fpm # systemctl status php-fpm ● php-fpm.service - The PHP FastCGI Process Manager Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; disabled; vendor preset: disabled) Active: inactive (dead) Jan 18 06:55:36 91caa1db0c51 systemd[1]: Starting The PHP FastCGI Process Manager... Jan 18 06:55:36 91caa1db0c51 systemd[1]: Started The PHP FastCGI Process Manager. Jan 18 06:59:38 91caa1db0c51 systemd[1]: Stopping The PHP FastCGI Process Manager... Jan 18 06:59:38 91caa1db0c51 systemd[1]: Stopped The PHP FastCGI Process Manager.php-fpm自動起動設定/設定解除
# systemctl enable php-fpm Created symlink /etc/systemd/system/multi-user.target.wants/php-fpm.service → /usr/lib/systemd/system/php-fpm.service. # systemctl list-unit-files --type=service |grep php-fpm php-fpm.service enabled# systemctl disable php-fpm Removed /etc/systemd/system/multi-user.target.wants/php-fpm.service. # systemctl list-unit-files --type=service |grep php-fpm php-fpm.service disabled各種確認
# which php /usr/bin/php # php -v PHP 7.3.5 (cli) (built: Apr 30 2019 08:37:17) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.5, Copyright (c) 1998-2018 Zend Technologies # php -i | grep php.ini Configuration File (php.ini) Path => /etc Loaded Configuration File => /etc/php.in # which php-fpm /usr/sbin/php-fpm # /usr/sbin/php-fpm -v PHP 7.3.5 (fpm-fcgi) (built: Apr 30 2019 08:37:17) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.5, Copyright (c) 1998-2018 Zend Technologies # yum module info php:7.3 Failed to set locale, defaulting to C.UTF-8 Last metadata expiration check: 0:11:45 ago on Sat Jan 18 06:49:39 2020. Name : php Stream : 7.3 [e] [a] Version : 8010020191122191516 Context : 2430b045 Architecture : x86_64 Profiles : common [i], devel, minimal Repo : AppStream Summary : PHP scripting language Description : php 7.3 module Artifacts : apcu-panel-0:5.1.17-1.module_el8.1.0+252+0d4e049c.noarch : libzip-0:1.5.2-1.module_el8.1.0+252+0d4e049c.src : libzip-0:1.5.2-1.module_el8.1.0+252+0d4e049c.x86_64 : libzip-debuginfo-0:1.5.2-1.module_el8.1.0+252+0d4e049c.x86_64 : libzip-debugsource-0:1.5.2-1.module_el8.1.0+252+0d4e049c.x86_64 : libzip-devel-0:1.5.2-1.module_el8.1.0+252+0d4e049c.x86_64 : libzip-tools-0:1.5.2-1.module_el8.1.0+252+0d4e049c.x86_64 : libzip-tools-debuginfo-0:1.5.2-1.module_el8.1.0+252+0d4e049c.x86_64 : php-0:7.3.5-3.module_el8.1.0+252+0d4e049c.src : php-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-bcmath-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-bcmath-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-cli-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-cli-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-common-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-common-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-dba-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-dba-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-dbg-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-dbg-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-debugsource-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-devel-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-embedded-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-embedded-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-enchant-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-enchant-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-fpm-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-fpm-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-gd-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-gd-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-gmp-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-gmp-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-intl-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-intl-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-json-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-json-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-ldap-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-ldap-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-mbstring-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-mbstring-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-mysqlnd-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-mysqlnd-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-odbc-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-odbc-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-opcache-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-opcache-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-pdo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-pdo-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-pear-1:1.10.9-1.module_el8.1.0+252+0d4e049c.noarch : php-pear-1:1.10.9-1.module_el8.1.0+252+0d4e049c.src : php-pecl-apcu-0:5.1.17-1.module_el8.1.0+252+0d4e049c.src : php-pecl-apcu-0:5.1.17-1.module_el8.1.0+252+0d4e049c.x86_64 : php-pecl-apcu-debuginfo-0:5.1.17-1.module_el8.1.0+252+0d4e049c.x86_64 : php-pecl-apcu-debugsource-0:5.1.17-1.module_el8.1.0+252+0d4e049c.x86_64 : php-pecl-apcu-devel-0:5.1.17-1.module_el8.1.0+252+0d4e049c.x86_64 : php-pecl-zip-0:1.15.4-1.module_el8.1.0+252+0d4e049c.src : php-pecl-zip-0:1.15.4-1.module_el8.1.0+252+0d4e049c.x86_64 : php-pecl-zip-debuginfo-0:1.15.4-1.module_el8.1.0+252+0d4e049c.x86_64 : php-pecl-zip-debugsource-0:1.15.4-1.module_el8.1.0+252+0d4e049c.x86_64 : php-pgsql-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-pgsql-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-process-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-process-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-recode-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-recode-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-snmp-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-snmp-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-soap-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-soap-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-xml-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-xml-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-xmlrpc-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 : php-xmlrpc-debuginfo-0:7.3.5-3.module_el8.1.0+252+0d4e049c.x86_64 Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled, [a]ctive
- 投稿日:2020-01-18T14:11:35+09:00
SQL文の実行とバインドについて
・SQLに変数を組み込むならprepare、execute
・変数がないならSQLはqueryでもいい。基本的にprepareでOK
・bindValueは文字列以外の型とプレスホルダーの値を渡す(使わなくてもOK)・prepare:入力を受け取る準備
・プレスホルダー:入力をSQL文に含める
・execute:SQL文の実行疑問符プレスホルダー
$stmt = $pdo->prepare('SELECT * FROM users WHERE city = ? AND gender = ?'); $stmt->execute([$city, $gender]);名前付きプレスホルダー
$stmt = $pdo->prepare('SELECT * FROM users WHERE city = :city AND gender = :gender'); $stmt->execute([':city' => $city, ':gender' => $gender]);executeの配列で渡す場合(こっちの方が好き)$stmt = $pdo->prepare('INSERT INTO users (id,title,uptime) VALUES (null,?,?)'); $params = []; $params[] = $title; $params[] = $uptime; $stmt->execute($params);バインドについて
・エミュレーションがONの時、変数は文字列型になる。PHP5.2以降のデフォルトは true
・文字列で渡したくないなら、bindValueで型指定をする・配列で渡す場合には
・executeの引数に配列を渡すと、バインドして、全てが文字列で渡される
・すでにバインドしていても無視されるから、引数でバインドする
- 投稿日:2020-01-18T14:11:35+09:00
SQL文とバインドについて
・SQLに変数を組み込むならprepare、execute
・変数がないならSQLはqueryでもいい。基本的にprepareでOK
・パラメータ部分を示す記号「?」のことをプレースホルダと呼び、そこへ実際の値を割り当てることを「バインドする」と呼びます。
・bindValueは文字列以外の型とプレスホルダーの値を渡す(使わなくてもOK)・prepare:入力を受け取る準備
・プレスホルダー:入力をSQL文に含める
・execute:SQL文の実行疑問符プレスホルダー
$stmt = $pdo->prepare('SELECT * FROM users WHERE city = ? AND gender = ?'); $stmt->execute([$city, $gender]);名前付きプレスホルダー
$stmt = $pdo->prepare('SELECT * FROM users WHERE city = :city AND gender = :gender'); $stmt->execute([':city' => $city, ':gender' => $gender]);executeの引数に配列を渡す場合(こっちの方が好き)$stmt = $pdo->prepare('INSERT INTO users (id,title,uptime) VALUES (null,?,?)'); $params = []; $params[] = $title; $params[] = $uptime; $stmt->execute($params);バインドについて
・エミュレーションがONの時、変数は文字列型になる。PHP5.2以降のデフォルトは true
・文字列で渡したくないなら、bindValueで型指定をする・配列で渡す場合には
・executeの引数に配列を渡すと、バインドされて、全てが文字列で渡される
・すでにバインドしていても無視されるから、引数でバインドする静的、動的プレスホルダーについて
・PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, [true または false]);
デフォルト、true
の一文を実行するとき以外実際にどちらのプレスホルダーを使用しているのかを意識する必要はほぼない
・また、動的プレスホルダーを利用する場合でも、進んでエスケープする必要はない
- 投稿日:2020-01-18T11:55:11+09:00
【Laravel】『Database does not exist.』エラーの原因と対処法
PHPフレームワークLaravel入門を学習中にデータベースにアクセスできない問題が発生しました。
エラーメッセージは『Database does not exist.(SQL:PRAGMA foreign_keys = ON;)』との表示。
.env
ファイルのDB_DATABASE=database.sqlite
をコメントアウトすることで解決したのですが、この記事では詳しい原因と対処法をお伝えします。エラーメッセージの意味
『Database does not exist.(SQL:PRAGMA foreign_keys = ON;)』
こちらのメッセージ、意味は「データベースが存在しません。」です。
本では誤植があったようで、実際にはデータベースファイル(database.sqlite
)のパスを指定する必要がありましたが、DB_DATABASE=database.sqLite
と入力していたため、「データベースが存在しない」というエラーが発生したようです。さらなる問題と対処法
誤植に気付き、ファイルパスを絶対パスで記入したところ、
The environment file is invalid!
のエラー。
詳細はFailed to parse dotenv file due to unexpected whitespace.
(予期しない空白のため、dotenvファイルの解析に失敗しました。)とのこと。
おそらくファイルパスに日本語が含まれていたため、うまくいかなかったのでしょう。相対パスでの表記もうまくいかず、対処法を探したところ
.env
ファイルのDB_DATABASE=〜
をコメントアウトすることでうまくいくとのこと。.envビフォー# 前略 DB_DATABASE=〜 # 後略.envアフター# 前略 # DB_DATABASE=〜 # 後略【参考】laravelにてdatabase.sqliteが存在しない(does not exist)と表示される|teratail
実際に書き換えて、サーバーを立ち上げ直したところ、きちんと動作しました。
対処法解説
では、なぜ
DB_DATABASE=〜
をコメントアウトすることで、きちんと動作するようになったのでしょうか?Laravelではデータベースを指定する際に
config/database.php
から設定を読み込みます。
このdatabase.php
ではデータベースの指定に以下のようなコードが書かれています。database.php# 前略 'database' => env('DB_DATABASE', database_path('database.sqlite')), # 後略まず、
env()
から見ていきましょう。グローバルヘルパー関数 env()
ここで使われている
env()
はLaravelに用意されているグローバルヘルパー関数の1つで、環境変数の値を取得します。
取得できない場合はデフォルト値を返します。$env = env('APP_ENV'); // APP_ENVがセットされていない場合、第二引数がデフォルト値('production')として返る $env = env('APP_ENV', 'production');
database.php
に書かれているenv('DB_DATABASE', database_path('database.sqlite'))
は、「環境変数DB_DATABASE
に保存されている値を取得する!なければdatabase_path('database.sqlite')の値を使う!」ということだったんですね。では、
DB_DATABASE
をコメントアウトすることで、取得するようになる第二引数database_path('database.sqlite')
はどういう関数なのでしょうか?グローバルヘルパー関数 database_path()
database_path()
もグローバルヘルパー関数のひとつです。
database/
ディレクトリの完全パスを返します。
database/
ディレクトリ内の指定ファイルへの完全パスを生成することもできます。$path = database_path(); // databaseディレクトリ内のfactories/UserFactory.phpへの完全パスを生成 $path = database_path('factories/UserFactory.php');
env('DB_DATABASE', database_path('database.sqlite'))
で使われていたdatabase_path('database.sqlite')
は「database/
ディレクトリのdatabase.sqlite
の完全パスを取得する!」ということだったんですね。【参考】ヘルパ 5.5 Laravel( database_path() )
2つの関数をまとめると
それぞれの関数でやっていることがわかったので、
database.php
に書かれているdatabase.php# 前略 'database' => env('DB_DATABASE', database_path('database.sqlite')), # 後略が何をしているかをまとめると、
「環境変数
DB_DATABASE
に保存されている値を取得する!なければdatabase/
ディレクトリのdatabase.sqlite
の完全パスを取得する!」ということになります。
対処法として行った「
.env
ファイルのDB_DATABASE=database.sqlite
をコメントアウトする」というのは、database_path()
で取得した完全パスをデータベースとして指定するようにするということだったんですね!その他の対処法
そうなると、「
.env
ファイルのDB_DATABASE=database.sqlite
をコメントアウトする」以外にも対処法が見えてきますね!
.env
ファイルのDB_DATABASE=database.sqlite
をコメントアウトせずにdatabase.php# 前略 'database' => env('DB_DATABASE', database_path('database.sqlite')), # 後略を
database.php# 前略 'database' => database_path('database.sqlite'), # 後略のように変更して、環境変数の読み込みをなくして直接
database.sqlite
の完全パスを指定してもきちんと動作するようになりました。まとめ
Laravelで『Database does not exist.』のエラーが出た際は、データベースのパスの指定が間違っている可能性があるので、
.env
ファイルのDB_DATABASE=database.sqlite
をコメントアウト.env# 前略 # DB_DATABASE=〜 # 後略もしくは
- 環境変数の読み込みをなくして直接
database.sqlite
の完全パスを指定database.php# 前略 'database' => database_path('database.sqlite'), # 後略を試してみましょう!
参考まとめ