20200812のPHPに関する記事は16件です。

PHPで動的変数(可変変数)を扱う

変数を動的に作成する(可変変数)

変数を動的に作成したら楽なのにな…と思うけど案外使っている方が少なかった?ので記録として。
例えばPHPの場合、変数の初期化宣言をしなくても代入を書いてしまえば使えてしまうわけですが、以下のように初期化宣言している場合です。

test.php
$apple = "";
$peach = "";
$grape = "";

上記のような例はよく見られると思います。
場合によってはもっと多くの変数を宣言しないといけない…なんて事もあるかもしれません。
これを動的に作成する方法は以下のようになります。

test_arr.php
$arr = array(
  "apple",
  "peach",
  "grape"
);

foreach ($arr as $value) {
  ${$value} = "";
}

${}の中にforeachでloopしたvalueを入れてあげることでtest.phpとやっていることは同じになります。
コード量増えたじゃん!って思うかもですが、稀にtest.phpのように初期化処理を行っているプログラムで10個も20個も初期化処理を頑張って書いているのを見たことがあります。
そんな時にこれを使えば4行くらいで書けてしまいます。
//各変数の初期化処理
などとコメントを入れておくと「ここで変数の初期化やってるんだな」くらいに見て貰えると思います。

動的変数(可変変数)応用編

先ほどまでは$arr配列の中身の変数をそのまま作っていました。
この変数を元に、更に別の変数を作ってみましょう。

test_arr2.php
$arr = array(
  "apple",
  "peach",
  "grape"
);

foreach ($arr as $value) {
  ${$value} = "";
  ${$value . "_flg"} = true;
}

ここでは.""でくくった文字列を連結することで配列の中身を元に

$apple = "";
$apple_flg = true;
$peach = "";
$peach_flg = true;
$grape = "";
$grape_flg = true;

このような変数宣言と同様の事が出来ます。
上記のような例では変数宣言を単純にしているだけですが、配列で使用することで世界が広がるかと思います。

上記は単純に変数を作っているだけですが、実はClassも同様に生成できたり実行できたりします。
ぜひ試してみてください。

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

ウクライナではPHPエンジニアの採用にいくらかかるのでしょうか?

現代のプログラミングの世界では、選択できるプログラミング言語がたくさんありますが、PHPはおそらく最も古い言語の1つであるにもかかわらず、今なお人気があります。 PHPは1994年にRasmus Lerdorfによって作成されました。当時は、Cと呼ばれる別の優れたプログラミング言語によって作成されたCGIバイナリのセットにすぎませんでした。しかし、長年にわたって人気を集め、より大きなものに成長してきました。

簡単に言えば、PHPはWeb開発で使用される言語の1つです。 PHPはプログラミング言語であり、主に以下の3つの分野で使用されています。

・サーバー側のスクリプト:これはPHPの主な目的です。サーバーによって処理され、クライアントがその結果を受け取ることはPHPの主な機能になっています。そして、クライアント側でアクションの論理を見ることはできません。
・コマンドラインスクリプト:PHPの優れたところは、サーバーやブラウザーなしで実行できることです。必要なのはPHPパーサーだけです。私たちはWindows向けのタスクスケジューラーをお勧めします。
・デスクトップアプリケーションの作成。デスクトップアプリケーションもPHPを使って開発できます。ただし、GUIを使用したアプリケーションを作成するのに最適な言語ではありません。それでも、優秀なPHP開発者は、本当に素晴らしいアプリケーションを作成できるのです。
PHPは非常に簡単に勉強できる言語として知られています。そのため、ほとんどの初心者がPHPを最初のプログラミング言語として選びます。ただし、経験豊富なプログラマーでさえ、容易でそれを使って幅広いことができますので、PHP言語をよく使用しているのです。

PHP 開発者の職務:概要

PHP Webサイト開発者は、クライアントには見えないエリアで仕事している人間です。これは、バックエンド開発とも呼ばれます。

現在PHP 開発者に何が求められているのかをもっと具体的に考えてみましょう。特定のスキルが必要であるのでPHP プログラマーの採用には注意すべきところもあります。専門PHP 開発者を採用する際、以下の能力の有無を確認する必要があります。
・高速、クリーン、高品質で拡張性のあるコードを記述すること
・詳しい仕様を作成すること
・コア製品ソフトウェアとデータベースをトラブルシューティング、テストやメンテナンスすること
・フロントエンドエンジニアによって開発したユーザー向け要素を総合すること
・効率的で再利用・テスト可能なPHPモジュールを構築すること
・複雑なパフォーマンス問題の解決策とアーキテクチャ上のチャレンジを提供すること
・キーバリューストア、データベース、ブロブストアなどのデータストレージ統合ソリューションを提供すること
上記のことを考慮すれば、専門PHP 開発者を採用することがはるかに簡単になります。

PHP開発アウトソーシング:ウクライナでのPHP デベロッパーの採用

PHPエンジニアを採用したいようでしたら、おそらくウクライナが一番優れた選択肢になっています。ウクライナにはITを教える大学が多くあるだけでなく、その卒業生の若者は優れた能力を示しています。Hacker Rankによると、ウクライナは世界で最高のコンピュータープログラマーのいるトップ11か国の1つだそうです。

PHP開発者のレート:概要

雇用主としてPHPプログラマーのコストを含めた採用プロセスについてすでに考えたことがあるかもしれません。PHP エンジニア、特に優秀な開発者のコストは、国によって異なります。 すでに説明しましたように、ウクライナのPHPアプリ開発会社からスペシャリストを採用するのが良いアイデアです。その採用により、PHP開発者のコストを削減することでお金をある程度節約し、実際にチームにかなり優れた専門家を採用することができます。

詳細はこちら:https://jp.mobilunity.com/blog/cost-of-php-developer-in-ukraine-jp/

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

laravel SQLSTATE[HY000] [2002] Connection refused

SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = laravel and table_name = migrations and table_type = 'BASE TABLE')エラー対処

メモ

.envの修正もしたのに解決しなかった場合、下記コマンド実行したら解消しました。

php artisan key:generate
php artisan cache:clear
php artisan route:clear
php artisan config:clear 
php artisan view:clear 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerでpostgresとpgweb(GUI)を構築した

DockerによるPHP、Apache、PostgreSQLの開発環境を構築した時の流れをまとめようと思います。

また、データベース管理インタフェースを使うと直感的に操作できて便利なので、PostgreSQLについてはモダンなUIであるpgwebも導入してみます。

環境

  • Mac for Docker
  • Apache2.4
  • PHP7.1
  • PostgreSQL9.6

構成

スクリーンショット 2020-08-11 12.15.42.png

ファイル群

docker/web/Dcokerfileに以下を記述します。

FROM php:7.1-apache

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

RUN set -ex apk --no-cache add postgresql-dev libpq-dev && \
    apt-get update && apt-get install -y libpq-dev \
    vim \
    less \
    && docker-php-ext-install pdo pdo_pgsql pgsql mbstring

