20210117のPHPに関する記事は14件です。

Warning: Illegal string offset ' ' in... の解決方法

今回は、SQLから取得したデータをsmartyを使って、foreachでtable表示させようとした際に発生したエラーが解決した方法をご紹介します。

発生したエラー

Warning: Illegal string offset '出力変数の各カラム名' in...

下記のサイトを参考に解決したのですが、全て英語で書かれた記事なので、正直正確なエラー発生の原因がわかっていません。
どなたか詳しい原因が分かる方いましたらコメントにて教えて頂けると幸いです。
私の場合は、どうやら出力変数のキーを文字列で指定していた為に発生したようです。

・参考サイト
https://stackoverflow.com/questions/9869150/illegal-string-offset-warning-php#:~:text=The%20error%20Illegal%20string%20offset,string%20as%20a%20full%20array.&text=For%20those%20who%20come%20to,about%20it%2C%20as%20I%20was

エラーが発生したコードと修正コード

list2.php(データ取得)修正前

<?php
require_once('../db_connect2/db_connect2.php');
require( dirname( __FILE__ , 3).'/libs/Smarty.class.php' );

$smarty = new Smarty();

$smarty->template_dir = dirname( __FILE__ , 3).'/templates';
$smarty->compile_dir  = dirname( __FILE__ , 3).'/templates_c';
$smarty->config_dir   = dirname( __FILE__ , 3).'/configs';
$smarty->cache_dir    = dirname( __FILE__ , 3).'/cache';

$smarty->escape_html  = true;

try
{
  $sql = 'SELECT stock_id,purchase_date,deadline,stock_name,price,number FROM stocks WHERE 1';
  $stmt = connect()->prepare($sql);
  $stmt->execute();
  $rec = $stmt->fetch(PDO::FETCH_ASSOC); //ここで、結果セットに返された際のカラム名で添字を付けた配列を返したことが原因。
  $dbh = null;
}
catch(Exception $e)
{
  echo "エラー発生:" . htmlspecialchars($e->getMessage(),ENT_QUOTES, 'UTF-8') . "<br>";
  print'ただいま障害により大変ご迷惑をお掛けしております。';
  exit();
}

$smarty->assign('stock', $rec);
$smarty->display('list.tpl');
?>

修正コード

try
{
  $sql = 'SELECT stock_id,purchase_date,deadline,stock_name,price,number FROM stocks WHERE 1';
  $stmt = connect()->prepare($sql);
  $stmt->execute();
  $rec = $stmt->fetch(PDO::FETCH_ASSOC); //ここで、結果セットに返された際のカラム名で添字を付けた配列を返したことが原因。
  $dbh = null;
}

↓

try
{
  $sql = 'SELECT stock_id,purchase_date,deadline,stock_name,price,number FROM stocks WHERE 1';
  $stmt = connect()->prepare($sql);
  $stmt->execute();
  $dbh = null;
}

list.tpl(出力)修正前

<table class = "sorttbl" id = "myTable" border = "2">
    <tr>
      <th class = "radio-th"></th>
      <th class = "purchase_date-th">購入日</th>
      <th class = "stock_name-th">商品</th>
      <th class = "price-th">値段</th>
      <th class = "number-th">数量</th>
      <th class = "deadline-th" onclick = "w3.sortHTML('#myTable','.item', 'td:nth-child(6)')">消費期限&nbsp;<i class = "fa fa-sort"></i></th>
    </tr>

    //出力変数のキーを文字列で指定しているのが原因
    {foreach $stock as $s}
      <tr class = "item">
        <td><input type = "radio" name = "stockid" value = "{$s.stock_id}"></td>
        <td>{$s.purchase_date|date_format:'%Y-%m-%d'}</td>
        <td>{$s.stock_name}</td>
        <td>¥{$s.price}</td>
        <td>{$s.number}</td>
        <td>{$s.deadline|date_format:'%Y-%m-%d'}</td>
      </tr>
    {/foreach}
  </table>

修正コード

{foreach $stock as $s}
  <tr class = "item">
    <td><input type = "radio" name = "stockid" value = "{$s.stock_id}"></td>
    <td>{$s.purchase_date|date_format:'%Y-%m-%d'}</td>
    <td>{$s.stock_name}</td>
    <td>¥{$s.price}</td>
    <td>{$s.number}</td>
    <td>{$s.deadline|date_format:'%Y-%m-%d'}</td>
  </tr>
{/foreach}

↓

