20200316のPHPに関する記事は18件です。

戻り値を変数に保存して扱う方法

最近PHP触りはじめたよーて人向け

といっても僕もまだまだ勉強中なので間違った点があればご指摘下さい、、
メモ程度です。

関数て最初慣れるまで理解しにくいですよね。。。
引数とかスコープとか:expressionless:

そんな方の助けになればとなんとなく理解しにくかったところを解説させていただきます!!!

1. function fullname($lastname, $firstname) //6行目の引数を受け取る
2. {
3.    $result = $lastname.$firstname; //1行目で受け取った引数を処理して$resultへ
4.     return $result;  //値を変数$resultへ返す
5. }
6. $result = fullname("山田", "太郎");  //関数fullname()を呼び出し&戻り値を受け取る
7. echo "私の名前は" . $result . "です。" //表示

ポイントは変数 = 関数名(引数)です!

コメントアウトで処理の流れを簡単に記しましたが、6行目のように変数 = 関数名(引数)を作ってあげて変数に値を保存してあげることです!!!

慣れるまではスコープや引数はややこしいですが、意外と単純なので頑張りましょう:punch:

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

Laravel6.xの日本語化パッケージ

目的

Laravel6.xの日本語化を行い、その言語リソースをパッケージ化してみる。

日本語化について

Laravel 6.x 多言語化

設定

config/app.php

    'locale' => 'en',

英語→日本語

デフォルトでは次の4種類が用意されている。

  1. 認証(auth.php)
  2. ページネーション(pagination.php)
  3. パスワードリセット(passwords.php)
  4. バリデーション(validation.php)

resources/lang/en以下に対応するphpファイルがあるので、それを翻訳してresources/lang/ja以下へ置く。

パッケージ化について

毎回翻訳するのは大変なのでパッケージ化してみる。

Laravel 6.x パッケージ開発

ServiceProviderで作成した日本語化ファイルを公開できるようにする。

    public function boot()
    {
        $this->publishes([
            __DIR__.'/../resources/lang' => $this->app->resourcePath('lang/'),
        ], 'lang-ja');
    }

vendor:publishコマンドで公開できるようになる。

$ php artisan vendor:publish --tag=lang-ja

作成した日本語化パッケージ

blue32a/laravel-language-ja

ほぼGoogle翻訳なので使いつつ調整していく予定。

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

フロントエンドビューを作成方法 

フロントエンドビュー(Frontend view)

このトピックでは、ブロック、レイアウト、テンプレートなど、Magento 2のビューについて学習します。 前のトピックでは、ルートとコントローラーを作成します。 ご存じのとおり、ページの表現を出力するためにビューが使用されます。

Magento 2では、ビューは3つのパスで作成されます。
-ブロック
- レイアウト
- テンプレート
作成したモジュールの単純なビューを構築することで、どのように作成するかを見つけます前のトピック

コントローラーを作成する

まず、レイアウトファイル.xmlを呼び出すコントローラーを作成します。

Karabiner/HelloMagento2/Controller/SomethingElse/Index.php
<?php

namespace Karabiner\HelloMagento2\Controller\SomethingElse;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;

class Index extends Action
{
    /**
     * @var PageFactory
     */
    private $pageFactory;

    public function __construct(Context $context, PageFactory $pageFactory)
    {
        parent::__construct($context);
        $this->pageFactory = $pageFactory;
    }

    /**
     * call Karabiner/HelloMagento2/view/frontend/layout/hellomagento2_somethingelse_index layout
     */
    public function execute()
    {
        return $this->pageFactory->create();
    }

}

レイアウトファイル(.xml)を作成

レイアウトは、Magento 2モジュールのビューレイヤーの主要なパスです。 レイアウトファイルはXMLファイルで、{MAGENTO_DIRECTORY}/view/{area}/layout/フォルダーにあります。
エリアパスは、レイアウトが適用される場所を定義するfrontendまたはadminhtml(adminダッシュボード)です。

レイアウトファイルの形式は{ルーターID} _ {コントローラー名} _ {アクション名}.xmlの形式になります。

レンダリングページの場合、Magentoはレイアウトファイルをチェックしてページのハンドルを見つけ、ブロックとテンプレートをロードします。 このモジュールのレイアウトハンドルファイルを作成します。

ファイル: app/code/Karabiner/HelloMagento2/view/frontend/layout/hellomagento2_somethingelse_index.xml

app/code/Karabiner/HelloMagento2/view/frontend/layout/hellomagento2_somethingelse_index.xml
<?xml version="1.0" encoding="UTF-8"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Karabiner\HelloMagento2\Block\SomethingElse" name="hello_magento2_display" 
                   template="Karabiner_HelloMagento2::hello_world.phtml" />
        </referenceContainer>
    </body>
</page>

ブロックファイルの作成

↑のファイルでは、このページのブロックとテンプレートを定義します。
class(ブロッククラス):HelloMagento2\HelloMagento2\Block\SomethingElse
ブロッククラスは、テンプレートファイルにデータを提供するクラスです。

template(テンプレートファイル):Karabiner_HelloMagento2::hello_world.phtml
ファイル名には2つの部分があります。
  1. Karabiner_HelloMagento2Karabiner/HelloMagento2/view/frontend/templatesを参照してください
  2. hello_world.phtml:上記のフォルダー内の場所は、SomethingElse/ hello_world.phtmlです。
 
name:これは必須属性であり、ブロックを参照として識別するために使用されます

テンプレートファイルを作成する

hello_world.phtmlというテンプレートファイルを作成します

app/code/Karabiner/HelloMagento2/view/frontend/templates/hello_world.phtml
以下コードを追加して

app/code/Karabiner/HelloMagento2/view/frontend/templates/hello_world.phtml
<?php

/**
 * @var \Karabiner\HelloMagento2\Block\SomethingElse $block
 */
?>

<?= $block->sayHi() ?>

レイアウトファイルでは、 Karabiner_HelloMagento2::hello_world.phtmlによってテンプレートを定義します。 これは、MagentoがモジュールKarabiner_HelloMagento2のテンプレートフォルダーでファイル名hello_world.phtmlを見つけることを意味します。 モジュールのテンプレートフォルダーは、 app/code/{vendor_name}/{module_name}/view/frontend/templates/です。

テンプレートファイルでは、ブロックオブジェクトに変数「$ block」を使用できます。 ご覧のとおり、Blockでメソッド sayHi()を呼び出します。 完了しました、

レイアウトまたはphtmlを変更した後、cache:cleanコマンドラインを実行する必要があります

MAGENTO_DIRECTORY
bin/magento cache:clean

もう一度このページにアクセスしてください
(http://[MAGENTO_URL]/custom_router_name/somethingelse) and see the result.

block-created.png

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

MySQLが起動できない(動かなくなった) という地獄のエラー(ERROR! The server quit without updating PID file  と Fatal error: Can't open and lock privilege tables: Table 'mysql.user' doesn't exist)

背景

phpの学習中にmysqlをいじっていましたw
急にmysqlが起動できなくなり、エラー解消にほぼ半日躓いてしまったので、
その解決策と試したことを記事としてのせたいと思う!!

mysqlでのエラー文との遭遇

エラー内容一覧

mysqlを起動を確かめる

 mysql.server start
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/var/mysql/ユーザーMBP.pid).

意味はpidファイルを更新せずに終わったよ!ってエラー?
すいません、、、意味がわかりません(涙)

pidファイルとは?

Pidファイルには、特定のプログラムのプロセスID(番号)が含まれています。たとえば、Apache HTTPDはメインプロセス番号をpidファイル(通常のテキストファイル、それ以上のもの)に書き込み、後でそこに含まれる情報を使用して停止します。 cat filename.pid | xargs killを使用して、その情報を使用して自分でプロセスを強制終了することもできるみたいです。

ググって試したこと!

①権限関係

権限確認すると「_mysql:_mysql」だったので、自分:adminに変更した。

chown -R [ユーザ名] /usr/local/var/mysql

うまくいかず。

②エラーログ確認しにいく

cd /usr/local/var/mysql
ls (lsコマンドでmysqlディレクトリの中身を確認する)
その中に
(ユーザー)MBP.err   というファイルがあるので
cat (ユーザー)MBP.err (catコマンドでファイルの中身を確認)

エラーログの中身に

2020-03-16 17:32:04 25993 [ERROR] Fatal error: Can't open and lock privilege tables: Table 'mysql.user' doesn't exist

調べてみると、インストール時に mysql_install_db が実行されるが、ディレクトリがわからない状態らしい。
インストール場所とユーザ名を指定して明示的に実行すると良さそうらしいですが、、

mysql_install_db --datadir=/var/lib/mysql --user=mysql

うまくいかず...
参考ページ
https://qiita.com/840_/items/06f32fecbe57c3fdf5ec

③最終手段 全てをアンイストール!!

よく見るとmysql、mysql@5.6、mysql@5.7やらいっぱいmysqlが存在してしまっていたので全てアンインストール!

の前に
*実行前に
そのまま解決手順を実行してしまうと、mysqlのデータが削除されてしまいます。
以下の手順を実行し、バックアップを行ってください!!

$ brew services stop mysql 
 mysqlを一旦停止
$ cp -pr /usr/local/Cellar/mysql /適当な場所/mysql_backup
  これで、mysqlのデータバックアップ。
brew uninstall mysql  
brew uninstall mysql@5.6 
brew uninstall mysql@5.7

まずはmysqlをアンインストール!

