20200118のPHPに関する記事は8件です。

Laravel6でページネーションのカスタマイズ

概要

Laravelのページネーションに触れてみたので備忘録です。
基本的に公式ページに全て書いてある。
Database: Pagination - Laravel - The PHP Framework For Web Artisans

環境

PHP: 7.2.22
Laravel: 6.11.0

事前準備

テスト用の各種設定は以下の通りです。ユーザやルーティングを適当に設定しています。

UsersController.php
class 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>

スクリーンショット 2020-01-18 21.21.59.png

ページネーション設定

以下コマンドを実行すると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') }}

スクリーンショット 2020-01-18 22.12.46.png

index.blade.php
{{ $users->links('vendor.pagination.semantic-ui') }}

スクリーンショット 2020-01-18 22.12.58.png

前か次かだけのシンプルなページングを指定することも可能です。

index.blade.php
{{ $users->links('vendor.pagination.simple-default') }}

スクリーンショット 2020-01-18 23.43.27.png

デフォルトで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">&laquo;</span>
                </li>
            @else
                <li class="page-item">
                    <a class="page-link text-success" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">&laquo;</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')">&raquo;</a>
                </li>
            @else
                <li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
                    <span class="page-link" aria-hidden="true">&raquo;</span>
                </li>
            @endif
        </ul>
    </nav>
@endif

スクリーンショット 2020-01-18 23.05.00.png

まとめ

Laravelのページネーションは意外と簡単に実装できる。
スタイルの変更も分かりやすく、自由に修正できる。

参考サイト

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

PHPで文字を画像にするやつ

ちょっと、そういうのが必要になったので。(WEBGLで日本語フォントが通らないとか・・・)

im.php?str=こんにちは,世界にアクセスすると、カンマ区切りで改行して、こんな画像を生成します。

スクリーンショット 2020-01-18 22.46.15.png

<?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);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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できなかった件

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

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 Technologies

Stream切り替え

# 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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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の引数に配列を渡すと、バインドして、全てが文字列で渡される
・すでにバインドしていても無視されるから、引数でバインドする

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

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
の一文を実行するとき以外実際にどちらのプレスホルダーを使用しているのかを意識する必要はほぼない
・また、動的プレスホルダーを利用する場合でも、進んでエスケープする必要はない

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

【Laravel】『Database does not exist.』エラーの原因と対処法

スクリーンショット 2020-01-18 10.30.34.png

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')の値を使う!」ということだったんですね。

【参考】ヘルパ 5.5 Laravel( env() )

では、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'),
# 後略

を試してみましょう!

参考まとめ

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