20200627のPHPに関する記事は7件です。

Laravel MySQL DBのカラム名を途中で変更する

目的

  • Laravelにて新規作成後のDBのカラム名の変更方法をまとめる

実施環境

  • ハードウェア環境
項目 情報
OS macOS Catalina(10.15.5)
ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
プロセッサ 2 GHz クアッドコアIntel Core i5
メモリ 32 GB 3733 MHz LPDDR4
グラフィックス Intel Iris Plus Graphics 1536 MB
  • ソフトウェア環境
項目 情報 備考
PHP バージョン 7.4.3 Homwbrewを用いて導入
Laravel バージョン 7.0.8 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う
MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする

前提情報

  • MySQLを使用しているが確認箇所以外はそのほかのRDSでも作業内容は変わらない。
  • カラム名を変更するとLaravelアプリで自分で実装したデータ取得処理を変更しないといけない場合があるので注視する。
  • すでに存在するカラムの名前を変更する際の方法を記載する。
  • 本方法と応用するとカラムタイプなどの変更可能となる。
  • 公式ドキュメントに記載されている内容を元に自分なりにまとめてみる。

概要

  1. ライブラリのインストール
  2. マイグレーションファイルの作成と記載
  3. マイグレート
  4. 確認

詳細

  1. ライブラリのインストール

    1. アプリ名ディレクトリで下記コマンドを実行してライブラリをインストールする。

      $ composer require doctrine/dbal
      
  2. マイグレーションファイルの作成と記載

    1. アプリ名ディレクトリで下記コマンドを実行してマイグレーションファイルを作成する。

      $ php artisan make:migration rename_変更する前のカラム名_to_変更した後のカラム名_on_所属テーブル名_table --table=所属テーブル名
      
    2. アプリ名ディレクトリで下記コマンドを実行してマイグレーションファイルを開く。

      $ vi database/migrations/YYYY_MM_DD_XXXXXX_rename_変更する前のカラム名_to_変更した後のカラム名_on_所属テーブル名_table.php
      
    3. マイグレーションファイルを下記の様に修正する。(public function up()にはマイグレーションにより実行したい処理(今回だとカラムのリネーム)処理を記載する。public function down()にはロールバックで実行したい(カラムのリネームを直す)処理)

      database/migrations/YYYY_MM_DD_XXXXXX_rename_変更する前のカラム名_to_変更した後のカラム名_on_所属テーブル名_table.php
       <?php
      
      use Illuminate\Database\Migrations\Migration;
      use Illuminate\Database\Schema\Blueprint;
      use Illuminate\Support\Facades\Schema;
      
      class Rename変更する前のカラム名To変更した後のカラム名Onテーブル名Table extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::table('テーブル名', function (Blueprint $table) {
                  //下記を追記する
                  $table->renameColumn('変更する前のカラム名', '変更した後のカラム名');
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::table('テーブル名', function (Blueprint $table) {
                  //下記を追記する
                  $table->renameColumn('変更した後のカラム名', '変更する前のカラム名');
              });
          }
      }
      
  3. マイグレート

    1. アプリ名ディレクトリで下記コマンドを実行してマイグレートを実行する。

      $ php artisan migrate
      
  4. 確認

    1. 下記コマンドを実行してMySQLにターミナルからログインする。(MySQLのパスワードを忘れてしまった方はこちら→Mac ローカル環境の MySQL 8.0 のrootパスワードを忘れた時のリセット方法)

      $ mysql -u root -p
      
    2. 下記を実行してカラム名が変更されたことを確認する。

      mysql> show columns from DB.テーブル名;
      

参考文献

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

【Laravel】グローバルスコープを用いてコード量を減らす

はじめに

実装していてモデルのクエリに制約で何度も同じ実装することはありませんか。
そんな時はグローバルスコープというLaravelの機能のグローバルスコープを使って1回の実装で済むようにするのも1つの方法かなと思います。

グローバルスコープとは

グローバルスコープにより、指定したモデルの全クエリに対して、制約を付け加えることができます。Laravel自身のソフトデリート機能は、「削除されていない」モデルをデータベースから取得するためにグローバルスコープを使用しています。独自のグローバルスコープを書くことにより、特定のモデルのクエリに制約を確実に、簡単に、便利に指定できます。

引用:Eloquent:利用の開始 7.x Laravel

グローバルスコープを1回の実装すれば特定のモデルのクエリに制約ができ、かなり便利です。

グローバルスコープの実装

Illuminate\Database\Eloquent\Scope配下に適当なファイルを作成します。