{foreach $stock as $s}
  <tr class = "item">
   <td><input type = "radio" name = "stockid" value = "{$s[0]}"></td>
   <td>{$s[1]|date_format:'%Y-%m-%d'}</td>
    <td>{$s[3]}</td>
    <td>¥{$s[4]}</td>
    <td>{$s[5]}</td>
    <td>{$s[2]|date_format:'%Y-%m-%d'}</td>
  </tr>
{/foreach}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerでapache7.4+mysql8環境構築(初期データ入り)

今更ですが、Macで表題の環境を作らなくてはいけなくなったので、構築してみました。
備忘録として書いておきます。

環境

マシン macOS Catalina 10.15.7

構成

ファイル、ディレクトリの構成はざっくりと以下のようにします。

任意のディレクトリ
  │
  ├── docker-compose.yml
  │
  ├── html/
  │   └── index.html
  │
  ├── mysql/
  │   ├── Dockerfile
  │   ├── data/
  │   ├── init/
  │   │   └── init.sql
  │   └── my.cnf
  │
  ├── php-apahce/
      ├── Dockerfile
      └── php.ini

この構築の重要な部分

docker-compose.ymlとDockerfileがこの構築の重要な部分になります。

ファイル名 説明
docker-compose.yml コンテナの構成を定義するもの。コンテナ間通信の定義もできる。
Dockerfile dockerのイメージに対する定義。

docker-compose.ymlの要素

調べて自分が認識している限りだと以下の通り

名称 意味
build Dockerfileがある位置を指定
volumus ローカル内のマウントされる場所:コンテナ内のマウントする場所
ports ポートフォワード
container_name コンテナの名前 docker container lsのname
environment 環境変数?変数名で何を意味するかがなんとなくわかる

Dockerfileの要素

調べて自分が認識している限りだと以下の通り

名称 意味
FROM 何をどのバージョンで
EXPOSE どのポートを使用するか
ADD ローカルファイルをコンテナ内ファイルに追記
CMD コンテナ起動時に実行されるやつ
COPY ローカルファイルをコンテナ内ディレクトリにコピーする
RUN イメージ作成時に呼ばれるやつ。なのでパッケージのインストール等を書く。

構築

本編はここからです。

確認

まずコンテナの状態確認

ksk@ksknoMacBook-Pro work % docker container ls -a
CONTAINER ID   IMAGE             COMMAND                  CREATED       STATUS       PORTS                               NAMES

何もいません

./docker-compose.yml

docker-compose.ymlとは、コンテナの構成を定義するファイル

docker-compose.yml
version: '3'
services:
  php-apache:
    build: ./php-apache/
    volumes:
      - ./html:/var/www/html
    ports:
      - 8080:80
    container_name: web
  mysql:
    build: ./mysql/
    volumes:
      - "./mysql/data:/var/lib/mysql"
      - "./mysql/init:/docker-entrypoint-initdb.d"
    environment:
      - MYSQL_ROOT_PASSWORD=docker
      - MYSQL_DATABASE=mydb
      - MYSQL_USER=appuser
      - MYSQL_PASSWORD=appuser1
    container_name: db
    ports:
      - 3306:3306

ymlに書いている属性?で、自分が理解していることを以下の表に書いてみる
(間違っているところを指摘してくれる優しい人いたら教えてください)

./html/index.php

動作確認するために使用。
とりあえず、DBのデータを表示できれば良しとする。
volumesの定義により、htmlがドキュメントルートとなる。

index.php
<?php
try {
    $db = sprintf('mysql:host=%s:3306;dbname=%s',  'mysql', 'mydb');
    $dbh = new PDO($db, 'appuser', 'appuser1');
    foreach($dbh->query('select * from users') as $row) {
        echo $row['name'] . '<br>';
    }
    $dbh = null;
} catch (PDOException $e) {
    echo $e;
    die();
}
$dbh = null;

hostの指定で「'mysql'」としていますが、これはdocker-compose.ymlのservice名と理解しています。

docker-compose.yml
  mysql:     ←これ!!!
    build: ./mysql/
    volumes:

./mysql/Dockerfile

mysql側のDockerfile
DockerfileとはDockerイメージの定義を書くファイルです。

FROM mysql:8.0

EXPOSE 3306

ADD ./my.cnf /etc/mysql/conf.d/my.cnf

CMD ["mysqld"]

./mysql/init/init.sql

適当なテーブルとデータを詰め込むような記述にしておく

use mydb;

CREATE TABLE users (
  id int(10) unsigned not null auto_increment,
  name varchar(255) not null,
  primary key (id)
);

