MW WP Formで登録後に自動で投稿する方法
WordPressのフォーム登録プラグイン「MW WP Form」を使って、登録後に自動で投稿する方法を紹介します。
この記事では、登録フォームの設定方法は割愛し、登録後の自動登録の部分のみ説明します。
環境
WordPress 5.2.4
MW WP Form 4.2.0
任意のテーマ
変更箇所
以下に記載のコードを使用中のテーマにある「function.php」に追加します。
フォームで使用するカスタムフィールドを定義する
管理画面の投稿登録画面に登録フォームで使用するカスタムフィールドの入力欄を追加します。
これを設定することで、投稿時に毎回プルダウンからカスタムフィールドを選択する手間が省かれます。
/** * 投稿画面で表示するカスタムフィールドのHTMLを定義します。 * 第2引数で独自の引数を設定することで、textareaまたはtextを生成するようにしています。 */ function write_html($post, $args) { $field_nm = $args['args'][0]; $type = $args['args'][1]; if ($type == 'textarea') { echo '<textarea name="' . $field_nm . '" style="width: 100%; height: 200px;">' . get_post_meta($post->ID, $field_nm, true) . '</textarea>'; } if ($type == 'text') { echo '<input type="text" name="' . $field_nm . '" style="width: 100%;" value="' . get_post_meta($post->ID, $field_nm, true) . '"/>'; } wp_nonce_field( 'send_field1' , 'nonce_for_field_1' ); } /** * 投稿画面にカスタムフィールドを表示します。 * 最後の引数に配列で独自の引数を設定することができます。 */ function add_custom_meta_box() { // 第1引数:項目ごとのdivタグにつくid名(被らないように任意の値) // 第2引数:登録フォームの各入力項目のname // 第3引数:HTMLを生成するコールバック名 // 第4引数:適用するページの種別(postで) // 第5引数:メタボックスの種別(初期値:advanced) // 第6引数:メタボックスの優先度(初期値:default) // 第7引数:第3引数のコールバックで使う任意の引数(必要であればarrayで定義) add_meta_box('custom_field_1','氏名','write_html','post','advanced','default',array('氏名','text')); add_meta_box('custom_field_2','メールアドレス','write_html','post','advanced','default',array('メールアドレス','text')); } add_action('admin_menu', 'add_custom_meta_box');
フォーム登録後に投稿する
MW WP Formで作成した登録フォームからデータが登録されたら、投稿するようにします。
処理内容は、投稿を新規登録し、カスタムフィールドを別テーブルに登録します。
function update_meta_posts($Mail_admin, $Data) { // 登録フォームから入力データを取得 $form_data = $Data->getInstance(); // 投稿新規データを作成(タイトルと公開状態の2つの最低限) $post = array( 'post_title' => $form_data->get('募集タイトル'), 'post_status' => 'publish' ); // 上記データで投稿を新規登録 $post_id = wp_insert_post($post, true); // 登録フォームのカスタムフィールドを別テーブルに登録 update_post_meta($post_id, '氏名', $form_data->get('氏名')); update_post_meta($post_id, 'メールアドレス', $form_data->get('メールアドレス')); } // アクションフックを追加 // 第1引数:末尾の数字は、登録フォーム作成時のショートコードを設定 // 第2引数:フック実行時の処理 // 第3・4引数:説明がないので用途は不明(固定値??) add_action('mwform_before_send_admin_mail_mw-wp-form-8', 'update_meta_posts', 10, 2);
参考サイト
mwform_before_send_admin_mail_mw-wp-form-xxx | MW WP Form
- 作者: 野島祐慈,菱川拓郎,杉田知至,細谷崇,枢木くっくる
- 出版社/メーカー: 技術評論社
- 発売日: 2017/01/26
- メディア: Kindle版
- この商品を含むブログを見る
LINQでグルーピングした最大の要素を取得する
C#でグルーピングして最大の要素を取得したかったので、試行錯誤して調べた結果、Max
ではなくOrderByDescending
を使うことで実現できました。
まだまだLINQは、使い慣れてないのでちょっと特殊なことをしようとするとハマって時間が取られてしまいました…。そんなんでお困りの方、ご参考に。
少し解説すると、以下のようになります。
GroupBy
・第1引数:元の値を何でグループ化するかを指定する
・第2引数:元の値をグループ化したものに対して、キーと値の2つの引数が使え、値に対しての処理を指定する
OrderByDescending
元の値を第1引数で指定したもので昇順に並べ、First
を指定することで先頭を取得する
サンプルコード
// 値を持つクラス public class Hoge { public int Key { get; set; } public string Dt { get; set; } } // グルーピングして最大を取得する処理 public void Main(string[] args) { // 値の設定 List<Hoge> list = new List<Hoge> { new Hoge() { Key = 1, Dt = "20190101" }, new Hoge() { Key = 1, Dt = "20190102" }, new Hoge() { Key = 2, Dt = "20190101" }, new Hoge() { Key = 3, Dt = "20190310" }, new Hoge() { Key = 3, Dt = "20190305" }, new Hoge() { Key = 3, Dt = "20190301" }, new Hoge() { Key = 4, Dt = "20190101" }, new Hoge() { Key = 4, Dt = "20190102" }, new Hoge() { Key = 5, Dt = "20190103" }, }; // Key毎にDtが最大の要素を取得 List<Hoge> retList = list .GroupBy( h => h.Key, (k, v) => v.OrderByDescending(o => o.Dt).First()) .ToList(); // 結果 retList.ForEach(f => Console.WriteLine("{0} {1}", f.Key, f.Dt)); }
結果
1 20190102 2 20190101 3 20190310 4 20190102 5 20190103
Key毎にDtが最大の要素がListに格納されています。
WildFlyでgetResourceするとパスが異なる事例と対処方法
GlassFishで動作していたSpringBootアプリを、サーバー移管に伴いWildFlyに切り替えました。
動作確認をしていくと、リソースの取得で404が返ってきて困っていました。
いろいろと調査すると、パスの取得方法がアプリケーション・サーバーによって異なることがあるらしく、その場合の対処方法をまとめました。
WilfFly上での問題の挙動
GlassFishでは、アプリをWAR形式でデプロイし動作させていました。
WildFlyでも同じようにして動作させていたのですが、Excelを出力する処理で、404が発生し原因を調査することにしました。
GlassFishでは、次のコードで正常に動作していました。
new File(this.getClass().getResource(srcFullPath).getPath());
このコードのままWildFlyで処理を行うと変なパスが返ってきます。
(ローカルでWARデプロイしたとき)
# getResourceで引数に「"."」を指定した場合 /Users/user_name/dev/eclipse/server/wildfly-15/modules/system/layers/base/org/jboss/as/ejb3/main/timers/ # getResourceで引数に「"report"」のパスを指定した場合 /content/Hoge.war/WEB-INF/classes/com/test/report/
いろいろと調べてみる
解決しないとマズイ問題なのでめちゃくちゃ調べました。
How to put an external file in the classpath |JBoss Developer
java - WildFly - getting resource from WAR - Stack Overflow
How to load a file in war file |JBoss Developer
How to load external property file in JBoss 7 classpath? - JBoss 7 Configurations
基本、英語のサイトしかヒットしないのでGoogle翻訳を駆使したり、コードから読み取ったりしてました。
サイトには、「それは解決できないよ」と絶望的な回答があったり、「この方法はどう?」と試すものの的外れだったりで、困り果ててました。
そんな中、「解決方法はこれ!」というのがあり、試すと問題なく動作するものがありました!!
解決方法
java - How to load resource files in jboss war - wildfly9.xV - Stack Overflow
getResource()
でFileを取得するのではなく、getResourceAsStream()
でStreamを取得して使えとのこと。
this.getClass().getResourceAsStream(path);
これですんなりExcelを出力できるようになりました。
Postfixで独自ドメイン用の送信メールサーバーを構築する
Webサービス等の開発でメールを送信することがあると思います。
リリースにあたり独自ドメインも取得してメールを送信すると思いますが、メールサーバーを構築したり、メールボックスを契約するのは手間や費用がかかり大変です。
それらのことをやらなくても、メールを受信したら転送するだけの仕組みがPostfixで可能だったので、それらについてまとめました。
メール送信するにあたり、キャリアメール(docomo、au、softbank等)の送信制限対策の設定も記載しましたので、ご活用下さい。
前提条件
独自ドメインを取得していること
今回構築するPostfixの仕様
・独自ドメイン宛のメールは、Postfixで受信し、それを指定のメールアドレスにそのまま転送する
・プログラムからのメール送信は、Postfixを経由してダイレクトに送信される
・プログラムからのキャリアへのメール送信は、Postfixで送信間隔を考慮して送信される
・プログラムからのメールは、暗号化して送信される(TLS設定をした場合)
独自ドメインにSPFレコードを設定する
SPFレコードとは?
独自ドメインのよるメール送信が、迷惑メール扱いとならないようにドメインの設定でSPFレコードを追加します。
SPFの詳細については以下のリンクを参考にして下さい。
salt.iajapan.org
ドメイン設定でSPFレコードを登録する
SPFレコードは、ドメインを取得したサイトにいって「DNSレコード設定」等のメニューで行います。
設定する値は、以下の表のようになります。
(独自ドメイン「hoge.com」メール送信するサーバーIP「192.168.0.1」の場合)
ホスト名 | TYPE | TTL | VALUE | 補足 |
mail.hoge.com | A | 3600 | 192.168.0.1 | すでにあれば不要 |
hoge.com | TXT | 3600 | v=spf1 a:mail.hoge.com ~all | 上記のホスト名を指定 |
TTLは任意の値で大丈夫です。
SPFレコードが有効か確認する
設定が終わったら、しばらく時間をおいて次のサイトでSPFレコードが有効になったか確認します。グリーンの表示ならOKです。
Sender Policy Framework (SPF) Record Lookup - SPF Check - MxToolBox
送信メールサーバーの設定
/etc/postfix/main.cf
# メール受信許可範囲(変更) inet_interfaces = all # 接続時に使うプロトコル(変更) net_protocols = ipv4 ## 配送設定 # 遅延メッセージの配送を試行する最小時間間隔 minimal_backoff_time=1m # 遅延メッセージの配送を試行する最大時間間隔 maximal_backoff_time=10m # 配送できないものとして送り返すまでに、メッセージがキューに入っている最大時間 maximal_queue_lifetime=1h # 配送できないと見なすまでに、バウンスメッセージがキューに入っている最大時間 bounce_queue_lifetime=1h # 遅延されたキューがキューマネージャによってスキャンされる時間間隔 queue_run_delay=30s # 配送経路ファイルパス transport_maps = hash:/etc/postfix/transport ## バーチャルドメイン # バーチャルドメイン virtual_alias_domains = hoge.com # バーチャルドメイン設定ファイルパス virtual_alias_maps = hash:/etc/postfix/virtual ## STARTTLSの設定(メールが暗号化される) # SMTP TLSセキュリティレベル smtp_tls_security_level = may # CAファイルのパス(Let's Encryptを使った場合) smtp_tls_CAfile = /etc/letsencrypt/live/hoge.com/cert.pem # TLS情報をログに出力 smtp_tls_loglevel = 1
/etc/postfix/virtual
hoge.com anything # 必須 # 独自ドメイン宛メールを別アドレスに転送する info@hoge.com hoge@gmail.com noreplay@hoge.com hoge@gmail.com
ハッシュ化する
postmap /etc/postfix/virtual
キャリアメールの送信制限対策の設定
キャリアメールの送信制限
キャリアメールの送信制限について調べたところ、表のような感じになりました。
内容が古いかもしれないので、間違っている場合はご指摘頂ければうれしいです。
1セッション同時送信 | 1日最大送信 | |
docomo | 100件 | 1,000通 |
au | 30件 | 1,000通 |
softbank | 20件 | 500通 |
Y!mobile | ???件 | 1,000通 |
キャリアにメールを送信する場合、独自ドメインにSPFレコードを設定することが必須となります。
キャリア毎の制限に引っかかった場合、迷惑メール扱いとなり、メールが届かなくなるので注意して下さい。
各キャリア規制についての参考情報
Postfixの設定
/etc/postfix/master.cf
docomo-smtp unix - - n - 1 smtp -o smtp_destination_concurrency_limit=1 -o smtp_destination_recipient_limit=1 au-smtp unix - - n - 1 smtp -o smtp_destination_concurrency_limit=1 -o smtp_destination_recipient_limit=1 softbank-smtp unix - - n - 1 smtp -o smtp_destination_concurrency_limit=1 -o smtp_destination_recipient_limit=1 ymobile-smtp unix - - n - 1 smtp -o smtp_destination_concurrency_limit=1 -o smtp_destination_recipient_limit=1
/etc/postfix/transport
docomo.ne.jp docomo-stmp: ezweb.ne.jp au-smtp: softbank.ne.jp softbank-smtp: .softbank.ne.jp softbank-smtp: .vodafone.ne.jp softbank-smtp: ymobile.ne.jp ymobile-smtp: willcom.com ymobile-smtp:
ハッシュ化する
postmap /etc/postfix/transport
ポートを開ける
SMTPポート(25)を開けます。
sudo firewall-cmd --add-service=smtp --zone=public --permanent
上記設定がおわったらPostfixを再起動します。
sudo systemctl restart postfix
まとめ
今回、Webサービスをリリースするときに、独自ドメインをお名前.comで取得したところ、メールボックスは別で契約しないといけないことが分かり、メール送信をどうするか悩んでいました。
メールボックスを用意するのは、管理が面倒くさいので何か方法はないかと思って調べていると、Postfixだけでメール処理ができることが分かりました。
構築は簡単にできたのですが、できればこれらもしない方が手間も省けるので、独自ドメインを取得するなら、メールサーバー付きのサービスで取得する方が良いと思いました。
お名前.com以外にスタードメインでドメインを管理しているので、スタードメインだとメールサーバー付いてるので、そちらでメール転送設定をすれば、任意のアドレスでメールを受け取れるので手間いらずです。
PostgreSQLでDB間でデータをコピーする
PostgreSQLでDB間またはスキーマー間でpd_dumpを使ってコピーを試みたものの、うまくいきませんでした。
調べているとやり方はあるらしいですが、結局手間がかかり\copyの方が早いらしいのでこれで試してみました。
環境
PostgreSQL 9.4
CentOS 6
Mac 11
コピーの流れ
「コピー元DB:A、コピー先DB:B」とします。
1.AでCSVエクスポート
2.Bでデータ削除
3.BでCSVインポート
4.Bでシーケンス初期化
各項番の説明をしていきます。
1.AでCSVエクスポート
ターミナルで次を実行します。
# 通常接続 psql -h Aのホスト -U Aのユーザー名 -d AのDB名 -c "\copy テーブル名 to '/出力先フルパス/テーブル名.csv' (format csv, delimiter ',', header true);" # SSL接続 psql "sslmode=require host=Aのホスト user=Aのユーザー名 dbname=AのDB名" -c "\copy テーブル名 to '/出力先フルパス/テーブル名.csv' (format csv, delimiter ',', header true);"
2.Bでデータ削除
ターミナルでpsqlコマンドでDBに接続し、次のSQLを流してデータを削除します。
(psql -c "コマンド"で接続しなくてもできます)
TRUNCATE TABLE テーブル名;
3.BでCSVインポート
エクスポートの「to」を「from」に変えるだけです。
ターミナルで次を実行します。
# 通常接続 psql -h Bのホスト -U Bのユーザー名 -d BのDB名 -c "\copy テーブル名 from '/出力先フルパス/テーブル名.csv' (format csv, delimiter ',', header true);" # SSL接続 psql "sslmode=require host=Bのホスト user=Bのユーザー名 dbname=BのDB名" -c "\copy テーブル名 from '/出力先フルパス/テーブル名.csv' (format csv, delimiter ',', header true);"
超絶おすすめするPostgreSQL書籍!!
[改訂新版]内部構造から学ぶPostgreSQL 設計・運用計画の鉄則 (Software Design plus)
- 作者: 勝俣智成,佐伯昌樹,原田登志
- 出版社/メーカー: 技術評論社
- 発売日: 2018/09/14
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
- 作者: 鈴木啓修
- 出版社/メーカー: 技術評論社
- 発売日: 2012/11/16
- メディア: 単行本(ソフトカバー)
- 購入: 2人 クリック: 14回
- この商品を含むブログ (5件) を見る
Gradle 4.x で「Could not resolve all artifacts for configuration」のエラーが出たときの対処方法
個人的にGradleはよく分かってないので突っ込まれると回答できません。ご了承下さい。
※ 一概に「Could not resolve all artifacts for configuration」のエラーが出たら、ここの対処をすれば良いと言うわけではない点にご注意下さい。
環境
Mac
Spring Boot 1.3.6
Gradle 4.9 (Homebrew)
エラー内容
gradle eclipse
等を実行すると以下のエラーが発生する。
* What went wrong: A problem occurred configuring root project 'Test'. > Could not resolve all artifacts for configuration ':classpath'. > Could not find org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}. Required by: project :
build.gradle(一部抜粋)
buildscript { ext { springBootVersion = '1.3.6.RELEASE' } repositories { mavenCentral() } dependencies { classpath 'org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}' // Gradle4対応 classpath 'io.spring.gradle:dependency-management-plugin:0.6.0.RELEASE' } }
対処方法
build.gradle(一部抜粋)
buildscript { ext { springBootVersion = '1.3.6.RELEASE' } repositories { mavenCentral() } dependencies { // 変数ではなく固定値にする classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.3.6.RELEASE' // Gradle4対応 classpath 'io.spring.gradle:dependency-management-plugin:0.6.0.RELEASE' } }
Gradle徹底入門 次世代ビルドツールによる自動化基盤の構築
- 作者: 綿引琢磨,須江信洋,林政利,今井勝信
- 出版社/メーカー: 翔泳社
- 発売日: 2014/11/05
- メディア: 大型本
- この商品を含むブログ (6件) を見る
Spring Boot 1.3.x で Gradle 4.x に更新してビルドするとエラーが出る場合の対処法
Gradleのバーションを久々に更新したら、一部のプロジェクトでエラーが出てました。
その時の対処を紹介します。
エラー内容
gradle eclipse
を実行するとbuild.gradleの15行目でエラーが発生と表示されます。
$ gradle eclipse FAILURE: Build failed with an exception. * Where: Build file '/Users/Applications/eclipse/workspace/Test/build.gradle' line: 15 * What went wrong: A problem occurred evaluating root project 'Test'. > Failed to apply plugin [class 'io.spring.gradle.dependencymanagement.DependencyManagementPlugin'] > Could not create task of type 'DependencyManagementReportTask'. * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 0s
build.gradle
問題の15行目は、apply 'spring-boot'
の宣言です。
buildscript { ext { springBootVersion = '1.3.6.RELEASE' } repositories { mavenCentral() } dependencies { classpath 'org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}' // Gradle4対応 classpath 'io.spring.gradle:dependency-management-plugin:0.6.0.RELEASE' } } apply plugin: 'java' apply plugin: 'eclipse-wtp' apply plugin: 'spring-boot' // line: 15 以下略
対処法
buildscript { ext { springBootVersion = '1.3.6.RELEASE' } repositories { mavenCentral() } dependencies { classpath 'org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}' // 追加 classpath 'io.spring.gradle:dependency-management-plugin:0.6.0.RELEASE' } } apply plugin: 'java' apply plugin: 'eclipse-wtp' apply plugin: 'spring-boot' // 追加 apply plugin: 'io.spring.dependency-management'