次にlocal配下のmysqlを全て削除する

$ rm -rf /usr/local/mysql
$ rm -rf /Library/StartupItems/MYSQL
$ rm -rf /Library/PreferencePanes/MySQL.prefPane
$ rm -rf /Library/Receipts/mysql-.pkg
$ rm -rf /usr/local/Cellar/mysql*
$ rm -rf /usr/local/bin/mysql*
$ rm -rf /usr/local/var/mysql*
$ rm -rf /usr/local/etc/my.cnf
$ rm -rf /usr/local/share/mysql*
$ rm -rf /usr/local/opt/mysql

ポイント!

brew uninstall mysqlでは削除できないファイル群を削除するのが大事!
残っているとアンインストールしても解消されないので、すっきり全て削除!

mysqlを再インストール

brew install mysql(@__使用するmysqlバージョンを指定)

mysqlコマンドをどこからでも実行できるようする

$ echo 'export PATH="/usr/local/opt/mysql/bin:$PATH"' >> ~/.bash_profile

 mysqlバージョンを指定している場合(mysql@5.6)
$ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.bash_profile

$ source ~/.bash_profile 

  mysqlのコマンドが打てるか確認する
$ which mysql
  以下のように表示されれば成功
/usr/local/opt/mysql/bin/mysql

最後にmysqlを起動

 mysqlの状態を確認するコマンドです
$ mysql.server status

 以下のように表示されれば成功
 SUCCESS! MySQL running (29385)

他にもプロセスを確認

$ ps ax | grep mysql
29714 s001  S      0:00.03 /bin/sh /usr/local/Cellar/mysql/8.0.19/bin/mysqld_safe --datadir=/usr/local/var/mysql --pid-file=/usr/local/var/mysql/ユーザMBP.pid
29825 s001  S      0:05.17 /usr/local/Cellar/mysql/8.0.19/bin/mysqld --basedir=/usr/local/Cellar/mysql/8.0.19 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/Cellar/mysql/8.0.19/lib/plugin --log-error=ユーザMBP.err --pid-file=/usr/local/var/mysql/ユーザMBP.pid
29837 s001  S+     0:00.00 grep mysql

ok問題ないですね!

参考
https://teratail.com/questions/199085

これでようやく解決してくれました!

本当に強引な方法ではありますがうまくいきました!

最後に

本当によく躓くエラーなので反省をとこれからの課題として記事として残しておきます!!

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

Magento 2.3のDeclarative Schema

Magento 2.3のDeclarative Schema

Declarative Schemaは、Magento2.2までのPHPコードを使用したデータベーススキーマ定義作成を置き換える仕組みです。
Magento2.3から新たに導入された仕組みで、XMLファイルを使用してテーブルの構造などを定義します。

Magento 2.3のDeclarative Schemaの使用する方法

Declarative Schemaの必要なファイルについてのみ説明します。

まず、フォルダ「Karabiner/Declarative/etc」内にファイル「db_schema.xml」を作成して、次のコードを記述します

db_schema.xml
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
  <table name="author_data" resource="default" engine="innodb" comment="Author Table">
     <column xsi:type="smallint" name="id" padding="6" unsigned="false" nullable="false" identity="true" comment="Author ID"/>
          <column xsi:type="varchar" name="author_name" nullable="false" length="255" comment="Author Name"/>
          <column xsi:type="varchar" name="author_email" nullable="false" length="255" comment="Author Email"/>
          <column xsi:type="varchar" name="affliation" nullable="false" length="255" comment="Affliation"/>
          <column xsi:type="int" name="age" unsigned="true" nullable="true" identity="false" default="" comment="Age"/>
          <constraint xsi:type="primary" name="PRIMARY">
             <column name="id"/>
          </constraint>
  </table>
</schema> 

各テーブルノードは、データベース内のテーブルを表します。

テーブルノードには、次の3種類のサブノードを含めることができます。

  • Column
  • Constraint
  • Index

setup:upgradeコマンドを実行すると、テーブル「author_data」が作成されます

新しい列を追加

既存のテーブルに新しい列を追加する場合は、db_schema.xmlに新しい列ノード(<column>)を追加する必要があります。setup:upgradeコマンドを実行すると、新しい列が追加されます。

db_schema.xml
<column xsi:type="int" name="new_column" unsigned="true" nullable="true" identity="false" default="" comment="New column"  />

既存の列を削除

既存の列を削除する場合は、テーブルノード内の列ノード(<column>)を削除するか、 disabledアトリビュートをtrueに設定する必要があります。

db_schema.xml
<column xsi:type="int" name="age" unsigned="true" nullable="true" identity="false" default="" comment="Age" disabled=”true” />

しかし、アップグレードコマンドを実行する前に、次のコマンドを実行してスキーマを db_whitelist_schema.jsonファイルに追加する必要があります。

php bin/magento setup:db-declaration:generate-whitelist --module-name=Karabiner_Declarative 

Karabiner_Declarativeはモジュール名です。 そこでモジュール名を指定する必要があります。

setup:upgradeコマンドを実行すると、列が削除されます。

列タイプを変更し、そのtypeアトリビュートをint、varchar、textなどに変更できます。

列の名前を変更

列の名前を変更するには、まず不要な列を削除する必要があります。 別の列を追加します。 その列のデータを新しく作成したものに移行する必要があります。これを行うには、古い列からデータを移行するアトリビュートonCreateを設定する必要があります。
author_email列の名前を「email」に変更する場合は、author_email列を削除して新しい列を追加します。

db_schema.xml
<column xsi:type="varchar" name="email" onCreate="migrateDataFrom(author_email)" on_update="false" nullable="false" default="" comment="Author Email"/>
<column xsi:type="varchar" name="author_email" unsigned="true" nullable="true" identity="false" default="" comment="Email" disabled=”true” />

削除された列のデータで新しい列「email」が作成されます。

テーブルをドロップ

テーブルを削除するには、テーブルノード全体を「db_schema.xml」から削除するか、「disabled」アトリビュートを「true」に設定します。

db_schema.xml
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
  <table name="author_data" resource="default" engine="innodb" comment="Author Table" disabled=”true”>
   ....
  </table>
</schema> 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Declarative Schema in Magento 2.3

Declarative Schema in Magento 2.3

Magento has introduced a new feature called Declarative Schema which aims to simplify the Magento installation and upgrade processes. This new concept will allow a developer to get away from writing updates for each new version in favour of declaring the final result that the developer wants to achieve.

How to use Declarative Schema in Magento 2.3

we will only discuss file required for a Declarative Schema.

Firstly create a file db_schema.xml inside the folder Karabiner/Declarative/etc and write the following code

db_schema.xml
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
  <table name="author_data" resource="default" engine="innodb" comment="Author Table">
     <column xsi:type="smallint" name="id" padding="6" unsigned="false" nullable="false" identity="true" comment="Author ID"/>
          <column xsi:type="varchar" name="author_name" nullable="false" length="255" comment="Author Name"/>
          <column xsi:type="varchar" name="author_email" nullable="false" length="255" comment="Author Email"/>
          <column xsi:type="varchar" name="affliation" nullable="false" length="255" comment="Affliation"/>
          <column xsi:type="int" name="age" unsigned="true" nullable="true" identity="false" default="" comment="Age"/>
          <constraint xsi:type="primary" name="PRIMARY">
             <column name="id"/>
          </constraint>
  </table>
</schema> 

Each table node represents a table in the database.

A table node can contain three types of subnodes:

  • Column
  • Constraint
  • Index

So when you run setup:upgrade command then it will create the table “author_data”

Adding New Column

If you want to add a new column to the existing table then you need to add a new column node in db_schema.xml and on running upgrade command it will add the new column.

db_schema.xml
<column xsi:type="int" name="new_column" unsigned="true" nullable="true" identity="false" default="" comment="New column"  />

Remove Existing Column

Now if you want to remove the existing column then you either need to remove the column node (< column >) inside the table node or you can set the disabled attribute to true.

db_schema.xml
<column xsi:type="int" name="age" unsigned="true" nullable="true" identity="false" default="" comment="Age" disabled=”true” />

But before running the upgrade command you need to add your schema to db_whitelist_schema.json file by running the following command-

php bin/magento setup:db-declaration:generate-whitelist --module-name=Karabiner_Declarative 

Karabiner_Declarative is a module name. You need to specify your module name there.

Now on running setup:upgrade command, it will remove the column.

Changing the column type
You can change the column type, changing its type attribute to int, varchar, text etc.

Renaming a column

To rename a column you need to first remove the one you don’t want and add another column with your desired name. Now you need to migrate that column data into a newly created one, to do this you need to set an attribute on Create which will migrate data from the old column.
If we want to rename the author_email column to just email, we will remove the author column and add a new one.

db_schema.xml
<column xsi:type="varchar" name="email" onCreate="migrateDataFrom(author_email)" on_update="false" nullable="false" default="" comment="Author Email"/>
<column xsi:type="int" name="email" unsigned="true" nullable="true" identity="false" default="" comment="Email" disabled=”true” />

So this will create a new column ‘email’ with data from the removed column.

Drop a Table

To drop a table, either remove the entire table node from db_schema.xml or set the disabled attribute to true.

db_schema.xml
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
  <table name="author_data" resource="default" engine="innodb" comment="Author Table" disabled=”true”>
   ....
  </table>
</schema> 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPエクステンションをCMakeする

PHP extensionをCMakeを使ってビルドする