insert into users(name) values('hogeo');
insert into users(name) values('fugao');

./mysql/my.cnf

my.cnf
[mysqld]
character-set-server=utf8
default_authentication_plugin=mysql_native_password

[mysql]
default-character-set=utf8

[client]
default-character-set=utf8

default_authentication_plugin=mysql_native_passwordについて

mysqlのデフォルト認証プラグインが変わったので、デフォルトの認証プラグインを変更しています。
mysqlの環境変数でユーザ(appuser)作っていますが、mysql_native_passwordという認証プラグインで設定されます。
デフォルトのままだと、phpがmysqlへのアクセスで失敗します。

./php-apache/Dockerfile

色んなサイトを見て参考にさせてもらいました。

FROM php:7.4-apache
COPY ./php.ini /usr/local/etc/php/
RUN apt-get update
RUN apt-get install -y zip unzip vim libpng-dev libpq-dev
RUN docker-php-ext-install pdo_mysql

./php-apache/php.ini

色んなサイトを見て参考にさせてもらいました。

[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

docker-compose build

上記を作った後、docker-compose.ymlと同階層で以下のコマンド実行

ksk@ksknoMacBook-Pro work % docker-compose build
〜〜〜中略〜〜〜
Successfully built e5b1c15e825e
Successfully tagged work_php-apache:latest
Building mysql
Step 1/4 : FROM mysql:8.0
 ---> d4c3cafb11d5
Step 2/4 : EXPOSE 3306
 ---> Using cache
 ---> e11d55e213ab
Step 3/4 : ADD ./my.cnf /etc/mysql/conf.d/my.cnf
 ---> Using cache
 ---> 6dd70a6b7ecd
Step 4/4 : CMD ["mysqld"]
 ---> Using cache
 ---> c22190479ddf

Successfully built c22190479ddf
Successfully tagged work_mysql:latest

コンテナ作成&起動

ksk@ksknoMacBook-Pro work % docker-compose up -d
Creating web ... done
Creating db  ... done

確認

コンテナの状態確認

ksk@ksknoMacBook-Pro work % docker container ls -a
CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS         PORTS                               NAMES
b416b97d3f7b   work_mysql        "docker-entrypoint.s…"   2 seconds ago   Up 2 seconds   0.0.0.0:3306->3306/tcp, 33060/tcp   db
9985abb2eb90   work_php-apache   "docker-php-entrypoi…"   2 seconds ago   Up 2 seconds   0.0.0.0:8080->80/tcp                web

コンテナが確認できました

画面確認

http://localhost:8080
こちらへアクセス

qiita_20200117_01.png

以上!

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

【コピペ】Docker ComposeでLaravel開発環境を構築その参

前回、docker-compose.yml達と一緒にLaravelをリポジトリ管理して、かなりスッキリした。
【コピペ】Docker ComposeでLaravel開発環境を構築その弐

でも、ふと思った、、、Laravelは別リポジトリで管理したいな。。。

マシンスペック

  • Mac mini 2018
  • macOS Catalina(10.15.x)
  • Intel Core-i7 3.2GHz 6コア
  • メモリ 32GB
  • SSD 512GB

やること

  • Docker Compose環境のLaravelを別リポジトリにする

前提条件

  • 空リポジトリを用意しておく

Docker Compose環境の準備

【コピペ】Docker ComposeでLaravel開発環境を構築その弐#使い方

src/laravelを別リポジトリにする

[Mac]$ pwd
/Users/xxx/docker
[Mac]$ cd src
[Mac]$ mv laravel laravel_bak
[Mac]$ git clone <前提条件で用意したリポジトリURL> laravel
[Mac]$ cp -pR laravel_bak/. laravel

以降は、IDEで src/laravel を開いてプッシュする

※注)dockerをIDEで開くと、dockerの方のリポジトリにプッシュされるので、src/laravelを開くこと!

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

Laravelの実行環境を一から構築する

Laravelには「Homestead」と「Laradock」があり、簡単に開発環境を用意することができます。しかし、これらを本番環境で使用することはできませんし、Dockerやサーバーレスを使わない場合は一から環境を構築する必要があります。この記事では、Laravelの実行環境を一から構築する手順を説明します。

使用ソフトウェア・バージョン

  • Laravel 8.21.0
  • PHP 8.0(PHP-FPM)
  • Nginx 1.18.0
  • MySQL 8.0.22
  • Ubuntu 20.04

*Dockerは使いません

参考にしたコード

HomesteadはLaravel公式の開発環境ですが、Homesteadを構築するコードがGitHubで公開されています。