docker/web/Dcokerfileと同じ階層にphp.iniを作成します。

docker/web/php.ini
[Core]
display_errors = On
error_reporting = E_ALL
error_log = /var/log/apache2/error.log
log_errors = On

[Date]
date.timezone = 'Asia/Tokyo'

[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = auto
mbstring.http_input = auto
mbstring.http_output = auto
mbsting.encoding_translation = Off
mbstring.detect_order = auto

dockerディレクトリにdocker-compose.ymlを作成します。

docker/docker-compose.yml
version: '3'

services:
  web:
    build: ./docker/web/
    ports:
      - 8110:80
    volumes:
      - .:/var/www/html
    depends_on:
      - db
  db:
    image: postgres:9.3
    container_name: postgres
    ports:
      - 5433:5432
    volumes:
      - ./docker/db:/docker-entrypoint-initdb.d
    environment:
      POSTGRES_DB: test
      POSTGRES_USER: test
  db-gui:
    image: sosedoff/pgweb
    container_name: "pgweb"
    ports:
      - "8081:8081"
    depends_on:
      - db

表示確認用ファイル作成

dockerディレクトリにindex.phpを作成します。
とりま、phpinfo()のみでOKです。

docker/index.php
<?php

phpinfo();

コンテナ立ち上げる

以下コマンドで実行します。

docker-compose up -d

コンテナ確認してみます。

$ docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
a25edb35c693        sosedoff/pgweb      "/usr/bin/pgweb --bi…"   10 seconds ago      Up 9 seconds        0.0.0.0:8081->8081/tcp   pgweb
e5f1ce8c159f        php_job_web         "docker-php-entrypoi…"   10 seconds ago      Up 9 seconds        0.0.0.0:8110->80/tcp     web
c2ae9b7b2ab6        postgres:9.3        "docker-entrypoint.s…"   11 seconds ago      Up 10 seconds       0.0.0.0:5433->5432/tcp   postgres

ブラウザ確認

localhost:8110にアクセスします。
以下のように表示されればOKです。
スクリーンショット 2020-08-12 14.17.32.png

pgwebの設定

localhost:8081にアクセスします。
以下のように入力すれば接続できるはずです。

スクリーンショット 2020-08-12 14.05.56.png

項目
Host データベースのコンテナ名
Username environmentのPOSTGRES_USER
Password 空欄でOK(セキュリティ的にアウトなので注意)
Database environmentのPOSTGRES_DB
SSL Mode disable

データベース管理ツールのpgwebからデータベースのアクセスするには、DBコンテナのIPが必要なのですが、docker-compose.yml に記載したデータベースコンテナ名でアクセス出来ます。

よって、Host名はデータベースのコンテナ名を指定しています。

pgwebでテーブルを作ってみる

スクリーンショット 2020-08-12 14.47.41.png

create table users (
  id integer, 
  name varchar(10)
);

をRunQueryしたらUsersテーブルの出来上がり。

まとめ

ご紹介したものは、あくまでローカルでの開発時を想定しており、本番利用には適さないです。

また、ローカルとはいえ、データベース認証をしっかり行うこと(ユーザー名・パスワードを分かりにくい文字列にするなど)を推奨します。

間違いがありましたらご指摘いただけますと幸いっす。

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

Dockerでpostgresとpgweb(GUI)を構築したっす

DockerによるPHP、Apache、PostgreSQLの開発環境を構築した時の流れをまとめようと思います。

また、データベース管理インタフェースを使うと直感的に操作できて便利なので、PostgreSQLについてはモダンなUIであるpgwebも導入してみます。

環境

  • Mac for Docker
  • Apache2.4
  • PHP7.1
  • PostgreSQL9.6

構成

スクリーンショット 2020-08-11 12.15.42.png

ファイル群

docker/web/Dcokerfileに以下を記述します。

FROM php:7.1-apache

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

RUN set -ex apk --no-cache add postgresql-dev libpq-dev && \
    apt-get update && apt-get install -y libpq-dev \
    vim \
    less \
    && docker-php-ext-install pdo pdo_pgsql pgsql mbstring

docker/web/Dcokerfileと同じ階層にphp.iniを作成します。

docker/web/php.ini
[Core]
display_errors = On
error_reporting = E_ALL
error_log = /var/log/apache2/error.log
log_errors = On

[Date]
date.timezone = 'Asia/Tokyo'

[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = auto
mbstring.http_input = auto
mbstring.http_output = auto
mbsting.encoding_translation = Off
mbstring.detect_order = auto

dockerディレクトリにdocker-compose.ymlを作成します。

docker/docker-compose.yml
version: '3'

services:
  web:
    build: ./docker/web/
    ports:
      - 8110:80
    volumes:
      - .:/var/www/html
    depends_on:
      - db
  db:
    image: postgres:9.3
    container_name: postgres
    ports:
      - 5433:5432
    volumes:
      - ./docker/db:/docker-entrypoint-initdb.d
    environment:
      POSTGRES_DB: test
      POSTGRES_USER: test
  db-gui:
    image: sosedoff/pgweb
    container_name: "pgweb"
    ports:
      - "8081:8081"
    depends_on:
      - db

表示確認用ファイル作成

dockerディレクトリにindex.phpを作成します。
とりま、phpinfo()のみでOKです。

docker/index.php
<?php

phpinfo();

コンテナ立ち上げる

以下コマンドで実行します。

docker-compose up -d

コンテナ確認してみます。

$ docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
a25edb35c693        sosedoff/pgweb      "/usr/bin/pgweb --bi…"   10 seconds ago      Up 9 seconds        0.0.0.0:8081->8081/tcp   pgweb
e5f1ce8c159f        php_job_web         "docker-php-entrypoi…"   10 seconds ago      Up 9 seconds        0.0.0.0:8110->80/tcp     web
c2ae9b7b2ab6        postgres:9.3        "docker-entrypoint.s…"   11 seconds ago      Up 10 seconds       0.0.0.0:5433->5432/tcp   postgres

ブラウザ確認

localhost:8110にアクセスします。
以下のように表示されればOKです。
スクリーンショット 2020-08-12 14.17.32.png

pgwebの設定

localhost:8081にアクセスします。
以下のように入力すれば接続できるはずです。

スクリーンショット 2020-08-12 14.05.56.png

項目
Host データベースのコンテナ名
Username environmentのPOSTGRES_USER
Password 空欄でOK(セキュリティ的にアウトなので注意)
Database environmentのPOSTGRES_DB
SSL Mode disable

データベース管理ツールのpgwebからデータベースのアクセスするには、DBコンテナのIPが必要なのですが、docker-compose.yml に記載したデータベースコンテナ名でアクセス出来ます。

よって、Host名はデータベースのコンテナ名を指定しています。

pgwebでテーブルを作ってみる

スクリーンショット 2020-08-12 14.47.41.png

create table users (
  id integer, 
  name varchar(10)
);

をRunQueryしたらUsersテーブルの出来上がり。

まとめ

ご紹介したものは、あくまでローカルでの開発時を想定しており、本番利用には適さないです。

また、ローカルとはいえ、データベース認証をしっかり行うこと(ユーザー名・パスワードを分かりにくい文字列にするなど)を推奨します。

間違いがありましたらご指摘いただけますと幸いっす。

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

[PHP] 簡易ログインアカウント登録機能を実装してみた

はじめに

前回の記事でログイン機能を実装しました。
https://qiita.com/N46_myHearter/items/ae4f776790c4c4666a66

この記事では、ログインする際に使用するアカウントをデータベースに登録する機能を実装してみたいと思います。

基本的な流れ
 1. 登録するユーザ情報(ID、パスワード、ユーザ名)を入力します。
 2. 入力値チェックを行う。
 3. ユーザ情報をDBに登録する。

簡易なので...笑笑

データベース

今回は、MySQLを使用しています。
データ項目は、IDパスワードユーザ名の3つのみで構成しています。
プライマリーキーにIDを指定しています。
パスワードは、ハッシュ化で暗号化。(調べた時にハッシュ化だと簡単に出来たから笑笑)

該当ソースコード

1. register.php

アカウントを登録するための入力画面です。
入力項目は、ID、名前、パスワード(確認のため2回入力)です。
入力項目すべて入力されているか、2回入力したパスワードが一致しているか、
パスワードの強度は大丈夫か(強度が弱いと警告)を確認して、アカウント登録確認画面に遷移します。

パスワード強度チェックは以下のHPにあるオープンソースであるpasswordchecker.jsを利用しています。
出典 https://www.websec-room.com/passswordchecker

アカウント登録画面(register.php)
<?php
  session_start();
  header("Content-type: text/html; charset=utf-8");
?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <link rel="stylesheet" type="text/css" href="style1.css"> 
  <meta charset="UTF-8">
  <script src="passwordchecker.js" type="text/javascript"></script>
  <script src="common.js" type="text/javascript"></script>
  <script type="text/javascript">

  /*
  * 登録前チェック  
  */
  function conrimMessage() {
    var id = document.getElementById("id").value;
    var name = document.getElementById("name").value;
    var pass = document.getElementById("password").value;
    var conf = document.getElementById("confirm_password").value;

    //必須チェック
    if((id == "") || (name == "") || (pass == "") || (conf == "")) {
      alert("必須項目が入力されていません。");
      return false;
    }

    //パスワードチェック
    if (pass != conf) {
      alert("パスワードが一致していません。");
      return false;
    }

    if (passwordLevel < 3) {
      return confirm("パスワード強度が弱いですがよいですか?");
    }

    return true;
    }

  </script>
</head>

<div class="form-wrapper">
  <h1>アカウント登録</h1>

  <?php
    if (isset($_SESSION["error_status"])) {
      if ($_SESSION["error_status"] == 1) {
        echo "<h2 style='color:red;'>入力内容に誤りがあります。</h2>";
      }
      if ($_SESSION["error_status"] == 2) {
        echo "<h2 style='color:red;'>IDは既に登録されています。</h2>";
      }
      if ($_SESSION["error_status"] == 3) {
        echo "<h2 style='color:red;'>タイムアウトか不正な URL です。</h2>";
      }
      if ($_SESSION["error_status"] == 4) {
        echo "<h2 style='color:red;'>登録に失敗しました。</h2>";
      }
      if ($_SESSION["error_status"] == 5) {
        echo "<h2 style='color:red;'>パスワードは既に登録されています。</h2>";
      }
    }
  ?>

  <form action="register_check.php" method="post" onsubmit="return conrimMessage();">
  <div class="form-item">
    <label for="ID"></label>
    <input type="text" name="id" id="id" required="required" placeholder="ID">
  </div>
  <div class="form-item">
    <label for="NAME"></label>
    <input type="text" name="name" id="name" required="required" placeholder="名前">
  </div>
  <div class="form-item">
    <label for="password"></label>
    <input type="password" name="password" required="required" placeholder="パスワード">
  </div>
  <div class="form-item">
    <label for="password"></label>
    <input type="password" name="confirm_password" id="confirm_password" required="required" placeholder="パスワード(確認)">
  </div>

  <div class="button-panel">
    <input type="submit" class="button" title="登録" value="登録">
  </div>
  </form>

  <div class="form-footer">
    <p><a href="/login.php">戻る</a></p>
  </div>
</div>
</html>

2. register_check.php

本当にアカウント登録していいのか再度確認する画面です。
また、入力したアカウント情報がDBに既に存在していないかをチェックします。
既に登録されていた場合はエラーを返します。

アカウント登録確認画面(register_check.php)
<?php
  require_once("function.php");
  session_start();
  header("Content-type: text/html; charset=utf-8");  

  $_SESSION['token']  = get_csrf_token();

  $id = $_POST['id'];
  $password = $_POST['password'];
  $name = $_POST['name'];
  $confirm_password = $_POST['confirm_password'];

  if ($password != $confirm_password) {
    //パスワード不一致 
    $_SESSION["error_status"] = 1;
    header("HTTP/1.1 301 Moved Permanently");
    header("Location: register.php");
    exit();
  }  

  //IDチェック

  //DB接続
  try {
    /*dbname: test
      host: localhost (DBをローカル環境に置いている)
      username: root
      password: '' (未設定)
    */
    $pdo = new PDO('mysql:dbname=test;host=localhost;charset=utf8mb4', 'root', '',
      [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
      ]
      );

    $stmt = $pdo->query('SELECT id, password FROM USER');

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
      $db_id = $row["id"];
      $db_password = $row["password"];

    //既にIDが登録されていた
    if ($db_id == $id) {
      $_SESSION["error_status"] = 2;
      header("HTTP/1.1 301 Moved Permanently");
      header("Location: register.php");
      exit();
    } 

    //エラー情報リセット
    $_SESSION["error_status"] = 0;
    }
    } catch (PDOException $e) {
      exit('データベース接続失敗。'.$e->getMessage());
    }

?>

<!DOCTYPE html>
<head>
  <link rel="stylesheet" type="text/css" href="style1.css">
  <meta charset="utf-8">
</head>

<html lang="ja">
<div class="form-wrapper">
  <h1>登録確認</h1>
  <h2>アカウント登録しますか?</h2>
  <form action="register_submit.php" method="post">
    <table border="0">

      <input type="hidden" name="id" value="<?php echo htmlspecialchars($id  , ENT_QUOTES, "UTF-8") ?>">
      <input type="hidden" name="name" value="<?php echo htmlspecialchars($name  , ENT_QUOTES, "UTF-8") ?>">
      <input type="hidden" name="password" value="<?php echo htmlspecialchars($password  , ENT_QUOTES, "UTF-8") ?>">
      <input type="hidden" name="token" value="<?php echo htmlspecialchars($_SESSION['token']  , ENT_QUOTES, "UTF-8") ?>">

      <div class="button-panel">
        <input type="submit" class="button" title="登録" value="登録">
      </div>
    </form>

    <div class="form-footer">
        <p><a href="/register.php">戻る</a></p>
    </div>
</div>
</html>

3. register_submit.php

実際にアカウント登録をして、登録完了を知らせる画面です。
DBに入力したユーザ情報を格納します。
その時、パスワードはハッシュ化で暗号化します。

アカウント登録完了画面(register_submit.php)
<?php
  require_once("function.php");
  session_start();
  header("Content-type: text/html; charset=utf-8");

  //CSRF チェック
  if ($_SESSION['token'] != $_POST['token']) {
      $_SESSION = array();
      session_destroy();
      session_start();

    $_SESSION["error_status"] = 2;
    header("HTTP/1.1 301 Moved Permanently");
    header("Location: login.php");
    exit();
  } 

  //エラー情報のリセット
  $_SESSION["error_status"] = 0;

  $id = $_POST['id'];
  $password = $_POST['password'];
  $name = $_POST['name'];

  // ハッシュを作る
  $hash = password_hash($password, PASSWORD_BCRYPT);

  //DB接続
  try {
    /*dbname: test
      host: localhost (DBをローカル環境に置いている)
      username: root
      password: '' (未設定)
    */
    $pdo = new PDO('mysql:dbname=test;host=localhost;charset=utf8mb4', 'root', '', 
    [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]
    );

    //パラメーターの型を指定
    $stmt = $pdo->prepare('INSERT INTO USER (ID, NAME, PASSWORD) VALUES (:id, :name, :password)'); 
    $stmt->bindParam(':id', $id, PDO::PARAM_STR);
    $stmt->bindParam(':name', $name, PDO::PARAM_STR);
    $stmt->bindParam(':password', $hash, PDO::PARAM_STR);

    $stmt->execute();
  } catch (PDOException $e) {
    exit('データベース接続失敗。'.$e->getMessage());
  }

?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <link rel="stylesheet" type="text/css" href="style1.css">
  <meta charset="utf-8">
</head>

<<div class="form-wrapper">
  <h1>アカウント登録完了</h1>
  アカウント登録が終了しました。<br>
  ログイン画面からログインしてください。<br><br>

    <div class="form-footer">
    <p><a href="/login.php">ログイン画面に戻る</a></p>
  </div>
</div>
</html>

4. function.php

以下の前回の記事に掲載済み。
https://qiita.com/N46_myHearter/items/ae4f776790c4c4666a66

環境

windows10 64bit
実行環境: xampp (mysql、php、apache等をまとめてインストールでき、インストールも簡単なので)

おわりに

抜けている箇所がありましたら、コメント欄で教えていただくとありがたいです。

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

Laravel で Docker 使って開発したいなら Vessel にしておこう

Vessel そこそこ使ってる人はいるんだろうけど、 Laradock 使ってツラいことになってる人がそこそこいそうなので Vessel 使うと楽だよということをに書いておきます。

Vessel とは

Vessel は簡単に下記環境を Docker で作成することができます。

  • PHP7.4
  • MySQL 5.7
  • Redis
  • NodeJS, NPM, Yarn, Gulp

ちょっと自分の環境にあわない(例えばデータベースに PostgreSQL を使っている等)場合は書き換えることができます(各種ファイルがコピーされるだけなので)。おおむね、PHP, データベース, キャッシュストレージ, NodeJS があれば 8〜9 割くらいの現場ではフィットするんじゃないでしょうか。

使用にあたっての注意点(追記)

Vessel は https://github.com/shipping-docker/vessel/blob/master/docker-files/docker/node/Dockerfile#L1node:latest を使っててこのままだとイメージサイズが大きいので変更したほうがよいです。

インストール

Composerを使ってインストールできます。

composer require shipping-docker/vessel

これはかなり嬉しいですね。 git submodule add とかできれば書きたくない。

次に設定ファイルを publish します。

php artisan vendor:publish --provider="Vessel\VesselServiceProvider"

すると docker ディレクトリに Docker の各種ファイル、プロジェクトルートに docker-compose.ymlvessel というシェルスクリプトがコピーされます。

で最後に

bash vessel init

とすれば準備完了。簡単ですね。

使い方

コンテナを起動するには

./vessel start

とすればコンテナが起動します。停止するには

./vessel stop

で停止します。

この vessel というシェルスクリプトが上手くできていて、Docker のコマンド(自分はすぐ忘れる)を補ってくれます。例えばコンテナ内で php artisan xxx したい時は

./vessel artisan xxx (tinker とか make:controller とか)

でOKです。上記コマンドは

docker-compose exec -u ユーザー名 コンテナ名 php artisan コマンド

と同じですが、かなり短くなって覚えやすくなってるのがわかると思います。他にも

./vessel test

で PHPUnit でテストができたり

./vessel node or npm or yarn

で各種コマンドが実行できたり

./vessel dump

mysqldump が実行できたり

./vessel mysql

で MySQL コマンドが実行できたり

./vessel ssh コンテナ名

でコンテナに入ったりできます。

あとは…そうですね。私はホストOSがUbuntuなので dockerでvolumeをマウントしたときのファイルのowner問題 が発生して困ることが多いのですがこの辺にも対処してくれています。

まとめ

Docker を開発環境と割り切って使うのであれば Vessel は非常におすすめです。そうでなくても vessel ファイルをちょっとカスタマイズして活用するのもいいのではと思います。私は理由があって Vessel が使えない現場でも vessel ファイルっぽいものを作って導入しています。

プロジェクトメンバー全員が Docker に習熟していれば必要ないかもしれませんが、私も Docker が得意なわけじゃないのでこういったパッケージがあるのは嬉しいですね。

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

お名前.comにて、拡張子htmlのままphpを動かす(レンタルサーバー RSプラン)

初投稿です。

今まで自分が利用したことのあるレンタルサーバーとは異なったため、サポセンに問い合わせたら

お問い合わせの件につきまして、「.html」ファイルを別の拡張子で
動作させる場合は.htaccessにて AddHandler など、「.html」ファイル
をcgiとして実行いただく記述でご利用いただけます。

なお、独自にご準備された.htaccessの設置についてはサポートを
控えさせていただいております。

具体的な記述や設定方法につきましては、市販の書籍や参考書など
にてご確認くださいますようお願い申しあげます。

とのことでしたのでインターネットで調べたところ、Qiitaに有益な情報を見つけました。

参照元:お名前.comにて、拡張子htmlのままphpを動かす

こちらはお名前.comでも共用サーバー SDプランのことなのか、レンタルサーバー RSプランだとこのままでは動作せず、どなたかが同じように悩んで時間を浪費しないようメモします。

対処法

基本的に参照元のままです。最低限のみ記載します。

①まず、「.htaccess」に以下を記入(追記)します。※同じです

Action myphp-cgi /php.cgi
#AddHandler myphp-cgi .html
<Files ~ "^index\.html?$">
  AddHandler myphp-cgi .html .htm
</Files>

パーミッションは644でも問題ありませんでした。

②次に、「php.cgi」というファイルを用意し、以下のように記入します。

php.cgi
#! /usr/bin/bash
exec /usr/bin/php-cgi

php-cgiまでのパスが異なります。
参考:【レンタルサーバー RSプラン】各種パス情報を教えてください
パーミッションは700にしました。

いずれのファイルも
文字コード:UTF-8
改行コード:LF
で動作しました。

ディレクトリを変える場合などは参照元などを参考にしてください。
もし引用方法などに間違いなどありましたらご指導いただけたらと思います。

ありがとうございました。

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

オープンソースとプライバシー志向の分析ソリューション

data-privacy-meme.png

はじめに

こんにちは streampack チームのメディです。
https://cloudpack.jp/service/option/streampack.html

Objective ・ 目的

Privacy is an important matter.
I would like to present several open source solutions that respect users privacy and will allow you to improve your business.

プライバシーは重要な問題です。
ユーザーのプライバシーを尊重し、ビジネスの改善を可能にするいくつかのオープンソースソリューションを紹介したいと思います。

Disclaimer ・ 免責事項

Analytics systems are listed in no particular order.
分析システムは特定の順序でリストされていません。

Offen

Screen Shot 2020-07-16 at 10.49.56.png

From the homepage ・ ホームページから

Offen is a fair and open alternative to common web analytics tools. Gain insights while your users have full access to their data. Lightweight, self hosted and free.

Offenは、一般的なWeb分析ツールの公正でオープンな代替手段です。 ユーザーがデータに完全にアクセスしながら、洞察を得ます。 また、軽量、自己ホスト型で、無料です。

Key points

  • Privacy friendly
  • Transparent and fair
  • lightweight

主な機能

  • プライバシーフレンドリー
  • 透明かつ公正
  • 軽量

https://github.com/offen/offen

PostHog

dashboards-0309f28b408dfd06dcb58fe11fefd185.png

From the homepage ・ ホームページから

Understand your users.
Build a better product.

ユーザーを理解します。
より良い製品を作ります。

Key points

  • privacy-focused
  • detailed product analytics

主な機能

  • プライバシー志向
  • 詳細な製品分析

https://github.com/posthog/posthog

Matomo (formely Piwik)

website-graphics-2020-v5-1.png

From the homepage ・ ホームページから

Google Analytics alternative that protects your data and your customers' privacy.

データと顧客のプライバシーを保護するGoogleアナリティクスの代替手段。

Key points

  • Real time analysis
  • Customizable

主な機能

  • リアルタイム分析
  • カスタマイズ可能

https://github.com/matomo-org/matomo

Fathom

fathom.jpg

From the homepage ・ ホームページから

Fathom Analytics is a simpler and more privacy-focused alternative to Google Analytics.

Fathom Analyticsは、Google Analyticsに代わる、よりシンプルでプライバシー重視の代替手段です。

Key points:

  • Simple website analysis
  • Do not use cookies

主な機能

  • シンプルなウェブサイト分析
  • クッキーを使用しない

https://github.com/usefathom/fathom

Information sources ・ 情報元

https://github.com/offen/offen
https://github.com/usefathom/fathom
https://github.com/posthog/posthog
https://github.com/matomo-org/matomo

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

PHP ひとこと掲示板

<?php

$filename = './bbs.txt';
$date  = date('Y-m-d H:i:s');
$data  = [];
$error = [];
$username = '';
$comment   = '';

if($_SERVER['REQUEST_METHOD'] === 'POST'){

    if (isset($_POST['username']) === true) {
        $username = trim($_POST['username']);
    }
    if (isset($_POST['comment']) === true) {
        $comment = trim($_POST['comment']);
    }

    if ($username === '') {
        $error[] = '名前を入力してください';
    } else if (mb_strlen($username) > 20 ) {
        $error[] = '名前は20文字以内で発言してください';
    }
    if ($comment === '') {
        $error[] = 'ひとことを入力してください';
    } else if (mb_strlen($comment) > 100) {
        $error[] = 'ひとことは100文字までで発言してください';
    }

    if (count($error) === 0) {
        $log = $username . ":\t" . $comment . "\t-" . $date . "\n";
        if (($fp = fopen($filename, 'a')) !== FALSE) {       
            if (fwrite($fp, $log) === FALSE) {              
                $error[] =  'ファイル書き込み失敗:  ' . $filename;
            }
            fclose($fp);
        }
    }
}


if(is_readable($filename) === true){
    if(($fp = fopen($filename,'r')) !== false){
        while(($tmp = fgets($fp)) !== false){
            $data[] = htmlspecialchars($tmp,ENT_QUOTES,'UTF-8');
        }
    }
} else {
    $error[] = 'ファイルがありません';
}

$data = array_reverse($data);

?>
<!doctype html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>ひとこと掲示板</title>
    </head>
    <body>
        <h1>ひとこと掲示板</h1>
<?php if (count($error) > 0) { ?>
    <ul>
    <?php foreach($error as $value) { ?>
        <li><?php print $value; ?></li>
    <?php } ?>
    </ul>
<?php } ?>
        <form method="post">
            名前:<input type="text" name="username">
            ひとこと:<input type="text" name="comment">
            <input type="submit" value="送信">
        </form>
        <ul>
<?php foreach ($data as $value) { ?>
            <li><?php print $value; ?></li>
<?php } ?>
        </ul>
    </body>
</html>

countを便利に使う。

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

[PHP]Twitter APIの利用まとめ

今回の題

Twitter APIの審査がようやく通ったので記事にします。
申請は英語で行うのですが、グーグル翻訳の精度が上がっていてめちゃくちゃ助かりました。
アカウントの申請に関しては今回は省きますが、人によっては数ヶ月待つというなかなか根気のいる審査なので、今は使う予定がない人もとりあえず申請だけしておくと後々役立つかと思います。(私は一週間待ちました)

申請はこちらから

ライブラリの準備

・abraham/twitteroauthのインストール
abraham/twitteroauthはstar数4000近い人気のライブラリです。
少ないコード、シンプルな記述で簡単にTwitter APIを操作できます。

$ composer require abraham/twitteroauth

利用準備

申請後の開発者用のページのComusumer KeyAccess Tokenが乗っているのでコピーしておいてください。
コードはREADMEに記載されていたこちらのページに従って書いていきます。
適宜、目を通しておくと吉です。

インスタンスの作成

<?php
require('vendor/autoload.php');

use Abraham\TwitterOAuth\TwitterOAuth;

$consumer_key = 'XXXXXXXXX';
$consumer_key_sercret = 'XXXXXXXXX';
$access_token = 'XXXXXXXXX';
$access_token_secret = 'XXXXXXXXX';

$connection = new TwitterOAuth($consumer_key, $consumer_key_sercret, $access_token, $access_token_secret);

composerのオートロードでvendor配下のライブラリをロードし、useを使ってエイリアスを作成。TwitterOAuthオブジェクトのインスタンスを変数$connectionに作成します。
インスタンス作成時の引数は各自の開発者ページに記載のものを利用してください。

コード

abraham/twitteroauthのメソッドには基本的に、
第一引数にエンドポイントのパス
第二引数にパラメーター
を渡します。
エンドポイントとパラメーターは以下で確認できます。
Twitter Developer
日本語でまとめてくれているサイトがありました。
Twitter REST APIの使い方

いくつか試してみます。


1.ツイートを検索する

ツイートの検索をするためのエンドポイントは
https://api.twitter.com/1.1/search/tweets.json
であることを、Twitter Developer /Search Tweetsで確認しておきます。

$tweets = $connection->get("search/tweets", ['q' => '駆け出しエンジニア']);

パラメーターは連想配列で渡します。
これで、駆け出しエンジニアというワードが含まれたツイートを取得できました。


2.ツイートする

$connection->post("statuses/update", ["status" => "テスト"];

メソッドをpostにするとpostリクエストが出来ます。
アカウントの設定をRead and Writeに設定しておく必要があります。


3.いいねする

いいねをする為には、対象のツイートのidが必要になります。
なので、「1.ツイートを検索する」で書いたような手段でツイートを検索し、そのレスポンスの中に含まれてるツイートのidを取得し指定してください。

$connection->post("favorites/create", ["id" => "1292797790070779905"];


4.トレンドを検索する

まず、エンドポイントtrends/availableで日本のidを取得します。

$connection->get("trends/available");

日本のidは2345896でした。
それを今度は、trends/placeのパラメータとして渡します。

$connection->get("trends/place", ['id' => '2345896']);

これで今現在の日本のTwitter上でのトレンドが取得できます。


5.APIの制限数を確認する

$connection->get("application/rate_limit_status");

APIのリクエストには一定時間内での回数制限があります。
それを取得するためのリクエストです。リクエストの残数などを確認することができます。
パラメーターを指定すればエンドポイントごとに確認することも可能です。

制限回数は以下で確認することができます。
Twitter Developer Rate limits

以上!!

最後に

ここまで読んでいただきありがとうございます。
いつか誰かの参考になれば幸いです。
他にもAPI関連の記事を書いていますので、よければ?‍♀️
[PHP] Zoom APIを利用してミーティングを作成する
[PHP] YouTube APIの利用(動画情報の取得)
[PHP] Messaging APIを使ったLINEbotで色々試してみる

参考

Twitter Developer
TwitterOAuth

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

[PHP]Twitter APIを試してみた

今回の題

Twitter APIの審査がようやく通ったので記事にします。
申請は英語で行うのですが、グーグル翻訳の精度が上がっていてめちゃくちゃ助かりました。
アカウントの申請に関しては今回は省きますが、人によっては数ヶ月待つというなかなか根気のいる審査なので、今は使う予定がない人もとりあえず申請だけしておくと後々役立つかと思います。(私は一週間待ちました)

申請はこちらから

ライブラリの準備

・abraham/twitteroauthのインストール
abraham/twitteroauthはstar数4000近い人気のライブラリです。
少ないコード、シンプルな記述で簡単にTwitter APIを操作できます。

$ composer require abraham/twitteroauth

利用準備

申請後の開発者用のページのComusumer KeyAccess Tokenが乗っているのでコピーしておいてください。
コードはREADMEに記載されていたこちらのページに従って書いていきます。
適宜、目を通しておくと吉です。

インスタンスの作成

<?php
require('vendor/autoload.php');

use Abraham\TwitterOAuth\TwitterOAuth;

$consumer_key = 'XXXXXXXXX';
$consumer_key_sercret = 'XXXXXXXXX';
$access_token = 'XXXXXXXXX';
$access_token_secret = 'XXXXXXXXX';

$connection = new TwitterOAuth($consumer_key, $consumer_key_sercret, $access_token, $access_token_secret);

composerのオートロードでvendor配下のライブラリをロードし、useを使ってエイリアスを作成。TwitterOAuthオブジェクトのインスタンスを変数$connectionに作成します。
インスタンス作成時の引数は各自の開発者ページに記載のものを利用してください。

コード

abraham/twitteroauthのメソッドには基本的に、
第一引数にエンドポイントのパス
第二引数にパラメーター
を渡します。
エンドポイントとパラメーターは以下で確認できます。
Twitter Developer
日本語でまとめてくれているサイトがありました。
Twitter REST APIの使い方

いくつか試してみます。


1.ツイートを検索する

ツイートの検索をするためのエンドポイントは
https://api.twitter.com/1.1/search/tweets.json
であることを、Twitter Developer /Search Tweetsで確認しておきます。

$tweets = $connection->get("search/tweets", ['q' => '駆け出しエンジニア']);

パラメーターは連想配列で渡します。
これで、駆け出しエンジニアというワードが含まれたツイートを取得できました。


2.ツイートする

$connection->post("statuses/update", ["status" => "テスト"];

メソッドをpostにするとpostリクエストが出来ます。
アカウントの設定をRead and Writeに設定しておく必要があります。


3.いいねする

いいねをする為には、対象のツイートのidが必要になります。
なので、「1.ツイートを検索する」で書いたような手段でツイートを検索し、そのレスポンスの中に含まれてるツイートのidを取得し指定してください。

$connection->post("favorites/create", ["id" => "1292797790070779905"];


4.トレンドを検索する

まず、エンドポイントtrends/availableで日本のidを取得します。

$connection->get("trends/available");

日本のidは2345896でした。
それを今度は、trends/placeのパラメータとして渡します。

$connection->get("trends/place", ['id' => '2345896']);

これで今現在の日本のTwitter上でのトレンドが取得できます。


5.APIの制限数を確認する

$connection->get("application/rate_limit_status");

APIのリクエストには一定時間内での回数制限があります。
それを取得するためのリクエストです。リクエストの残数などを確認することができます。
パラメーターを指定すればエンドポイントごとに確認することも可能です。

制限回数は以下で確認することができます。
Twitter Developer Rate limits

以上!!

最後に

ここまで読んでいただきありがとうございます。
いつか誰かの参考になれば幸いです。
他にもAPI関連の記事を書いていますので、よければ?‍♀️
[PHP] Zoom APIを利用してミーティングを作成する
[PHP] YouTube APIの利用(動画情報の取得)
[PHP] Messaging APIを使ったLINEbotで色々試してみる

参考

Twitter Developer
TwitterOAuth

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

[PHP]Twitter APIを試してまとめた

今回の題

Twitter APIの審査がようやく通ったので記事にします。
申請は英語で行うのですが、グーグル翻訳の精度が上がっていてめちゃくちゃ助かりました。
アカウントの申請に関しては今回は省きますが、人によっては数ヶ月待つというなかなか根気のいる審査なので、今は使う予定がない人もとりあえず申請だけしておくと後々役立つかと思います。(私は一週間待ちました)

申請はこちらから

ライブラリの準備

・abraham/twitteroauthのインストール
abraham/twitteroauthはstar数4000近い人気のライブラリです。
少ないコード、シンプルな記述で簡単にTwitter APIを操作できます。

$ composer require abraham/twitteroauth

利用準備

申請後の開発者用のページのComusumer KeyAccess Tokenが乗っているのでコピーしておいてください。
コードはREADMEに記載されていたこちらのページに従って書いていきます。
適宜、目を通しておくと吉です。

インスタンスの作成

<?php
require('vendor/autoload.php');

use Abraham\TwitterOAuth\TwitterOAuth;

$consumer_key = 'XXXXXXXXX';
$consumer_key_sercret = 'XXXXXXXXX';
$access_token = 'XXXXXXXXX';
$access_token_secret = 'XXXXXXXXX';

$connection = new TwitterOAuth($consumer_key, $consumer_key_sercret, $access_token, $access_token_secret);

composerのオートロードでvendor配下のライブラリをロードし、useを使ってエイリアスを作成。TwitterOAuthオブジェクトのインスタンスを変数$connectionに作成します。
インスタンス作成時の引数は各自の開発者ページに記載のものを利用してください。

コード

abraham/twitteroauthのメソッドには基本的に、
第一引数にエンドポイントのパス
第二引数にパラメーター
を渡します。
エンドポイントとパラメーターは以下で確認できます。
Twitter Developer
日本語でまとめてくれているサイトがありました。
Twitter REST APIの使い方

いくつか試してみます。


1.ツイートを検索する

ツイートの検索をするためのエンドポイントは
https://api.twitter.com/1.1/search/tweets.json
であることを、Twitter Developer /Search Tweetsで確認しておきます。

$tweets = $connection->get("search/tweets", ['q' => '駆け出しエンジニア']);

パラメーターは連想配列で渡します。
これで、駆け出しエンジニアというワードが含まれたツイートを取得できました。


2.ツイートする

$connection->post("statuses/update", ["status" => "テスト"];

メソッドをpostにするとpostリクエストが出来ます。
アカウントの設定をRead and Writeに設定しておく必要があります。


3.いいねする

いいねをする為には、対象のツイートのidが必要になります。
なので、「1.ツイートを検索する」で書いたような手段でツイートを検索し、そのレスポンスの中に含まれてるツイートのidを取得し指定してください。

$connection->post("favorites/create", ["id" => "1292797790070779905"];


4.トレンドを検索する

まず、エンドポイントtrends/availableで日本のidを取得します。

$connection->get("trends/available");

日本のidは2345896でした。
それを今度は、trends/placeのパラメータとして渡します。

$connection->get("trends/place", ['id' => '2345896']);

これで今現在の日本のTwitter上でのトレンドが取得できます。


5.APIの制限数を確認する

$connection->get("application/rate_limit_status");

APIのリクエストには一定時間内での回数制限があります。
それを取得するためのリクエストです。リクエストの残数などを確認することができます。
パラメーターを指定すればエンドポイントごとに確認することも可能です。

制限回数は以下で確認することができます。
Twitter Developer Rate limits

以上!!

最後に

ここまで読んでいただきありがとうございます。
いつか誰かの参考になれば幸いです。
他にもAPI関連の記事を書いていますので、よければ?‍♀️
[PHP] Zoom APIを利用してミーティングを作成する
[PHP] YouTube APIの利用(動画情報の取得)
[PHP] Messaging APIを使ったLINEbotで色々試してみる

参考

Twitter Developer
TwitterOAuth

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

MW WP Formのお問い合わせデータを日付指定でフィルタする

普段あまりWordPress触らないのですが、急遽サポートで対応した内容になります。
調べても案外情報がなかったので、あまりそういう要件がないのかな。
※急ぎでの対応でしたのでもっと最善策があるかもしれません。

環境

WordPress 5.2
PHP 7.0.32
Apache バージョン不明

MW WP Formとは

MW WP Form

WordPressのフォームプラグイン。
簡単にフォームを構築できて、入力内容を保存、閲覧も可能な便利なプラグイン。

問題点

MW WP Formの管理画面では、フォームの入力内容を一覧で見ることができるが、その際にフィルタリングが「月指定」でしかできない。
そのため、これに「日付指定」を追加したい。
また、画面上のフィルタリングがCSVダウンロードに反映されない。

まとめると2点。

  • 「月指定」のフィルタリングしかできない
  • フィルタリングがCSVダウンロードに適用されない

上記2点を改善します。

改修内容

  • 「日付指定」でフィルタリング機能の追加
  • 「日付指定」のフィルタリングをCSVダウンロードにも適用

※今回の場合、急ぎ案件であったこともあり、日付は手入力。ただし、datepicker使用。
※本来は入力内容から入力があった日付をすべて抽出してドロップダウン化した方がよいのかもしれないが、日付が増えた時のことを考慮して無しとした。

修正内容

完成形

最終的にできたのが以下。

20200812_mw_wp_form_1.png

登録日時にフォーカスを当てると以下のようにdatepickerが起動する。
20200812_mw_wp_form_2.png

この状態で「絞り込み検索」を実行すると日付指定での検索が可能。
かつCSVダウンロードも同様に日付指定でのダウンロードが可能になる。

修正内容全体

functions.php
function add_date_input($vars) {
    $vars[] = 'date';
    return $vars;
}
add_filter('query_vars', 'add_date_input');

function add_date_filter() {
    // 登録日の絞り込み検索
    // MW WP Form以外では実行しないようにする
    if (strpos($GLOBALS['post_type'], 'mwf_') !== false) {
        wp_enqueue_script('jquery-ui-core');
        wp_enqueue_script('jquery-ui-datepicker');

        global $wp_scripts;
        $ui = $wp_scripts->query('jquery-ui-core');
        wp_enqueue_style('jquery-ui-css', "//ajax.googleapis.com/ajax/libs/jqueryui/{$ui->ver}/themes/smoothness/jquery-ui.css");

        echo '<input type="text" name="date" class="datepicker" value="' . get_query_var('date') . '" size="10" maxlength="10" placeholder="登録日時">';
        echo '<script type="text/javascript">';
        echo 'jQuery(function($) { $("input[name=\'date\']").datepicker({ dateFormat: \'yymmdd\', changeYear: true, monthNames: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"] }); });';
        echo '</script>';
    }
};
add_action('restrict_manage_posts', 'add_date_filter');

// 問い合わせ一覧画面の絞り込み時に条件を追加する
// CSVダウンロードでも使用される
function my_mwform_get_inquiry_data_args($args) {
    $strDate = get_query_var('date'); // date(日付指定)
    $strM = get_query_var('m');  // m(月指定)
    if (empty($strDate)) {
        if (isset($_GET['date'])) {
            $strDate = $_GET['date'];
        }
    }

    if (empty($strM)) {
        if (isset($_GET['m'])) {
            $strM = $_GET['m'];
        }
    }

    $strSearchDate = '';
    $bIsDayExist = false;
    if (!empty($strDate)) {
        // dateパラメータがある場合はdateを優先
        $strSearchDate = $strDate;
        $bIsDayExist = true;
    } elseif (!empty($strM)) {
        // dateがなくてmがある場合はmを使用
        $strSearchDate = $strM . '01';
    }

    if (!empty($strSearchDate)) {
        // date or mのどちらかが指定されている場合のみ条件を追加
        $objDate = new DateTime($strSearchDate);
        $arrSearchCondition = array(
            'year' => $objDate->format('Y'),
            'month' => $objDate->format('m'),
        );
        if ($bIsDayExist) {
            $arrSearchCondition['day'] = $objDate->format('d');
        }

        $args = array_merge($args, array(
            'date_query' => array(
                $arrSearchCondition
             ),
        ));
    }

    return $args;
}
add_filter('mwform_get_inquiry_data_args-mwf_xxx', 'my_mwform_get_inquiry_data_args');

// デフォルトの月指定の絞り込み条件を非表示にする
function custom_load_edit() {
    add_filter( 'disable_months_dropdown' , 'custom_disable_months_dropdown' , 10 , 2 );
    function custom_disable_months_dropdown( $false , $post_type ) {
        $disable_months_dropdown = $false;
        if (strpos($post_type, 'mwf_') !== false) {
            $disable_months_dropdown = true;
        }
        return $disable_months_dropdown;
    }
}
add_action( 'load-edit.php' , 'custom_load_edit' );

細かく

大きく分けて3つ。

URLクエリ変数の追加

functions.php
function add_date_input($vars) {
    $vars[] = 'date';
    return $vars;
}
add_filter('query_vars', 'add_date_input');

テキストボックスの追加

jquery-uiのdatepickerを使用しています。
前半はjquery-uiのロード。
datepickerを使用しなければinput文のみでOK。

inputのplaceholderは「登録日時」となっていますが、適切な文言に変更してください。

functions.php
function add_date_filter() {
    // 登録日の絞り込み検索
    // MW WP Form以外では実行しないようにする
    if (strpos($GLOBALS['post_type'], 'mwf_') !== false) {
        wp_enqueue_script('jquery-ui-core');
        wp_enqueue_script('jquery-ui-datepicker');

        global $wp_scripts;
        $ui = $wp_scripts->query('jquery-ui-core');
        wp_enqueue_style('jquery-ui-css', "//ajax.googleapis.com/ajax/libs/jqueryui/{$ui->ver}/themes/smoothness/jquery-ui.css");

        echo '<input type="text" name="date" class="datepicker" value="' . get_query_var('date') . '" size="10" maxlength="10" placeholder="登録日時">';
        echo '<script type="text/javascript">';
        echo 'jQuery(function($) { $("input[name=\'date\']").datepicker({ dateFormat: \'yymmdd\', changeYear: true, monthNames: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"] }); });';
        echo '</script>';
    }
};
add_action('restrict_manage_posts', 'add_date_filter');

検索条件の追加

検索条件に日付指定を追加している。
そもそもMW WP Form自体、CSVダウンロードには月検索結果のフィルタが効かないようだったので、その辺も考慮している。

dateパラメータがあればdate、なければmパラメータ(月検索)でフィルタリングする。

functions.php
function my_mwform_get_inquiry_data_args($args) {
    $strDate = get_query_var('date');
    $strM = get_query_var('m');
    if (empty($strDate)) {
        if (isset($_GET['date'])) {
            $strDate = $_GET['date'];
        }
    }

    if (empty($strM)) {
        if (isset($_GET['m'])) {
            $strM = $_GET['m'];
        }
    }

    $strSearchDate = '';
    $bIsDayExist = false;
    if (!empty($strDate)) {
        $strSearchDate = $strDate;
        $bIsDayExist = true;
    } elseif (!empty($strM)) {
        $strSearchDate = $strM . '01';
    }

    if (!empty($strSearchDate)) {
        $objDate = new DateTime($strSearchDate);
        $arrSearchCondition = array(
            'year' => $objDate->format('Y'),
            'month' => $objDate->format('m'),
        );
        if ($bIsDayExist) {
            $arrSearchCondition['day'] = $objDate->format('d');
        }

        $args = array_merge($args, array(
            'date_query' => array(
                $arrSearchCondition
             ),
        ));
    }

    return $args;
}
add_filter('mwform_get_inquiry_data_args-mwf_xxxx', 'my_mwform_get_inquiry_data_args');

デフォルトの月指定のドロップダウンを非表示にする

今回はここまでやらなかったが、完全に日付検索だけにしたい場合は以下のコードで可能。

functions.php
add_action( 'load-edit.php' , 'custom_load_edit' );
function custom_load_edit() {
    add_filter( 'disable_months_dropdown' , 'custom_disable_months_dropdown' , 10 , 2 );
    function custom_disable_months_dropdown( $false , $post_type ) {
        $disable_months_dropdown = $false;
        if (strpos($post_type, 'mwf_') !== false) {
            $disable_months_dropdown = true;
        }
        return $disable_months_dropdown;
    }
}

参考記事

以下の記事を参考にさせていただきました。

【WordPress】MW WP Formで都道府県フォームを作り、対応状況と都道府県で絞り込み検索しつつ、都道府県フォームの内容によって送信先を変更
WordPressのget_postsとWP_Queryの違いと使用方法について
WordPress管理画面でDatepickerを使う
WordPress管理画面の絞り込み検索をカスタマイズする

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

新しめのmacOSでPHP 5.6を自前ビルドするとOPcacheがクラッシュする件の解決

表題の通りですが、私の手元のmacOS 10.14 (Mojave)でPHP 5.6.40を自前ビルドしたところ、OPcache有効のときに常にクラッシュする問題が発生しました。OPcacheを無効にすると何も問題ありません。

ググったところ、PHP 5.5/5.6のOPcacheの実装がイケていないせいでclang 6.0のみ期待通りに動かないようで、macportsでパッチが作られていました。

更に元ネタはこれかな…?

この修正を入れたところPHP 5.6.40がOPcache有効でも死ななくなりました。

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

PHP mb_strimwidth関数

目的

  • 便利そうな関数だったので自分用に使い方をざっとまとめてみる

前提情報

機能

  • 文字列を丸めることができる。

  • 下記にmb_strimwidth関数の例を記載する。文字を丸める数の指定は半角での指定になるので日本語文字列の3文字目で丸めたいなら丸め文字数を6と指定する必要がある

    mb_strimwidth(丸めたい文字列, 文字列の開始位置, 開始位置から何文字で丸めるか, 丸めた後の文字列の最後に追加される文字);
    

# 具体例

  • 「日本の朝は酢豚とビール」という文字列の全角5文字目(半角10文字目)で丸める場合は下記の様に記載する。(ちなみに「日本の朝は酢豚とビール」という言葉は周期表の15属を縦に覚える時の語呂合わせである。)

    echo mb_strimwidth('日本の朝は酢豚とビール', 0, 10);
    
  • 上記の文字列丸めを実施した後に「...」を付与する場合は下記の様に記載する。カンマを語尾に三つ追加するので丸める文字数の指定も半角文字3文字分追加する。

    echo mb_strimwidth('日本の朝は酢豚とビール', 0, 13, '...');
    

参考文献

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