構成

sample/
    CMakeLists.txt
    config.cmake
    config.h.in
    php_sample.h
    sample.c
    test.php

各ファイル

CMakeLists.txt
cmake_minimum_required(VERSION 3.5.1)

project(sample-ext)

set(CMAKE_C_STANDARD_REQUIRED ON)

set(CMAKE_C_FLAGS "-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -DPHP_ATOM_INC -DHAVE_CONFIG_H -O3 -funroll-loops")

execute_process(COMMAND "php-config" "--prefix" OUTPUT_VARIABLE PHP_BASE_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "php-config" "--include-dir" OUTPUT_VARIABLE PHP_INCLUDE_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "php-config" "--extension-dir" OUTPUT_VARIABLE EXTENSION_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)

set(COMPILE_DL_SAMPLE 1)
set(HAVE_SAMPLE 1)
include(config.cmake)

include_directories(
    "${PHP_INCLUDE_PATH}"
    "${PHP_INCLUDE_PATH}/main"
    "${PHP_INCLUDE_PATH}/TSRM"
    "${PHP_INCLUDE_PATH}/Zend"
    "${PHP_INCLUDE_PATH}/ext"
    "${PHP_INCLUDE_PATH}/ext/date/lib"
    ${CMAKE_BINARY_DIR})

add_library(sample-shared SHARED 
    ${CMAKE_CURRENT_SOURCE_DIR}/sample.c)

set_target_properties(sample-shared PROPERTIES LINK_FLAGS "-Wl,-rpath,${PHP_BASE_PATH}/lib")
set_target_properties(sample-shared PROPERTIES PREFIX "" OUTPUT_NAME sample) 

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/sample.so 
    DESTINATION ${EXTENSION_DIR}
    PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE 
    GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
config.cmake
find_path(DLFCN_H_PATH dlfcn.h PATHS /usr /usr/local PATH_SUFFIXES include)
find_path(INTTYPES_H_PATH inttypes.h PATHS /usr /usr/local PATH_SUFFIXES include)
find_path(MEMORY_H_PATH memory.h PATHS /usr /usr/local PATH_SUFFIXES include)
find_path(STDINT_H_PATH stdint.h PATHS /usr /usr/local PATH_SUFFIXES include)
find_path(STDLIB_H_PATH stdlib.h PATHS /usr /usr/local PATH_SUFFIXES include)
find_path(STRINGS_H_PATH strings.h PATHS /usr /usr/local PATH_SUFFIXES include)
find_path(STRING_H_PATH string.h PATHS /usr /usr/local PATH_SUFFIXES include)
find_path(SYS_STAT_H_PATH sys/stat.h PATHS /usr /usr/local PATH_SUFFIXES include)
find_path(SYS_TYPES_H_PATH sys/types.h PATHS /usr /usr/local PATH_SUFFIXES include)
find_path(UNISTD_H_PATH unistd.h PATHS /usr /usr/local PATH_SUFFIXES include)

if (DLFCN_H_PATH)
    set(HAVE_DLFCN_H 1)
endif (DLFCN_H_PATH)

if (INTTYPES_H_PATH)
    set(HAVE_INTTYPES_H 1)
endif (INTTYPES_H_PATH)

if (MEMORY_H_PATH)
    set(HAVE_MEMORY_H 1)
endif (MEMORY_H_PATH)

if (STDINT_H_PATH)
    set(HAVE_STDINT_H 1)
endif (STDINT_H_PATH)

if (STDLIB_H_PATH)
    set(HAVE_STDLIB_H 1)
endif (STDLIB_H_PATH)

if (STRINGS_H_PATH)
    set(HAVE_STRINGS_H 1)
endif (STRINGS_H_PATH)

if (STRING_H_PATH)
    set(HAVE_STRING_H 1)
endif (STRING_H_PATH)

if (SYS_STAT_H_PATH)
    set(HAVE_SYS_STAT_H 1)
endif (SYS_STAT_H_PATH)

if (SYS_TYPES_H_PATH)
    set(HAVE_SYS_TYPES_H 1)
endif (SYS_TYPES_H_PATH)

if (UNISTD_H_PATH)
    set(HAVE_UNISTD_H 1)
endif (UNISTD_H_PATH)


set(PACKAGE_BUGREPORT "")
set(PACKAGE_NAME "")
set(PACKAGE_STRING "")
set(PACKAGE_TARNAME "")
set(PACKAGE_URL "")
set(PACKAGE_VERSION "")

if (DLFCN_H_PATH AND
    INTTYPES_H_PATH AND
    MEMORY_H_PATH AND
    STDINT_H_PATH AND
    STDLIB_H_PATH AND
    STRINGS_H_PATH AND
    STRING_H_PATH AND
    SYS_STAT_H_PATH AND
    SYS_TYPES_H_PATH AND
    UNISTD_H_PATH)
    set(STDC_HEADERS 1)
endif (DLFCN_H_PATH AND
    INTTYPES_H_PATH AND
    MEMORY_H_PATH AND
    STDINT_H_PATH AND
    STDLIB_H_PATH AND
    STRINGS_H_PATH AND
    STRING_H_PATH AND
    SYS_STAT_H_PATH AND
    SYS_TYPES_H_PATH AND
    UNISTD_H_PATH)

configure_file(
    ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
    ${CMAKE_BINARY_DIR}/config.h)
config.h.in
#cmakedefine COMPILE_DL_SAMPLE @COMPILE_DL_SAMPLE@
#cmakedefine HAVE_DLFCN_H @HAVE_DLFCN_H@
#cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@
#cmakedefine HAVE_MEMORY_H @HAVE_MEMORY_H@
#cmakedefine HAVE_SAMPLE @HAVE_SAMPLE@
#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@
#cmakedefine HAVE_STDLIB_H @HAVE_STDLIB_H@
#cmakedefine HAVE_STRINGS_H @HAVE_STRINGS_H@
#cmakedefine HAVE_STRING_H @HAVE_STRING_H@
#cmakedefine HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@
#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@
#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@
#cmakedefine NO_MINUS_C_MINUS_O @NO_MINUS_C_MINUS_O@
#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
#define PACKAGE_NAME "@PACKAGE_NAME@"
#define PACKAGE_STRING "@PACKAGE_STRING@"
#define PACKAGE_TARNAME "@PACKAGE_TARNAME@"
#define PACKAGE_URL "@PACKAGE_URL@"
#define PACKAGE_VERSION "@PACKAGE_VERSION@"
#cmakedefine STDC_HEADERS @STDC_HEADERS@

上記はphpize./configureが担当している部分ですが多分こんな感じです。
これがないとエラーになったので、config.hはコピペした方が良いかもしれません。

php_sample.h
#ifndef PHP_SAMPLE_H
# define PHP_SAMPLE_H

extern zend_module_entry sample_module_entry;
# define phpext_sample_ptr &sample_module_entry

# define PHP_SAMPLE_VERSION "0.1.0"

# if defined(ZTS) && defined(COMPILE_DL_SAMPLE)
ZEND_TSRMLS_CACHE_EXTERN()
# endif

#endif  /* PHP_SAMPLE_H */
sample.c
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "php.h"
#include "ext/standard/info.h"
#include "php_sample.h"

/* For compatibility with older PHP versions */
#ifndef ZEND_PARSE_PARAMETERS_NONE
#define ZEND_PARSE_PARAMETERS_NONE() \
    ZEND_PARSE_PARAMETERS_START(0, 0) \
    ZEND_PARSE_PARAMETERS_END()
#endif

/* {{{ void sample_test1()
 */
PHP_FUNCTION(sample_test1)
{
    ZEND_PARSE_PARAMETERS_NONE();

    php_printf("The extension %s is loaded and working!\r\n", "sample");
}
/* }}} */

/* {{{ string sample_test2( [ string $var ] )
 */
PHP_FUNCTION(sample_test2)
{
    char *var = "World";
    size_t var_len = sizeof("World") - 1;
    zend_string *retval;

    ZEND_PARSE_PARAMETERS_START(0, 1)
        Z_PARAM_OPTIONAL
        Z_PARAM_STRING(var, var_len)
    ZEND_PARSE_PARAMETERS_END();

    retval = strpprintf(0, "Hello %s", var);

    RETURN_STR(retval);
}
/* }}}*/

/* {{{ PHP_RINIT_FUNCTION
 */