laravel/settler

scripts/provision.sh」に環境を構築するコードが記述されています。Homesteadは多様な環境に対応できるよう多くのパッケージをインストールしているため、このコードを参考に必要なものだけインストールするようにします。

実行手順

1.PHPのインストール
2.php.iniの設定
3.PHP-FPMユーザーの作成
4.PHP-FPMの設定
5.Nginxの設定
6.Composerのインストール
7.Laravelのインストール・設定

1.PHPのインストール

  • ppa:ondrej/phpリポジトリをシステムに追加する
  • PHP8(PHP-FPM)および拡張機能のインストール

PHPのバージョン選定

まずPHPのバージョンを選定します。利用可能なもののうち最も新しいバージョンが好ましいですが、環境によっては最新のものが利用できない場合があります。

Ubuntu20.04(LTS)の場合、apt-get installでインストールできるバージョンはPHP7.4のため、現時点(2021年1月)で最新のPHP8がインストールできません。そのため、PPAを使ってインストールするようにします。

PPA(Personal Package Archive)は個人が管理している非公式のリポジトリです。最新のパッケージが使えますがアップデートの保証はないため、リポジトリの選定と扱いには気を付ける必要があります。PHPのインストールには以下のPPAを使います。

ppa:ondrej/php

このリポジトリは、Debianの開発者でありPHP5の頃からパッケージ管理を行っている人のもので、公式パッケージもこのリポジトリを採用していることから信頼できるリポジトリと言えます。

ppa:ondrej/php開発者のページ

また、調べたところUbuntu公式のPHPパッケージのリリースは1年ほど前でしたが(更新されていない)、PPAは1ヶ月程度でアップデートされています。PPAの方がセキュリティパッチが更新される頻度が多いためより安全であると思われます。

・ppa:ondrej/phpリポジトリをシステムに追加する

sudo add-apt-repository ppa:ondrej/php
sudo apt-get update

Laravelのサーバー要件

次にPHPをインストールしますが、まずは公式ホームページでLaravel 8.×のサーバー要件を確認します。

Laravelのサーバー要件

  • PHP >= 7.3
  • BCMath PHP Extension
  • Ctype PHP Extension
  • Fileinfo PHP Extension
  • JSON PHP Extension
  • Mbstring PHP Extension
  • OpenSSL PHP Extension
  • PDO PHP Extension
  • Tokenizer PHP Extension
  • XML PHP Extension

太字の「BCMath」「Mbstring」「XML」以外はPHPをインストールすると有効になるため、PHPおよび3つの拡張機能をインストールすれば要件を満たすことができます。

・PHP8(PHP-FPM)および拡張機能のインストール(ppa:ondrej/php)

sudo apt-get install php8.0-fpm php8.0-bcmath php8.0-mbstring php8.0-xml php8.0-mysql php8.0-zip

php-fpmとLaravelに必要な3つの拡張機能およびMySQL拡張機能をインストールしています。php8.0-zipはLaravelのインストールで必要になります。

*NginxではなくApacheを使う場合は「php8.0-fpm」ではなく「php8.0」をインストールしてください。Apacheおよび関連パッケージがインストールされます。

php8.0-fpmには以下のパッケージも含まれています。

php-common php8.0-cli php8.0-opache php8.0-readline

これらはLaravelが動作する最低限の拡張機能であるため、必要になった時点で他のパッケージもインストールしましょう。上記で紹介した「laravel/settler」のprovision.shでは、どのような拡張機能を使用しているか確認することができます。またPHP開発者の新原さんのブログも参考になると思います。

Shin x Blog

2.php.iniの設定

  • FPMとCLIのphp.iniを設定する

PHPの設定ファイルは以下の2つです。

  • /etc/php/8.0/fpm/php.ini(FPM)
  • /etc/php/8.0/cli/php.ini(CLI)

これらのファイルは本番用の推奨設定ファイルである以下と同じものです。

  • /usr/lib/php/8.0/php.ini-production(FPM)
  • /usr/lib/php/8.0/php.ini-production.cli(CLI)

・FPMとCLIのphp.iniを設定する

*以下は「FPM」「CLI」両方の設定ファイルで変更

memory_limit = 512M
date.timezone = "Asia/Tokyo"

*以下は「FPM」の設定ファイルでのみ変更

upload_max_filesize = 100M
post_max_size = 100M

なお、これらの値はHomesteadで使用されている値ですので、環境に応じて適切な値を設定してください。

また、開発環境の場合はエラーを表示するように設定します。