walkingMinutes.php
<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class walkingMinutesScope implements Scope
{
    /**
     * Eloquentクエリビルダへ適用するスコープ
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function setGlobalScope(Builder $builder, Model $model)
    {
        static::addGlobalScope('walking_minute', function (Builder $builder) {
            $builder->orderByRaw('walking_minute' ASC NULLS LAST);
        });
    }
}

こんな感じに実装するとどこでもwalking_minutes(徒歩時間)が短い順に表示できるようになります。

おわりに

いかがでしたでしょうか。
うまく実装して無駄な実装を減らしていきましょう。

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

【PHP】DateIntervalクラスで、あさってが「1日差」になっちゃった!?

環境

CentOS 7.6
PHP 7.1.20

現象

PHPの DateInterval クラス は、
今日が 2020/01/01 とすると、2020/01/03 との日数差が
なぜか「1」で返る場合があります(2が欲しいのに。)

$date1 = new DateTime();             //今日
$date2 = new DateTime('2020-01-03'); //あさって
$diff = $date1->diff( $date2 );

echo $diff->days;  // 1

原因

今日の $date1 = new DateTime(); に現在時刻が含まれているからです。
その分、日数差が2日に届かず、1日となっているようです。

例えば 現在時刻をクリアすれば、期待する「2」が得られます。

$date1 = new DateTime();
$date1->setTime(0,0,0);  //時刻クリア

$date2 = new DateTime('2020-01-03');
$diff = $date1->diff( $date2 );

echo $diff->days; // 2

余談ですが、DateTime::diff のマニュアルには、
英語コメントに同様の記述がありました。

参考

PHPのDateTimeで日付差分を得る時は、dではなくdaysを使う。

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

Laravel開発用のDockerイメージできたのでシェアします。

これからLaravelを使って開発とかしていく予定だったので、すぐにスタートできるようにDockerでイメージ作りました。
同じ環境で開発してる方など、よかったら持ってってください。

https://hub.docker.com/r/ryuki0529/webserver

大まかなイメージ環境

  • OS:CentOS 7.8
  • サーバー:Apache 2.4.6
  • PHP 7.4.7
  • PHPMyAdmin 5.0.2
  • Composer 1.10.7
  • Laravel Installer 3.1.0
  • Git 2.9.5
  • データベース:mysql Ver 15.1 Distrib 10.4.13-MariaDB

注意点

docker runでコンテナ作るときに、--privilegedと起動時のコマンドで/sbin/initを指定しないとsystemctlコマンド周りが使えないので注意です。これで3時間ほどハマってしまいました。

詳しくは下記の記事で説明されてます。
CentOS7のコンテナでsystemctlを使うための方法

ということで、最終的にコマンドは以下になります。

docker run -itd -p 80:80 --privileged webserver:1.0.2 /sbin/init
docker exec -it webserver /bin/bash
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Eccube で OutOfMemoryException が出た時にやってみたこと

$qb = $em->getRepository('Eccube\Entity\Order')->createQueryBuilder('o');
$qb
    // query builder に関する処理 ...
    ;

$query = $qb->getQuery();
$result = $query->getResult();

foreach($result as $Order) {

    // Order に対する処理

}

こうすると巨大なOrder オブジェクトに対して一度に処理することになりOutOfMemoryException が発生した。

ので、

$qb = $em->getRepository('Eccube\Entity\Order')->createQueryBuilder('o');
$qb
    // query builder に関する処理 ...
    ;

$query = $qb->getQuery();
$iterableResult = $query->iterate();

foreach($iterableResult as $count => list($Order)) { // list() でアンラップ

    // Order に対する処理

    if (++$count % 1000 === 0) {
        $em->clear(); // 1000回トラバースする毎にEntityManagerのオブジェクトを開放
    }
}

\$query->getResult() で結果セット全体を一度に持ってきていたところを、$query->iterate() で一つずつ処理するようにし、1000回処理するごとにメモリーを開放するようにしました。

これでOutOfMemoryException が起きなくなりました。

iterate で持ってきた result は array でラップされているとのことで、list() でアンラップすればgetResult() のときの \$Order と同じように扱えます(\$Order->getId() とかが使える)。

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

【SQL】3つのテーブルのリレーション方法

はじめに

こんにちは、takumi(@takumidiary)です。
タイトルの通り今回は3つのテーブルのリレーションをします。

WEBサービスを開発している過程で3つのテーブルをリレーションしないといけない場面があったので調べながら実装しました。意外と簡単です。

環境

OS : mac Catalina vaersion10.15.5
ディベロッパーツール : MAMP version 5.7

目次

1. テーブルの準備
2. リレーションする
 2-1. 方法1〜外部結合
 2-2. 方法2〜内部結合
3. おわりに

1. テーブルの準備

以下の3つのテーブルを準備します。
phpMyAdmin使いました。

  • userテーブル
  • areaテーブル
  • itemテーブル

userテーブル

id name area_id
1 浦島 1
2 4
3 3
4 雉子 3
5 2

areaテーブル

id name
1 竜宮城
2 犬小屋
3 動物園
4
5 北海道

itemテーブル

id name user_id
1 2
2 黍団子 2
3 1
4 羽根 4
5 ドッグフード 5

2. リレーションする

2つの方法でリレーションしていきます。

2-1. 方法1〜外部結合

sql文

SELECT * FROM user LEFT JOIN item ON user.id=item.user_id LEFT JOIN area ON user.area_id=area.id;

このsql文をphpMyAdminのsqlタブに入力して実行します。

実行結果

スクリーンショット 2020-06-27 10.59.36.png

2-2. 方法2〜内部結合

sql文

SELECT * FROM user INNER JOIN item ON user.id=item.user_id INNER JOIN area ON user.area_id=area.id

実行結果

スクリーンショット 2020-06-27 11.02.09.png

3. おわりに

今回は簡単のため、'WEHERE'句などは使っていないので条件を追加したりして自分で試してみましょう。

間違いなどありましたら、ご指摘お願いします。

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

foreach と type="radio" の共存の仕方

foreach (PHP)

<?php
$fruits = ["ぶどう", "みかん", "もも"];

foreach ($fruits as $value) {
    echo $value;
}
?>

こう表示される

ぶどうみかんもも

type="radio" (HTML)

<input type="radio">

ガッチャンコする

<?php
        $fruits = ["ぶどう", "みかん", "もも"];

foreach ($fruits as $value) { ?>
    <input type="radio">
    <?php echo $value;
}
?>

こんな感じで表示される

●ぶどう●みかん●もも

思ったこと

ベースをHTMLにして書いてるからPHPとして埋め込んで書くところをちゃんと指定して区別してやってあげないとね!って感じ

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