PHP_RINIT_FUNCTION(sample)
{
#if defined(ZTS) && defined(COMPILE_DL_SAMPLE)
    ZEND_TSRMLS_CACHE_UPDATE();
#endif

    return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(sample)
{
    php_info_print_table_start();
    php_info_print_table_header(2, "sample support", "enabled");
    php_info_print_table_end();
}
/* }}} */

/* {{{ arginfo
 */
ZEND_BEGIN_ARG_INFO(arginfo_sample_test1, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_sample_test2, 0)
    ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
/* }}} */

/* {{{ sample_functions[]
 */
static const zend_function_entry sample_functions[] = {
    PHP_FE(sample_test1,        arginfo_sample_test1)
    PHP_FE(sample_test2,        arginfo_sample_test2)
    PHP_FE_END
};
/* }}} */

/* {{{ sample_module_entry
 */
zend_module_entry sample_module_entry = {
    STANDARD_MODULE_HEADER,
    "sample",                   /* Extension name */
    sample_functions,           /* zend_function_entry */
    NULL,                           /* PHP_MINIT - Module initialization */
    NULL,                           /* PHP_MSHUTDOWN - Module shutdown */
    PHP_RINIT(sample),          /* PHP_RINIT - Request initialization */
    NULL,                           /* PHP_RSHUTDOWN - Request shutdown */
    PHP_MINFO(sample),          /* PHP_MINFO - Module info */
    PHP_SAMPLE_VERSION,     /* Version */
    STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_SAMPLE
# ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
# endif
ZEND_GET_MODULE(sample)
#endif

こちらはスケルトンそのままです。

test.php
<?php
sample_test1();

ビルド

$ mkdir build
$ cd build
$ cmake ..
$ make -j

動作確認

$ php -d extension=build/sample.so -f test.php
The extension sample is loaded and working!

phpize

sample.pb.cc のようなファイル名だとIFSコマンドで分割している箇所でおかしくなるのでCMakeのサンプルがあったので調整してみました。
動作確認の引数をいつも忘れるので備忘録です。:relaxed:

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

WordPress検証コード

概要

WordPressのテーマ・プラグインの検証をするときによく使うコードをまとめます。
開発よりもむしろ全体的なチューニングでよく使うものです。

ログ出力

ログをファイルに書き出す。
/wp-content/debug.log にログが書き出される。

これをwp-config.phpに書く

define( 'WP_DEBUG', true );
if ( WP_DEBUG ) {
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', true );
    @ini_set( 'display_errors', 1 );
    define( 'SAVEQUERIES', true );
}

ログ出力

error_log('test message');

Hook

掛かっているフックを調べる

現状どのようなフックが掛かっているかを確認する。
ある程度は何がどんなフックをかけているか把握できる。

add_action('wp_footer', function(){
    global $wp_filter;
    echo "<pre>";
    var_dump($wp_filter['wp_footer']);
    echo "</pre>";
});

どのタイミングで起こるのかを確認

WordPressの基本的なアクションフックが始まるごとにログを出力する。結構力技。

テーマのfunctions.php上ではロードが遅いので、プラグインから動かすのがおすすめ。

add_action('muplugins_loaded',function(){error_log('[hook] muplugins_loaded');},0);
add_action('registered_taxonomy',function(){error_log('[hook] registered_taxonomy');},0);
add_action('registered_post_type',function(){error_log('[hook] registered_post_type');},0);
add_action('plugins_loaded',function(){error_log('[hook] plugins_loaded');},0);
add_action('sanitize_comment_cookies',function(){error_log('[hook] sanitize_comment_cookies');},0);
add_action('setup_theme',function(){error_log('[hook] setup_theme');},0);
add_action('load_textdomain',function(){error_log('[hook] load_textdomain');},0);
add_action('after_setup_theme',function(){error_log('[hook] after_setup_theme');},0);
add_action('auth_cookie_malformed',function(){error_log('[hook] auth_cookie_malformed');},0);
add_action('auth_cookie_valid',function(){error_log('[hook] auth_cookie_valid');},0);
add_action('set_current_user',function(){error_log('[hook] set_current_user');},0);
add_action('init',function(){error_log('[hook] init');},0);
add_action('register_sidebar',function(){error_log('[hook] register_sidebar');},0);
add_action('wp_register_sidebar_widget',function(){error_log('[hook] wp_register_sidebar_widget');},0);
add_action('wp_default_scripts',function(){error_log('[hook] wp_default_scripts');},0);
add_action('wp_default_styles',function(){error_log('[hook] wp_default_styles');},0);
add_action('admin_bar_init',function(){error_log('[hook] admin_bar_init');},0);
add_action('add_admin_bar_menus',function(){error_log('[hook] add_admin_bar_menus');},0);
add_action('wp_loaded',function(){error_log('[hook] wp_loaded');},0);
add_action('parse_request',function(){error_log('[hook] parse_request');},0);
add_action('send_headers',function(){error_log('[hook] send_headers');},0);
add_action('parse_query',function(){error_log('[hook] parse_query');},0);
add_action('pre_get_posts',function(){error_log('[hook] pre_get_posts');},0);
add_action('posts_selection',function(){error_log('[hook] posts_selection');},0);
add_action('wp',function(){error_log('[hook] wp');},0);
add_action('template_redirect',function(){error_log('[hook] template_redirect');},0);
add_action('get_header',function(){error_log('[hook] get_header');},0);
add_action('wp_enqueue_scripts',function(){error_log('[hook] wp_enqueue_scripts');},0);
add_action('twentyeleven_enqueue_color_scheme',function(){error_log('[hook] twentyeleven_enqueue_color_scheme');},0);
add_action('wp_head',function(){error_log('[hook] wp_head');},0);
add_action('wp_print_styles',function(){error_log('[hook] wp_print_styles');},0);
add_action('wp_print_scripts',function(){error_log('[hook] wp_print_scripts');},0);
add_action('get_search_form',function(){error_log('[hook] get_search_form');},0);
add_action('loop_start',function(){error_log('[hook] loop_start');},0);
add_action('the_post',function(){error_log('[hook] the_post');},0);
add_action('get_template_part_content',function(){error_log('[hook] get_template_part_content');},0);
add_action('loop_end',function(){error_log('[hook] loop_end');},0);
add_action('get_sidebar',function(){error_log('[hook] get_sidebar');},0);
add_action('dynamic_sidebar',function(){error_log('[hook] dynamic_sidebar');},0);
add_action('get_search_form',function(){error_log('[hook] get_search_form');},0);
add_action('pre_get_comments',function(){error_log('[hook] pre_get_comments');},0);
add_action('wp_meta',function(){error_log('[hook] wp_meta');},0);
add_action('get_footer',function(){error_log('[hook] get_footer');},0);
add_action('get_sidebar',function(){error_log('[hook] get_sidebar');},0);
add_action('twentyeleven_credits',function(){error_log('[hook] twentyeleven_credits');},0);
add_action('wp_footer',function(){error_log('[hook] wp_footer');},0);
add_action('wp_print_footer_scripts',function(){error_log('[hook] wp_print_footer_scripts');},0);
add_action('admin_bar_menu',function(){error_log('[hook] admin_bar_menu');},0);
add_action('wp_before_admin_bar_render',function(){error_log('[hook] wp_before_admin_bar_render');},0);
add_action('wp_after_admin_bar_render',function(){error_log('[hook] wp_after_admin_bar_render');},0);
add_action('shutdown',function(){error_log('[hook] shutdown');},0);

スタイル・スクリプト

キューされているスクリプト一覧を見る

add_action( 'wp_print_scripts', function() {
    echo "<pre>";
    var_dump(wp_scripts()->queue);
    echo "</pre>";
}, 0);

スタイル

add_action( 'wp_print_scripts', function() {
    echo "<pre>";
    var_dump(wp_styles()->queue);
    echo "</pre>";
}, 100);

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

Laradockをやる時にコンテナがdocker-composeでもなかなか立ち上がってくれなかった話

Laradockを使っての環境構築にチャレンジしてみました。
Windows10 homeを使っているので、Docker for Desktopは使えず、
かつInsider Previewには切り替えたくないなと思いましたので、
Docker Toolboxをインストール!

https://docs.docker.com/toolbox/toolbox_install_windows/

こちらリンクですが、入ってみても分かる通り、非常にわかりにくいUIですが頑張ってインストールしましょう。
その際に、gitとvirtual boxがインストールしますかと選択肢がでますが、
すでにインストールしている人はダブルと不具合になるのでチェックは外しておきましょう。

インストール完了するとDocker Quickstart Terminalgが使えるのでクリックして起動。
初回はけっこう時間がかかります。
終了したら、おなじみのクジラのAAとIPアドレスが採番されて完了です。

実際にVirtual Boxを開いてみてみると、「default」というボックスが立ち上がっているのが見てわかります。

その後、任意のターミナル(せっかく開いているのでDocker Quickstart Terminalでよいかと)で

$ docker --version

と入力するとバージョンが返ってきたらインストール完了です。

続いて任意のディレクトリ(僕はいつもCフォルダ直下に作っています)で

/c
$ mkdir docker-workspace

と打って作業用フォルダを作りましょう。

/c
$ cd docker-workspace

でそこに移動して、Laradockをインストールします。

docker-workspace
$ git clone https://github.com/Laradock/laradock.git
$ ls
> laradock
$ cd laradock

次にenvファイルの名前を書き換えます。

laradock
$ cp env-example .env

ここまでできたら、いよいよコンテナを立ち上げていきます。

laradock
$ docker-compose up -d nginx mysql phpmyadmin workspace

こちらもプロセスにかなりの時間が初回はかかります。
そして、ほとんどの方は問題なく終了するかと思いますが、
私の場合は、こんなエラーがでてきました。

Starting phpmyadmin ... error

ERROR: for phpmyadmin  Cannot start service phpmyadmin: driver failed programming external coStarting phpmyadmin ... error
006): Bind for 0.0.0.0:8080 failed: port is already allocated

ERROR: for workspaceCannot start service workspace: driver failed programming external connectivity on endpoint workspace(xxxxxxxxx): Bind for 0.0.0.0:8080 failed: port is already allocated

どうやら、ポートが被っている??
一旦、再起動してみたり、コンテナを削除して作り直しても無駄なうえ、
lsofコマンドができず、起動しているファイルをkillすることもできなかったので、
.envファイルを編集することにしました。

.env
### WORKSPACE #############################################

WORKSPACE_COMPOSER_GLOBAL_INSTALL=true
WORKSPACE_COMPOSER_AUTH=false
WORKSPACE_COMPOSER_REPO_PACKAGIST=
WORKSPACE_NVM_NODEJS_ORG_MIRROR=
WORKSPACE_INSTALL_NODE=true
WORKSPACE_NODE_VERSION=node
WORKSPACE_NPM_REGISTRY=
WORKSPACE_INSTALL_YARN=true
WORKSPACE_YARN_VERSION=latest
WORKSPACE_INSTALL_NPM_GULP=true
WORKSPACE_INSTALL_NPM_BOWER=false
WORKSPACE_INSTALL_NPM_VUE_CLI=true
WORKSPACE_INSTALL_NPM_ANGULAR_CLI=false
WORKSPACE_INSTALL_PHPREDIS=true
WORKSPACE_INSTALL_WORKSPACE_SSH=false
WORKSPACE_INSTALL_SUBVERSION=false
WORKSPACE_INSTALL_BZ2=false
WORKSPACE_INSTALL_GMP=false
WORKSPACE_INSTALL_XDEBUG=false
WORKSPACE_INSTALL_PCOV=false
WORKSPACE_INSTALL_PHPDBG=false
WORKSPACE_INSTALL_SSH2=false
WORKSPACE_INSTALL_LDAP=false
WORKSPACE_INSTALL_SOAP=false
WORKSPACE_INSTALL_XSL=false
WORKSPACE_INSTALL_SMB=false
WORKSPACE_INSTALL_IMAP=false
WORKSPACE_INSTALL_MONGO=false
WORKSPACE_INSTALL_AMQP=false
WORKSPACE_INSTALL_CASSANDRA=false
WORKSPACE_INSTALL_GEARMAN=false
WORKSPACE_INSTALL_MSSQL=false
WORKSPACE_INSTALL_DRUSH=false
WORKSPACE_DRUSH_VERSION=8.1.17
WORKSPACE_INSTALL_DRUPAL_CONSOLE=false
WORKSPACE_INSTALL_WP_CLI=false
WORKSPACE_INSTALL_AEROSPIKE=false
WORKSPACE_INSTALL_OCI8=false
WORKSPACE_INSTALL_V8JS=false
WORKSPACE_INSTALL_LARAVEL_ENVOY=false
WORKSPACE_INSTALL_LARAVEL_INSTALLER=false
WORKSPACE_INSTALL_DEPLOYER=false
WORKSPACE_INSTALL_PRESTISSIMO=false
WORKSPACE_INSTALL_LINUXBREW=false
WORKSPACE_INSTALL_MC=false
WORKSPACE_INSTALL_SYMFONY=false
WORKSPACE_INSTALL_PYTHON=false
WORKSPACE_INSTALL_POWERLINE=false
WORKSPACE_INSTALL_SUPERVISOR=false
WORKSPACE_INSTALL_IMAGE_OPTIMIZERS=false
WORKSPACE_INSTALL_IMAGEMAGICK=false
WORKSPACE_INSTALL_TERRAFORM=false
WORKSPACE_INSTALL_DUSK_DEPS=false
WORKSPACE_INSTALL_PG_CLIENT=false
WORKSPACE_INSTALL_PHALCON=false
WORKSPACE_INSTALL_SWOOLE=false
WORKSPACE_INSTALL_TAINT=false
WORKSPACE_INSTALL_LIBPNG=false
WORKSPACE_INSTALL_IONCUBE=false
WORKSPACE_INSTALL_MYSQL_CLIENT=false
WORKSPACE_INSTALL_PING=false
WORKSPACE_INSTALL_SSHPASS=false
WORKSPACE_INSTALL_INOTIFY=false
WORKSPACE_INSTALL_FSWATCH=false
WORKSPACE_INSTALL_YAML=false
WORKSPACE_INSTALL_MAILPARSE=false
WORKSPACE_PUID=1000
WORKSPACE_PGID=1000
WORKSPACE_CHROME_DRIVER_VERSION=2.42
WORKSPACE_TIMEZONE=UTC
WORKSPACE_SSH_PORT=2222
WORKSPACE_INSTALL_FFMPEG=false
WORKSPACE_INSTALL_WKHTMLTOPDF=false
WORKSPACE_INSTALL_GNU_PARALLEL=false
WORKSPACE_INSTALL_AST=true
WORKSPACE_AST_VERSION=1.0.3
WORKSPACE_VUE_CLI_SERVE_HOST_PORT=8008 #ここ、8080になってたので適当な番号に書き換えました!
WORKSPACE_VUE_CLI_UI_HOST_PORT=8001
WORKSPACE_INSTALL_GIT_PROMPT=false

これでコマンドをやり直したらできました!!

docker-compose up

とだけやってしまうと、容量不足になってしまい、

ERROR: Service 'web' failed to build: failed to copy files: failed to copy directory: Error processing tar file(exit status 1): open /node_modules/hosted-git-info/CHANGELOG.md: no space left on device

みたいな感じでエラーになってしまうので、立ち上げるコンテナを-dで指定しましょう。
立ち上げた後は、

laradock
$ docker-compose exec workspace bash

と打ってワークスペースに接続します。ディレクトリがroot@var/wwwみたいな感じに変わったら成功。いつもやるようにプロジェクトをコマンドを打って作りましょう。

laradock
$ composer create-project --prefer-dist laravel/laravel #アプリ名

またこれで少しの間完了するまで放置します。

root@var/www
$ ls
>laradock #アプリ名

できたらexitで接続を終了します。

laradock
$ cd nginx/sites/

最後にnginxの設定ファイルを編集します。

laradock/nginx/sites
$ cp default.conf default.conf.backup   
$ cp laravel.conf.example default.conf
$ vim default.conf
defalut.conf
server {

    listen 80;
    listen [::]:80;

    # For https
    # listen 443 ssl;
    # listen [::]:443 ssl ipv6only=on;
    # ssl_certificate /etc/nginx/ssl/default.crt;
    # ssl_certificate_key /etc/nginx/ssl/default.key;

    server_name laravel.test;
    root /var/www/laravel/#ここにアプリ名を入れる!/public;
    index index.php index.html index.htm;

laradockに戻って $docker-compose restartをして、
Docker Quickstart Terminal起動時に出るIPアドレスをブラウザで入力すると、
Laravelトップページがでます。

これで、環境構築は完了です!

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

AWSで作ったLaravelアプリケーションをXserverにデプロイする

はじめに

タイトル通りですが、LaravelアプリケーションのデプロイをXserverで試してみました。

AWSでアプリケーションは作成したのですが、
XAMPPで作成した方も以下のやり方でできると思います。

まとめ

さっそくですがやり方を以下にまとめました。

※XAMPPでアプリケーションを作成した方は⑥以降を参考にしていただければと思います。

①AWSでLaravelアプリケーションを作成。

②作成したアプリケーションのフォルダをダウンロードしてXAMPP環境下(htdocs内)に保存する。

③XAMPPでphpMyAdminを起動。アプリケーション用のDB(DB名:laravel)を作成する。

④.envをXAMPP環境下でDBが使えるようにに編集。

.env
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

⑤コマンドプロンプトで同フォルダに移動してテーブル作成

$ cd 作成したアプリのフォルダ
$ php artisan migrate//このコマンドでテーブルが作成されます。

⑥FTP(FileZillaを使用しました)で転送したいドメイン内のpublic_htmlへ作成したアプリのpublic内のファイルをすべて転送

⑦publicフォルダ以外のファイルをまとめて新しく作ったフォルダに転送(public_htmlと同じ階層下)

フォルダ名はlaraveltestとしました。
コメント 2020-01-22 230052.png

⑧public_htmlに転送したindex.phpのrequire先を新しく作ったフォルダ先に変更

index.php
require __DIR__.'/../laraveltest/vendor/autoload.php';//28行目
~~
$app = require_once __DIR__.'/../laraveltest/bootstrap/app.php';//38行目

⑨XAMPP環境下のphpMyAdminで同アプリ用に作ったテーブルをエクスポート(.sqlファイル)

⑩先ほどエクスポートしたsqlファイルをXserver環境下のphpMyAdminにインポートしてテーブル作成

⑪転送した.envを以下のように編集して保存

.env
APP_URL=http://独自ドメイン/

DB_connection=mysql
DB_HOST=自身のサーバ名.xserver.jp
DB_PORT=3306
DB_DATABASE=自身のデータベース名
DB_USERNAME=自身のユーザー名
DB_PASSWORD=自身で設定したパスワード

⑫対象のドメインへアクセスして問題ないか確認。

実際にデプロイしたサイトは以下になります。
よければ覗いてみてください◎
https://craftbeers.site

参考

参考にさせていただいた記事は以下です。
https://qiita.com/hitotch/items/5c8c2858c883e69cd507

最後に

完全に個人的備忘録です。
もしかしたらかなり遠回りな方法でデプロイしているかもしれませんので、
他にも良い方法がありましたら教えていただけますと幸いです。
また、初投稿で書き方もあまりわからなかったのでかなり雑な記事になってしまいました。。。
 

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

未定義の場合実行しないforeachを、なるべくシンプルに書いてみる

目的

  • PHP Warning: Invalid argument supplied for foreach() を起こさない
  • 予め空配列を定義するのもなんか嫌
  • でも定義されているときはforeachを実行してほしい

対策

// $array をstring型の配列と仮定します
foreach($array as $key => $value){
    echo $value;
}
// => PHP Warning:  Invalid argument supplied for foreach()

// 対策
if(isset($array)) foreach($array as $key => $value){
    echo $value;
}
// => エラーも起きず、何も出力されない

$array = ['a', 'b', 'c'];
// $array をstring型の配列と仮定します
if(isset($array)) foreach($array as $key => $value){
    echo $value;
}
// => abc

課題点

  • そもそも未定義かもしれない変数を使う構造の是非
  • isset()関数の仕様上、NULLと未定義を区別できない(らしい)

アルバイト中、if文とforeach文を1行にまとめられるのか気になったので調べてみました。

「こういうのもあるよ!」とか「やめたほうがいいよ!」などありましたらコメントお願いします。?‍♂️(お手柔らかに)

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

swagger-php �で書く Annotation テンプレ3種

この記事は、温かみのある手作業で swagger-php の annotation を書かなければいけない人向けに、コピペで使えるannotationを提供する目的でまとめます。

単なる key value 表現のannotation

出力例

{
  "id": "1",
  "name": "サンプル太郎",
  "email": "example@hoge.com",
  "created_at": "2006-04-13T14:12:53+09:00"
}

annotation

    /**
     * @OA\Get(
     *   tags={"Common"},
     *   path="/api/user",
     *   @OA\Response(
     *       response="200",
     *       description="success",
     *       @OA\JsonContent(ref="#/components/schemas/user_responder")
     *   ),
     *   @OA\Response(
     *       response="204",
     *       description="there is no authorized user",
     *       @OA\JsonContent(ref="#/components/schemas/204_no_content")
     *   )
     * )
     */

tags は swagger-ui で見るときに整理されて見えるので便利のためにつけてます。
Response については別のところで定義した schema を参照するようにして、リクエストとレスポンスを別々に定義できるようにしています。

以下は schema の書き方です。
まずはシンプルな方式から。

/**
 * @OA\Schema(
 *   schema="user_responder",
 *   required={"id", "name", "email", "created_at"},
 *   @OA\Property(
 *     property="id",
 *     type="integer",
 *     description="ユーザID",
 *     example="1"
 *   ),
 *   @OA\Property(
 *     property="name",
 *     type="string",
 *     description="ユーザの名前",
 *     example="サンプル太郎"
 *   ),
 *   ~その他フィールド略。追加する場合にはカンマを忘れがちなのでお気をつけて~
 * )
 */

クラスやフィールドに寄り添った書き方。分解して書くことができます。

/**
 * @OA\Schema(
 *   schema="user_responder",
 *   required={"id", "name"}
 * )
 */
class UserResponder extends BaseResponder
{
    /**
     * @OA\Property(
     *     property="id",
     *     type="integer",
     *     description="ユーザID",
     *     example="1"
     * ),
     */
    private $id;

    /**
     * @OA\Property(
     *     property="name",
     *     type="string",
     *     description="ユーザの名前",
     *     example="サンプル太郎"
     * ),
     */
    private $name;

required はそれぞれのプロパティに書くのではなくて、schemaに定義します。

配列を含むannotation

出力例

{
  "news": [
    {
      "id": 5,
      "title": "Synergy Night Fever 2019 ──国内ベンチャーシーンを牽引する経営者3名とM&Aについて語る イベントレポート",
      "created_at": "2019-08-26T11:01:38+09:00"
    },
    {
      "id": 4,
      "title": "テスト",
      "created_at": "2019-07-31T10:41:21+09:00"
    },
  ]
}

annotation

    /**
     * @OA\Get(
     *   tags={"Media"},
     *   path="/api/news",
     *   @OA\Response(
     *       response="200",
     *       description="success",
     *       @OA\JsonContent(ref="#/components/schemas/news_list_responder")
     *   ),
     * )
     */

呼び出される schema は以下のようになります。

/**
 * @OA\Schema(
 *     schema="news_summary",
 *     required={"id", "title", "created_at"},
 *     @OA\Property(property="id", type="integer", example=1),
 *     @OA\Property(property="title", type="string", example="タイトル"),
 *     @OA\Property(property="created_at", type="string", example="2020-01-17T11:25:28+09:00"),
 * )
 */
/**
 * @OA\Schema(
 *   schema="news_list_responder",
 * )
 */
class NewsListResponder extends BaseResponder
{
    /**
     * @OA\Property(
     *     property="news",
     *     type="array",
     *     @OA\Items(
     *       ref="#/components/schemas/news_summary"
     *     ),
     * )
     */
    private $news;

ちょっと複雑ですが、要するに、まずは list の schema を呼び出して、property が配列なので、さらに別のschemaを呼び出しています。
array type の property の中で schema を定義せず全て子供の property を定義することも試したのですが、それは動きませんでした。ちょっとハマりどころ。

キーに対してオブジェクトを指定するannotation

出力例

{
  "number_of_people_options": {
    "1": "~5人",
    "2": "5~10人"
  },
  "headquarter_location_options": {
    "1": "北海道",
    "2": "青森県"
  }
}

annotation

    /**
     * @OA\Get(
     *   tags={"Common"},
     *   path="/api/options/info",
     *   @OA\Response(
     *       response="200",
     *       description="success",
     *       @OA\JsonContent(ref="#/components/schemas/info_options_responder")
     *   ),
     * )
     */
/**
 * @OA\Schema(
 *   schema="info_options_responder",
 *   type="object",
 *   required={"number_of_people_options", "headquarter_location_options"}
 * )
 */
class InfoOptionsResponder extends BaseResponder
{
    /**
     * @OA\Property(
     *   property="number_of_people_options",
     *   type="object",
     *   example={1: "~5人", 2: "5~10人"}
     * ),
     */
    private $numberOfPeopleOptions;

    /**
     * @OA\Property(
     *   property="headquarter_location_options",
     *   type="object",
     *   example={1: "北海道", 2: "青森県"}
     * ),
     */
    private $headquarterLocationOptions;

schema においては object type を使用します。property の object の key value が固定であればさらに定義できますが、このケースのように固定じゃない場合には array が使えるかもしれません(この形は本運用でまだ使えていないので今後の宿題にして、かけたら更新します)。

終わりに

書き慣れるまでなかなか辛いです。慣れてしまうとパターンも少ないので案外サクサクかけます。

このannotationを使ったdocumentから実際のAPIレスポンスをテストできるのですが、それについては他の記事で書こうと思います。

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

swagger-php で書く Annotation テンプレ3種

この記事は、温かみのある手作業で swagger-php の annotation を書かなければいけない人向けに、コピペで使えるannotationを提供する目的でまとめます。

単なる key value 表現のannotation

出力例

{
  "id": "1",
  "name": "サンプル太郎",
  "email": "example@hoge.com",
  "created_at": "2006-04-13T14:12:53+09:00"
}

annotation

    /**
     * @OA\Get(
     *   tags={"Common"},
     *   path="/api/user",
     *   @OA\Response(
     *       response="200",
     *       description="success",
     *       @OA\JsonContent(ref="#/components/schemas/user_responder")
     *   ),
     *   @OA\Response(
     *       response="204",
     *       description="there is no authorized user",
     *       @OA\JsonContent(ref="#/components/schemas/204_no_content")
     *   )
     * )
     */

tags は swagger-ui で見るときに整理されて見えるので便利のためにつけてます。
Response については別のところで定義した schema を参照するようにして、リクエストとレスポンスを別々に定義できるようにしています。

以下は schema の書き方です。
まずはシンプルな方式から。

/**
 * @OA\Schema(
 *   schema="user_responder",
 *   required={"id", "name", "email", "created_at"},
 *   @OA\Property(
 *     property="id",
 *     type="integer",
 *     description="ユーザID",
 *     example="1"
 *   ),
 *   @OA\Property(
 *     property="name",
 *     type="string",
 *     description="ユーザの名前",
 *     example="サンプル太郎"
 *   ),
 *   ~その他フィールド略。追加する場合にはカンマを忘れがちなのでお気をつけて~
 * )
 */

クラスやフィールドに寄り添った書き方。分解して書くことができます。

/**
 * @OA\Schema(
 *   schema="user_responder",
 *   required={"id", "name"}
 * )
 */
class UserResponder extends BaseResponder
{
    /**
     * @OA\Property(
     *     property="id",
     *     type="integer",
     *     description="ユーザID",
     *     example="1"
     * ),
     */
    private $id;

    /**
     * @OA\Property(
     *     property="name",
     *     type="string",
     *     description="ユーザの名前",
     *     example="サンプル太郎"
     * ),
     */
    private $name;

required はそれぞれのプロパティに書くのではなくて、schemaに定義します。

配列を含むannotation

出力例

{
  "news": [
    {
      "id": 5,
      "title": "Synergy Night Fever 2019 ──国内ベンチャーシーンを牽引する経営者3名とM&Aについて語る イベントレポート",
      "created_at": "2019-08-26T11:01:38+09:00"
    },
    {
      "id": 4,
      "title": "テスト",
      "created_at": "2019-07-31T10:41:21+09:00"
    },
  ]
}

annotation

    /**
     * @OA\Get(
     *   tags={"Media"},
     *   path="/api/news",
     *   @OA\Response(
     *       response="200",
     *       description="success",
     *       @OA\JsonContent(ref="#/components/schemas/news_list_responder")
     *   ),
     * )
     */

呼び出される schema は以下のようになります。

/**
 * @OA\Schema(
 *     schema="news_summary",
 *     required={"id", "title", "created_at"},
 *     @OA\Property(property="id", type="integer", example=1),
 *     @OA\Property(property="title", type="string", example="タイトル"),
 *     @OA\Property(property="created_at", type="string", example="2020-01-17T11:25:28+09:00"),
 * )
 */
/**
 * @OA\Schema(
 *   schema="news_list_responder",
 * )
 */
class NewsListResponder extends BaseResponder
{
    /**
     * @OA\Property(
     *     property="news",
     *     type="array",
     *     @OA\Items(
     *       ref="#/components/schemas/news_summary"
     *     ),
     * )
     */
    private $news;

ちょっと複雑ですが、要するに、まずは list の schema を呼び出して、property が配列なので、さらに別のschemaを呼び出しています。
array type の property の中で schema を定義せず全て子供の property を定義することも試したのですが、それは動きませんでした。ちょっとハマりどころ。

キーに対してオブジェクトを指定するannotation

出力例

{
  "number_of_people_options": {
    "1": "~5人",
    "2": "5~10人"
  },
  "headquarter_location_options": {
    "1": "北海道",
    "2": "青森県"
  }
}

annotation

    /**
     * @OA\Get(
     *   tags={"Common"},
     *   path="/api/options/info",
     *   @OA\Response(
     *       response="200",
     *       description="success",
     *       @OA\JsonContent(ref="#/components/schemas/info_options_responder")
     *   ),
     * )
     */
/**
 * @OA\Schema(
 *   schema="info_options_responder",
 *   type="object",
 *   required={"number_of_people_options", "headquarter_location_options"}
 * )
 */
class InfoOptionsResponder extends BaseResponder
{
    /**
     * @OA\Property(
     *   property="number_of_people_options",
     *   type="object",
     *   example={1: "~5人", 2: "5~10人"}
     * ),
     */
    private $numberOfPeopleOptions;

    /**
     * @OA\Property(
     *   property="headquarter_location_options",
     *   type="object",
     *   example={1: "北海道", 2: "青森県"}
     * ),
     */
    private $headquarterLocationOptions;

schema においては object type を使用します。property の object の key value が固定であればさらに定義できますが、このケースのように固定じゃない場合には array が使えるかもしれません(この形は本運用でまだ使えていないので今後の宿題にして、かけたら更新します)。

終わりに

書き慣れるまでなかなか辛いです。慣れてしまうとパターンも少ないので案外サクサクかけます。

このannotationを使ったdocumentから実際のAPIレスポンスをテストできるのですが、それについては他の記事で書こうと思います。

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

【CMS】ローカル環境でJS CMSをお試しする

最近WordPress、いやだなあ~なんて思ってます。
更新通知メール多いのもなんですけど。
ブロック配置のところが分かりにくいのでメリットがまるで生かせてません。
WIXとかJIMDOとかだと重い上に細かいCSSカスタマイズが出来ないのでもだもだします。

正直、静的サイトドーン! でもいいなあと思って、
改めてCMSツールを調べたところ「JS CMS」なるものを発見。

・DBレス
・リアルタイムレイアウト
・完全無料
という謳い文句に惹かれていざいざお試ししてみます!
……ローカル環境で。

JS CMS公式サイト
(公式にもローカル環境の手引きがあるんですけど、それとは違う方法です)

本体とテンプレートをDL

JS CMSは本体とテンプレートをセットでダウンロードします。
敢えて嫌な感じに言うと、一度落としたらテンプレートは変更できません。
とは言え痒い所はHTMLとかCSSいじったりすればいいだけなのでモーマンタイ。

ダウンロードページ

そんなこんなで適当なところに解凍。
index.htmlがあるので、実はこれだけでもデモサイトが見れます。
全然実はじゃないけど。
でもブラウザで弄りたいので、それは後回し。

環境をささっと整える

参考:PHPのダウンロードとインストール - Windows環境

JS CMSはPHPだけで動いてるので、PHPだけ入れれば自前の環境でも動かせます。
静的ジェネレーターじゃないので、あくまでちょっと動作確認したいって時だけのほうがいいと思います。
……静的ファイルは生み出す点では否定は出来ませんが。

公式サイトによると「PHP4.3以上」が条件のようです。(2020/03/16現在)
なので、ver4.3以上のPHPを入れます。
 

配布ページから適当なWindows向けPHPをDL(今回は7.3.15)
②Cドライブ直下にzipを解凍し、フォルダ名を「PHP」に変更
③PHPフォルダにある「php.ini-production」ファイルをコピーし、「php.ini」というファイル名で上書き保存
④エクスプローラーのPCを右クリック→プロパティ→システムの詳細設定→環境変数に移動
⑤Path→新規をクリックしてから、C:\PHPと入力してOK
⑥コマンドプロンプトを起動し、「php -v」と入力して、以下のような画面が出たらOK
image.png

これでPHPが入りました。
文字だけの説明になってしまったので、画像で詳しく見たい方は上記の参考サイトまで。
CMSって(多分)複雑だと思うので、PHP一本で動かせるのってレアな気がします。
他のCMSになるとDB入れたりNode入れたりしそうなので、今回のは今更ながらアプリ依存な手法かと。

まずローカルで試すなって話ですかね!!!

localhostを設置

参考:指定フォルダを簡単に localhost でアクセスできるようにする

さあ本題。
PHPを入れても、そのままじゃPHPファイルはブラウザでは見れません。
結論から言うと「http://」から始まらないとダメっぽいです。
なので力業……でもないですが、ローカルサーバを起動してなんとかします。

①参考サイトに載っているソースをコピー
②JS CMSのフォルダ内に「local.txt」というファイルを作成し、コピーしたソースをペースト
③_local.txtを閉じてから、「
local.txt」を「_local.bat」という名前にリネーム

これで準備は完了です。
このバッチファイルを叩けば、現在地のフォルダがローカルサーバとして立ち上がる? ようなかんじ。
コマンド叩くよりバッチのほうがいいなあって思ったのでこんなかんじです。

ちなみにでもないですが、バッチ叩くとポート番号入力画面が出ますけども、
入力せずにエンター押せばデフォルトで設定したポート番号(何もしていなければ8080)が設定されます。
ので、どのポート番号が良いのやらってなっている人はエンターだけ押せばいいと思います。
自分だ!

いざいざ!

バッチを叩いてからhttp://localhost:8000/_cms/にアクセスしてみます。
こんなかんじの画面が出たら成功!
image.png

ちなみにログインIDとパスワードはデフォルトで「guest」になっています。
変更したいときは/_cms/setting/setting.phpの該当欄をいじれば良いです。

あとは存分にローカルで弄り倒して下さい。
WordPressより楽しいですよ!(当社比)

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

変数の名前を付けるときに、絶対パスを格納していることを明記したい場合はabs_がよさげ

はじめに

相対パスではなく、絶対パスを変数に格納してほしい場合がしばしば生じます。
その際今まで私は、

$setting_json_full_path

とかの名前を利用していました

abs

$abs_setting_json_path

とか、

$abs_ubuntu_iso

とかの方が文字数も少なく、見た目もスッキリする上、意味もしっかり伝わるのでよいなと思った次第です。特に出典はありません。

absabsolute path、絶対パスの略称です。

突き詰めると好みの問題になりそうですが、absを使っていこうと思った次第でした。1


  1. 一番ベストなのは、参加したプロジェクトに合わせて使い分けることですね 

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

WSL2+docker+PHPのWindows開発環境構築(3) PHPStorm編

本ページに直接来た方はWSL2+docker+PHPのWindows開発環境構築(1) WSL2編から読んでね。

ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪


------------------- ↓ 余談はここから ↓-------------------

関連記事:

前回docker起動までいけた。
あとはPHPStormと繋げれば良い。

('ω')ノ あとすこしやで


------------------- ↓ 本題はここから ↓-------------------

Dockerの調整

タスクバーのdockerアイコンから「setting」を選択
以下にチェックを入れて「Appli&Restart」

  • Expose daemon on tcp://localhost:2375 without TLS

キャプチャ-202003091735.JPG

PHPStormの調整

Pluginのインストール

兎にも角にもプラグイン。
DockerPHP Dockerをインストール

[File]-[Setting]-[Plugins]から以下の二つをインストール

  • Docker
  • PHP Docker

キャプチャ-202003091743.JPG

(PHP Remote Interpreterってのも一緒に入る)

Docker Pluginの設定

「Build, Execution, Deployment」-「Docker」-「+」を押下
「TCP socker」にチェックを入れて「OK」を押下

キャプチャ-202003091744.JPG

PHP Pluginの設定

「Languages & Frameworks」-「PHP」-「Cli Interpreter」-「...」を押下

キャプチャ-202003091751.JPG

「Cli Interpreters」欄の「+」を押下、
「From Docker, Vagrant, Vm, WSL, Remote...」を押下する。

キャプチャ-202003091755.JPG

「Image Name」欄の「▼」を押し、
「laradock_php-fpm:latest」を選択

キャプチャ-202003141546.JPG

コード補完が効いていたら成功だ。
これで実際の開発に入ることができるだろう。
(゜-゜) こんなに頑張らないと物作れないってどうなんだろ・・・。

このあとGitやらXdebugやら使うことになると思うが、
それは一般的なものなので今回は省く。
(過去記事のどれかでやったっけな。)


------------------- ↓ 後書はここから ↓-------------------
これだけやって、
ようやく使えるDockerってどうなの?
(ワイだけかな)
まぁ、AWSのデプロイ考えたらdockerなのかなぁ。
ほかの方法だとイメージを量産する感じになっちゃうし。
環境を作るって観点だけで物事を考えたらいかんか。

今回はlaradockでやったけど、
これがなければ環境作りだけで時間を食い潰してただろうな。
いまいちDocker Hubの扱い方がよくわからない。

MySQLが起動しない

PHPとは関係ないが、
Dockerがらみ。
DockerコンテナでMySQLだけが起動しない。

$ docker-compose up -d --build mysql

シーン・・・。

(?_?) アレ?
ログ見てみよう。

2020-03-14 18:48:39+09:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.19-1debian10 started.
2020-03-14 18:48:39+09:00 [Note] [Entrypoint]: Initializing database files
2020-03-14T09:48:39.973002Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.
2020-03-14T09:48:39.973444Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.19) initializing of server in progress as process 22
2020-03-14T09:48:39.986553Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
mysqld: Cannot change permissions of the file 'ca.pem' (OS errno 1 - Operation not permitted)
2020-03-14T09:48:45.126054Z 0 [ERROR] [MY-010295] [Server] Could not set file permission for ca.pem
2020-03-14T09:48:45.126403Z 0 [ERROR] [MY-013236] [Server] The designated data directory /var/lib/mysql/ is unusable. You can remove all files that the server added to it.
2020-03-14T09:48:45.126758Z 0 [ERROR] [MY-010119] [Server] Aborting
2020-03-14T09:48:46.659592Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.19) MySQL Community Server - GPL.

|ω・) ナニコレ

データディレクトリをいったん削除してもう一回起動

2020-03-14 18:48:39+09:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.19-1debian10 started.
2020-03-14 18:48:39+09:00 [Note] [Entrypoint]: Initializing database files
2020-03-14T09:48:39.973002Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.
2020-03-14T09:48:39.973444Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.19) initializing of server in progress as process 22
2020-03-14T09:48:39.986553Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
mysqld: Cannot change permissions of the file 'ca.pem' (OS errno 1 - Operation not permitted)
2020-03-14T09:48:45.126054Z 0 [ERROR] [MY-010295] [Server] Could not set file permission for ca.pem
2020-03-14T09:48:45.126403Z 0 [ERROR] [MY-013236] [Server] The designated data directory /var/lib/mysql/ is unusable. You can remove all files that the server added to it.
2020-03-14T09:48:45.126758Z 0 [ERROR] [MY-010119] [Server] Aborting
2020-03-14T09:48:46.659592Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.19) MySQL Community Server - GPL.
2020-03-14 18:53:21+09:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.19-1debian10 started.
2020-03-14 18:53:21+09:00 [Note] [Entrypoint]: Initializing database files
2020-03-14T09:53:21.968144Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.
2020-03-14T09:53:21.969067Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.19) initializing of server in progress as process 22
2020-03-14T09:53:21.987587Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
2020-03-14T09:53:27.708440Z 0 [ERROR] [MY-010295] [Server] Could not set file permission for ca.pem
2020-03-14T09:53:27.708719Z 0 [ERROR] [MY-013236] [Server] The designated data directory /var/lib/mysql/ is unusable. You can remove all files that the server added to it.
2020-03-14T09:53:27.709077Z 0 [ERROR] [MY-010119] [Server] Aborting
2020-03-14T09:53:29.169116Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.19) MySQL Community Server - GPL.

( ゚Д゚)ハァ? 余計悪化した。。。
ちょっと掘り下げてみるか。。。

permissionって書いてあるから権限回りだろう・・・( ゚д゚)ハッ!
そういえばこのDocker設定作ったのはMac野郎だった。

docker-compose.yml
  mysql:
    image: mysql:8.0
    ports:
      - 3306:3306
    user: "500:500"
    volumes:
・・・・

やっぱり。
WSL上のuserIDとdocker上のuserIDがあってない。
WSL上のUIDを確認してみよう。

C:\> wsl
$ id
uid=1000(dozo) gid=1000(dozo) groups=1000(dozo),・・・

docker-compose.ymlを調整

docker-compose.yml
  mysql:
    image: mysql:8.0
    ports:
      - 3306:3306
    user: "1000:1000"
    volumes:
・・・・

Mysqlのデータを全削除。
イメージを削除して、コンテナを再構成

$ rm -Rf /mnt/c/Users/magic/mysql/data/*
$ docker rm bc57ea450000
bc57ea450000
$ docker rmi 9b51d9270000
Untagged: mysql:8.0
Untagged: mysql@sha256:4a30434ce03d2fa39
・・・
79e9d07a19e3a8d49010ab9c98a2c348fa116c87
$ docker-compose up -d --build mysql
Creating laradock_mysql_1 ... done

直った・・・。

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

【個人開発】ゲージの画像を作るサービスをリリースした

個人開発のサービス まいゲージをリリースしました。

ゲージの画像を作るサービスです。

12.png

作るときに考えたこと

やっぱり、無名の人が頑張っても人気にはならないわけで、有名にするにはSNSを使う必要があります。

ツイートボタンとかを用意して、投稿されたツイートがクリックされるように、twitter cardを使いました。

もともと、ダウンロードさせて自分で画像添付にしようかと思ったけど、手間がかかって途中で諦める人が多くなるので却下。
あと、「リンクが広告臭いのがいやだ」って消される可能性もあるし、、

Twitterカードの失敗

Twitterカードのメタタグをつけて、何回ツイートしても、Twitterカードがでませんでした。

理由はカードがBASE64に対応をしていなかったからです。

file_put_contentsを使って画像にしたら、無事表示されました。

使用言語

JavaScript

表示部分は、JSのCanvasを使っています。
ゲージ部は、くけいで表示しています。

PHP

画像を保存したりする部分です。
後々ログイン処理をすることも考えて、全ページphpにしてあります。

ライブラリーなど

jQuery

これメインで使う というよりは、このあと紹介するライブラリで必要なので入ってます。

spectrum

カラーピッカーです。input colorよりも使い勝手が良さそうでした。

サービスが作りたい人へ

質より量です。たくさん作って公開しましょう。
アイデアについてですが、すでにあるもの+α でもそれっぽくなります。

診断メーカー + 絵を書く でできた(と思われる)作品もありますよね。
とりあえず 作ってアップ、作ってアップ を繰り返してください。

ですが、毎回別ドメインを用意してたら財布が泣くので、同じドメインのサブドメインやディレクトリにしましょう。

人気が出てきたら、ドメインをとってそれにリダイレクト。

最後に

ぜひまいゲージ使ってみてください。

クリックするとサイトに飛びます。

最後まで読んでいただき、ありがとうございました。

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

Wordpress プラグインを使わずカスタムMetaBoxを作成する方法

metaboxはカスタムフィールドの強化版みたいな感じ。デフォルトのカスタムフィールドはkeyに対して値を入力するだけだが、metaboxを使うことでカレンダーや画像の選択、セレクトボックスなどのフォームを利用できるようになる。

一番簡単に実装するなら以下のようなプラグインを使う。ここではプラグインを使わず実装する方法をまとめる。

カスタムMetaBoxの作り方

metaboxを作るのに必要なのは3つの関数。1つのmetaboxで複数のフォームを作成することも可能。

  • add: metaboxの定義
  • save: データの保存
  • html: フォームの定義
function my_custom_meta_box_add()
{
  add_meta_box(
        'post_meta_box_id',          // Unique ID
        'メタボックスのタイトル',     // タイトル
        'my_custom_meta_box_html',   // フォーム関数の呼び出し
        'post',                 // 投稿タイプ
    'default'         // 表示する位置
    );
}

function my_custom_meta_box_save($post_id)
{
  if (array_key_exists('my_custom_meta_box_field', $_POST)) {
    update_post_meta(
      $post_id,
      'my_custom_meta_box_key',
      $_POST['my_custom_meta_box_field']
    );
  }
}

function my_custom_meta_box_html($post)
{
  $value = get_post_meta($post->ID, 'my_custom_meta_box_key', true);
  ?>
  <label for="my_custom_meta_box_field">メタボックスのラベル</label>
  <select name="my_custom_meta_box_field" id="my_custom_meta_box_field" class="postbox">
    <option value="">カラーの選択</option>
    <option value="red" <?php selected($value, 'red'); ?>>Red</option>
    <option value="green" <?php selected($value, 'green'); ?>>Green</option>
  </select>
  <?php
}

// metaboxの定義
add_action('add_meta_boxes', 'my_custom_meta_box_add');
// metaboxのデータ保存
add_action('save_post', 'my_custom_meta_box_save');

カスタムMetaBoxのフォームの表示と保存

add_meta_box()で定義した投稿タイプに自動的に表示される。

metabox-1.png

表示する位置はデフォルトでカスタムフィールドの下、sideに設定すると、カテゴリやアイキャッチのあるサイドバーに表示される。

データはfunctions.phpでsave_postのフックを入れておくことで、記事を保存したり更新したりした際に一緒に保存されるようになる。

カスタムMetaBoxのデータをテンプレートに表示

テンプレートにmetaboxのデータを表示するには、カスタムフィールドと同じ方法で良い。

get_post_meta($post->ID, 'my_custom_meta_box_key', true);

記事ページでの実装例

<ul class="nav">
  <li>投稿日: <?php echo get_the_date('Y-m-d'); ?></li>
  <li>カラー: <?php echo get_post_meta($post->ID, 'my_custom_meta_box_key', true); ?></li>
</ul>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む