error_reporting = E_ALL
display_errors = On

3.PHP-FPMユーザーの作成

  • 新規ユーザー作成
  • デフォルトのパーミッション設定
  • authorized_keysの設定
  • デプロイディレクトリの作成

PHP-FPMをインストールするとデフォルトのユーザーである「www-data」が作成されます。このwww-dataまたはnginxユーザーを使用することもできますが、セキュリティ上好ましくないため新たにPHP-FPMユーザー(PHP実行ユーザー)を作成します。

PHP-FPMとNginxのユーザーおよびパーミッションについては以下の記事が参考になります。

NGINX and PHP-FPM. What my permissions should be?

・新規ユーザーの作成

sudo useradd phpuser

このユーザーにはsudo権限は与えません。また、第三者がファイルを操作できないよう「.bashrc」に以下を追記します。

・デフォルトのパーミッション設定

umask 0027

パーミッションは以下のようになります。

  • ディレクトリ 750
  • ファイル 640

SSHログインまたはdeployerを使う場合は認証が必要となるため、以下に公開鍵を設定しておきます。

・authorized_keysの設定

/home/phpuser/.ssh/authorized_keys

・デプロイディレクトリの作成

sudo mkdir /var/www 
sudo chown phpuser:phpuser /var/www 
sudo chmod 750 /var/www

デプロイ先は「/var/www」でなくても構いませんが、PHP-FPMユーザーを所有者としパーミッションを750に設定しましょう。

4.PHP-FPMの設定

  • PHP-FPMの設定ファイルを編集する
  • PHP-FPMを再起動する

新しく作成したユーザーをPHP-FPMのユーザーとして設定します。

・PHP-FPMの設定ファイルを編集する

sudo vi /etc/php/8.0/fpm/pool.d/www.conf

user = phpuser
group = phpuser
listen = /run/php/php8.0-fpm.sock *UNIXドメインソケット(デフォルトのまま)
listen.owner = phpuser *Unixドメインソケットを使う場合に設定が必要
listen.group = phpuser

UnixドメインソケットではなくTCP接続を行う場合は下記のように「IPアドレス:ポート番号」で設定します。

listen = 127.0.0.1:9000

・PHP-FPMを再起動する

sudo systemctl restart php8.0-fpm

5.Nginxの設定

  • NginxユーザーにPHP-FPMグループを加える
  • 設定ファイルを編集 /etc/nginx/conf.d/default.conf
  • Nginxの再起動

*Nginxは公式を参照してインストールしてください

Nginxのインストール

・NginxユーザーにPHP-FPMグループを加える

sudo gpasswd -a nginx phpuser

これはNginxがPHP-FPMと通信を行う際にパーミッションエラーを起こさないようにするための措置です。

続いて、Laravel公式の設定例を参考にして設定ファイルを編集します。

Laravel用のNginx設定

変更する箇所は以下になります。

・設定ファイルを編集 /etc/nginx/conf.d/default.conf

server_name localhost; *本番はドメイン名
root /home/ubuntu/laravel/public *開発環境
root /var/www/current/public; *本番環境(deployerを使う場合)
fastcgi_pass unix:/run/php/php8.0-fpm.sock;

rootディレクティブには、Laravelの公開ディレクトリ(public)のパスを指定します。上記はdeployerを使って「/var/www/」に「laravel」というプロジェクト名でデプロイした場合のディレクトリになります。開発環境の場合はデフォルトユーザーであるubuntuのホームディレクリで良いかと思います。

・Nginxの再起動

sudo systemctl restart nginx

6.Composerのインストール

Composerは公式に参照してインストールしてください。

Composerのインストール

7.Laravelのインストール・設定

  • Laravelのインストール
  • 「.env」の編集
  • config/database.phpの編集
  • config/app.phpの編集
  • パーミッションの設定

ユーザーUbuntuのホームディレクリでLaravelをインストールします。

・Laravelのインストール

composer create-project --prefer-dist laravel/laravel laravel(プロジェクト名)

バージョンを指定する場合は「laravel/laravel」の後に「=」を付けて指定します。

例:laravel/laravel=8.4.0

「--prefer-dist」オプションはzipでダウンロードするので高速です。

以下のコマンドでインストールされたバージョンを確認します。

cd laravel
php artisan -V

インストール完了後「.env」「config/databse.php」「config/app.php」の3つの設定ファイルを編集します。

MySQLを使う場合は「.env」に以下を設定します。

・「.env」の編集

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mysql *データベース名
DB_USERNAME=mysql-user
DB_PASSWORD=mysql-password

「.env」ファイルは機密情報を含みgit管理下に含まれないため、別途保存しておいてデプロイ時にコピーする必要があります。

データベースの設定ファイルは「.env」以外に「config/databse.php」があります。このファイルは「.env」に値が設定されていない場合にのみ適用されます。そのため、必要な箇所のみ変更します。

・config/database.phpの編集

'connections' => [
  'mysql' => [
    'collation' => 'utf8mb4_bin',

MySQLのcollation(照合順序)である「utf8mb4_bin」は、大文字・小文字、ひらなが・カタカナ、絵文字などすべての文字を異なるものとして判定します。日本語を使う場合に適したcollationです。

続いて、app.phpでタイムゾーンを東京に変更します。

・config/app.phpの編集

'timezone' => 'Asia/Tokyo',

最後に、laravelディレクリのパーミッションをディレクトリ(755)ファイル(640)にしておきます。

・パーミッションの設定

chmod -R u=rwX,g=rX,o= /home/ubuntu/laravel

以上で環境の構築は完了です。開発環境であればlocalhostにアクセスするとLaravelのwelcomeページが表示されるはずです。これらの手順を毎回実行するのは煩雑なので、Ansible等を使うまたはスクリプト化して自動で行うことをお勧めします。

laravel.png

終わりに

LaravelにはHomesteadやLaradockなど開発環境を簡単に用意できるものがありますが、一から構築するとなるとなかなか大変です。PHPパッケージのインストールやPHP-FPM/Nginxの設定など、まとまった情報がなかったので今回まとめて記事にしました。環境構築の一助になれば幸いです。

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

Laravel 多対多。野球選手を例にして考えてみる

Laravel多対多について

多対多の概念や使い方が難しかったので、野球選手とポジションを例に考えてみる。
野球選手:ポジション

例えば、

選手目線

大谷は投手と外野の複数のポジションを守れる

ポジション目線

外野は大谷とイチロ-が守れる
このとき、野球選手とポジションは多対多の関係にあるといえる
この考えから下記のテーブルを作成する。

users(選手)目線

イチロー(1):外野(4)
大谷(2):投手(1)、外野(4)
阿部(3):捕手(2)、内野(3)

ポジション目線

投手(1):大谷(2)
捕手(2):阿部(3)
内野(3):阿部(3)
外野(4):イチロー(1)と大谷(2)
image.png

image.png

image.png

このとき、選手目線からみたポジションの情報がほしいときは下記のModelを作成する

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Member extends Model
{

    public function potisions()
    {
                // 第2,3,4引数は省略できる
                // 実際は第2:users_positions 第3:users_id 第4:positions_id 
        return $this->belongsToMany('App\Potision');
    }

}

このModelを使えば、選手目線の情報(例えば大谷は投手と外野)が取得できる。
逆にポジション目線の情報(例えば外野はイチローと大谷)が欲しい場合は下記のモデルを作成する。

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Potision extends Model
{
      public function members()
    {
                // 第2,3,4引数は省略できる
        return $this->belongsToMany('App\User');
    }  
}

これらのModelを使って情報を取得する。

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

AjaxでJavaScriptからPHPのサーバに文字列を引数にしてWebAPIを実行する例

クライアント側のhtmlファイル

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<style></style>
</head>
<body>
<input type="text" id="input_message">
<button onclick="PostString()">WebAPI実行</button>
<div id="result">ここにWebAPIの結果が入ります</div>
</body>
</html>

<script>
function PostString()
{
    const xhr = new XMLHttpRequest();

    //http://XXXXXXX.jp/test.php が今回呼び出すWebAPIを記述したphpファイル
    xhr.open('POST', 'http://XXXXXXX.jp/test.php');

    //文字列を引数にしてWebAPIを実行する(日本語も可能です)
    const msg = document.getElementById("input_message").value;
    xhr.send(msg);
    xhr.onreadystatechange = function() 
    {
        if(xhr.readyState === 4 && xhr.status === 200)
        {
            document.getElementById( "result" ).innerHTML = xhr.responseText;
        };
    }
}
</script>

XMLHttpRequestオブジェクトの
sendメソッドでデータをpostして
結果があれば
responseTextプロパティで取得します

サーバー側のphpファイル

test.php
<?php
    echo date("Y/m/d H:i:s") . "</br>";
    echo "送られた文字列は" . "</br>";
    echo file_get_contents("php://input") . "</br>";
    echo "です" . "</br>";
?>

file_get_contents("php://input")でpostされたメタデータが取得できるようです。

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

JavaScriptからPHPのサーバに文字列を引数にしてWebAPIを実行する例

クライアント側のhtmlファイル

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<style></style>
</head>
<body>
<input type="text" id="input_message">
<button onclick="PostString()">WebAPI実行</button>
<div id="result">ここにWebAPIの結果が入ります</div>
</body>
</html>

<script>
function PostString()
{
    const xhr = new XMLHttpRequest();

    //http://XXXXXXX.jp/test.php が今回呼び出すWebAPIを記述したphpファイル
    xhr.open('POST', 'http://XXXXXXX.jp/test.php');

    //文字列を引数にしてWebAPIを実行する(日本語も可能です)
    const msg = document.getElementById("input_message").value;
    xhr.send(msg);
    xhr.onreadystatechange = function() 
    {
        if(xhr.readyState === 4 && xhr.status === 200)
        {
            document.getElementById( "result" ).innerHTML = xhr.responseText;
        };
    }
}
</script>

XMLHttpRequestオブジェクトの
sendメソッドでデータをpostして
結果があれば
responseTextプロパティで取得します

サーバー側のphpファイル

test.php
<?php
    echo date("Y/m/d H:i:s") . "</br>";
    echo "送られた文字列は" . "</br>";
    echo file_get_contents("php://input") . "</br>";
    echo "です" . "</br>";
?>

file_get_contents("php://input")でpostされたメタデータが取得できるようです。

注意事項

htmlファイルをWEB上にホスティングせず、PCのローカルディスク上でブラウザで開いて実行しても、うまく動かないようです。

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

【PHP】Ajax

blade.php
<!-- ajax -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script>
    $('#answer-btn').on('click', function () {
      $question_id = {{ $question->id }};
      $answer_choice = {{ $question->answer_choice }};
      $answered_choice = Number($('input[name="answer"]:checked').val());
      console.log($answered_choice);
      console.log($answer_choice);
      console.log($question_id);
       $.ajax({
        type: "POST",
        url: "/question/choice",
        headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
        data: { 'answered_choice': $answered_choice, 'question_id': $question_id },
      });
    })
</script>
<!-- ajax -->
QuestionController.php
  /**
   * Remove the specified resource from storage.
   *
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function choice(Request $request)
  {
      $answered_choice = $request->answered_choice;
      $question_id = $request->question_id;
      $question = Question::find($question_id);
      if($answered_choice == $question->answer_choice){
        $question->update(["status_num" => 2]);
      } else {
        $question->update(["status_num" => 3]);
      }
  }
web.php
use App\Http\Controllers\QuestionController;
Route::resource('/question',  QuestionController::class)->middleware('auth');
Route::post('/question/choice',  [QuestionController::class, 'choice'])->middleware('auth');
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】component

resources/js/app.js
/**
 * First we will load all of this project's JavaScript dependencies which
 * includes React and other helpers. It's a great starting point while
 * building robust, powerful web applications using React + Laravel.
 */

require('./bootstrap');

/**
 * Next, we will create a fresh React component instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */

require('./components/Example');
require('./components/Answer'); //追記

resources/js/componentsにanswer.jsを作成する。

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

素人がPHPのアップデートで失敗した話

PHPのアップデートで失敗した話

Qitaの投稿練習記事です。
ずいぶん前にサポートが切れているPHPを7.1(期限切れ)→7.4にアップデートしようと、以前から調べていたのですが、ちょっと手こずったのでメモがわりに。

環境

  • CentOS7
  • PHP 7.1

事前にやったこと

  • ユーザーさんへのメンテナンス予告
  • 寝る前にスマホでggr
  • 本番に備えての昼寝(平日は他業務なので)

アップデート当日

  • S3にバックアップ
  • remiのリポジトリに古いのがあったので、mvでリネームして無効にする
  • 古いini をバックアップ

参考にしたサイト

  • 自分のポカミスなのを参考サイトが悪いようにとられるとまずいので、割愛
  • php centos などでググった内容を参考にしました

やっちまったこと

  • php* で削除したので、phpMyAdminが動かなくなる

対処した内容

  • いろいろググるもわけ分からず
  • ライブラリを追加する
  • サイト自体は問題無く動作しているのを確認して、落ち着くために寝る(ふて寝)
  • 朝になって、いくつかライブラリ入れたら治りました

入れたライブラリ

このをインストールしてたらどれかがうまく作用して動きました
$ sudo yum install --enablerepo=remi-php74 php-fpm
$ sudo yum install --enablerepo=remi-php74 php-mbstring
$ sudo yum install --enablerepo=remi-php74 php-mysqlnd
$ sudo yum install --enablerepo=remi-php74 php-pecl-zip
$ sudo yum install --enablerepo=remi-php74 php-xml

反省点

次回からは、どのライブラリがどこに作用しているのかよく調べてからにします。

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

【PHP】無名関数にuse()を使用する時の注意点

無名関数 (クロージャ)とは

関数名を指定せずに関数を作成できるようにするもの
公式

読んで字の如く、関数名をつけずに関数を定義できます。

無名関数

pattern1
$func = function() {
    echo 'Hello!';
}; // ←『;』をつけ忘れないように注意!

$func();
// Hello!

即時関数

patter2
(function() {
    echo 'Hello!';
})();
// Hello!

こちらも広義の意味で、無名関数です。PHPが()を認識したタイミングで関数が実行される仕組みとなっています

では、こちらは??

// 世界1
$word = 'Hello!!';

$func = function() {
    // 世界2
    echo $word;
};

$func();
//PHP Notice:  Undefined variable: ・・・

こちらはエラーになります。一見、動いても良さそうに見えますね。
これは「世界1」と「世界2」では、参照できる変数が異なるのでエラーが出ます。

「世界1」から「世界2」に変数を渡すことできるのが、『use()

use()を使ってみよう!

// 世界1
$word = 'Hello!!';

$func = function() use($word) {
    // 世界2
    echo $word;
};

$func();
// 'Hello!!'

できた! use($word)することで、「世界2」でも「世界1」の変数$wordを参照するようになります。

【本題】 use()の注意点

$word = 'Hello!!';

$func = function() use($word) {
    echo $word;
};

$word = 'Good Morning!';

$func();
// Hello!

こちらは、「Hello!」と出力されます!
use()は定義された時の変数を参照することに注意してください!

これは回避する方法

$word = 'Hello!!';

$func = function() use(&$word) { // ←参照渡しにする
    echo $word;
};

$word = 'Good Morning!';
unset($word);

$func();
// Good Morning!'

$wordを参照渡しにすることで回避できます。ただ、再度$wordに値を代入されると挙動が変わってしまうので、unset()で変数の割当を解除するようにしましょう。

まとめ

無名関数を使うとスコープを小さくできるので、私はすごく好きです。

  • use()に変数を3個以上書く時
  • use()に参照渡しで変数を書く時

は使いたくないな〜って気持ちです。

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

Lravelを初めて導入した

Laravelを初めて使用して、導入に成功したのでアウトプットのために記事を投稿します。

まずは、PHPをインストールします。MacにはデフォルトでPHPが使用できるそうですが、Laravelをインストールする場合にはPHPもインストールします。

brew install php@7.4

今回は、Laravel6を使用します。
Laravel6はPHP7.2以降に対応しているため7.4をインストールします。

次にComposerをインストールします。
ComposerはPHPのパッケージを管理することができます。

brew install composer

その後、Laravelをインストール

composer global require "laravel/installer"

この後、laravelのコマンドを使用できるように設定します。(php artisan serve)など

その後、laravelのプロジェクトを起動してサーバーを立ち上げます。

composer create-project laravel/laravel プロジェクト名 --prefer-dist バージョン
php artisan serve

するとサーバーが立ち上がり、Laravelのトップページが表示されていれば成功です。

ちなみに「rails s]だとローカルホストのポート番号は3000でしたが、「php artisan serve」の場合は番号が8000になります。

以上、アウトプットのために投稿させていただきました。

初投稿でしたが、今後も少しずつ投稿していきたいと思いますので、宜しくお願いいたします。

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

PHP 配列が空かどうか判定する

目的

  • PHPで配列が空かどうか判定する方法をメモ的にまとめる

情報

方法

  • empty()関数を用いて配列が空かどうかを判定する。empty()関数は空の場合trueを返す。
  • 下記を実行すると配列$arrayは空のため「Empty data」の文字列が出力される。

    <?php
    
    $array = '';
    
    if (empty($array)) {
        echo 'Empty data';
    }
    

参考文献

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

PHP 変数が空かどうか判定する

目的

  • PHPで変数が空かどうか判定する方法をメモ的にまとめる

情報

方法

  • empty()関数を用いて変数が空かどうかを判定する。empty()関数は空の場合trueを返す。
  • 下記を実行すると変数$strは空のため「Empty data」の文字列が出力される。

    <?php
    
    $str = '';
    
    if (empty($str)) {
        echo 'Empty data';
    }
    

参考文献

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