JREが複数動いている環境向け。Javaプログラムで、実行しているJREのバージョンを確認する方法。

Java

複数の異なるJREがインストールされているマシン上でJavaアプリケーションを動かす場合、パスの記述方法を誤っていると意図していないJRE上でアプリケーションが動いてしまうことがあります。


アプリケーションで動作保証しているJREのバージョンは決めている事がほとんどなので、動作しているJREのバージョンをきちんと把握しておく事はとても大事です。


今回は、Javaアプリケーション内で、動作しているJREを判別する方法を紹介します。


皆さんは、開発したJavaアプリケーションを動かす場合、Javaアプリケーションを動かすサーバやパソコンにJREをインストールしているかと思います。
その際、環境変数にJREのパスを記述したり、もしくは、Javaアプリケーションの起動シェル(バッチ)にJREのパスを記述したり、といった方法をとっているのではないでしょうか。


単純に、1つのバージョンのJREをインストールし、そのサーバやパソコンで動作するアプリケーションはインストールした1つのバージョンのJRE上で動かす場合は問題ないのですが、例えば、1つのサーバやパソコン内で、あるアプリケーションはJava1.7で動かしたいが、あるアプリケーションはJava1.8で動かしたいといったパターンがまれにあります。


その場合、「本当にこのアプリ、Java1.8で動いてるっけ?」って不安になりませんか?
だって、Javaは2つ入っている訳でありまして。。。


こういう心配性な技術者向けに、Javaプログラム内で参照しているJavaのパスを取得する方法を紹介します。


複数のJREがインストールされている環境


サーバ上で10個のアプリケーションが動かす必要があり、そのうち9個はJava1.7で動かす必要があるが、1個はJava1.8で動かす必要がある、といった場面です。
この場合、ほとんどの人が以下のような方法をとるのではないか?


  • JREは、1.7と1.8の両方をインストールする。
  • 環境変数には、Java1.7のパスを定義する。
  • Java1.8で動かす必要があるアプリについてどうにかする。

環境変数にはJava1.7とJava1.8のパスを両方定義しても無意味です。
参照先パスは、先に見つかった方を採用するので、後に定義したJavaのパスは無視されます


Java1.7が採用される環境変数の記述方法

C:\Program Files\Java\jre1.7\bin;C:\Program Files\Java\jre1.8\bin

Java1.8が採用される環境変数の記述方法

C:\Program Files\Java\jre1.8\bin;C:\Program Files\Java\jre1.7\bin

2つ定義するのは無意味なので、環境変数の定義は以下のように記載するのが正解です。


正しい環境変数の定義

C:\Program Files\Java\jre1.7\bin

Java1.7で動くアプリケーションは上記でいいとして、問題はJava1.8で動かす方です。
王道としてはアプリケーションの起動シェルやバッチにJava1.8のパスを定義する方法がメジャーです。


set PATH=C:\Program Files\Java\jre1.8\bin;%PATH%

%PATH%の前にJava1.8のパスを記載するのがポイントです。


環境変数にはJava1.7のパスが定義されているので、%PATH%の後にJava1.8のパスを記載してしまうとJava1.7の方が採用されてしまいます。%PATH%の前にJava1.8のパスを定義することで、Java1.8の方が採用されます。


本当に意図したJREで動いているか?を確認


動かすアプリケーションに以下の試験プログラムを入れてみて、意図したJavaのパスを参照しているかを確認しましょう。
「System.getProperty」を使います。

public class getProperty {

    public static void main(String[] args){
        System.out.println("sun.boot.library.path=" + 
            System.getProperty("sun.boot.library.path"));
    }
}

実行結果は以下になります。

sun.boot.library.path=C:\Program Files\Java\jre1.8\bin

「sun.boot.library.path」がJavaのパスです。
これが、Java1.8になっていればOK。


Javaのプロパティ情報を出力する


Javaのパスを確認してみましたが、Javaのパス以外にもプロパティ情報が存在します。
以下のプログラムでリスト形式で確認できます。

import java.util.Properties;

public class getProperty2 {

    public static void main(String[] args){
        Properties props = System.getProperties();
        props.list(System.out);
    }
}

実行結果は以下になります。

-- listing properties --
sun.desktop=windows
awt.toolkit=sun.awt.windows.WToolkit
java.specification.version=12
sun.cpu.isalist=amd64
sun.jnu.encoding=MS932
java.class.path=.
java.vm.vendor=Oracle Corporation
sun.arch.data.model=64
user.variant=
java.vendor.url=https://java.oracle.com/
java.vm.specification.version=12
os.name=Windows 7
sun.java.launcher=SUN_STANDARD
user.country=JP
sun.boot.library.path=C:\Program Files\Java\jdk-1.8\bin
sun.java.command=getProperty
jdk.debug=release
sun.cpu.endian=little
user.home=C:\Users\user
user.language=ja
sun.stderr.encoding=ms932
java.specification.vendor=Oracle Corporation
java.version.date=2019-04-16
java.home=C:\Program Files\Java\jdk1.8
file.separator=\
java.vm.compressedOopsMode=32-bit
line.separator=
java.vm.specification.vendor=Oracle Corporation
java.specification.name=Java Platform API Specification
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironmen
user.script=
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
java.runtime.version=12.0.1+12
user.name=saku
path.separator=;
os.version=6.1
java.runtime.name=Java(TM) SE Runtime Environment
file.encoding=MS932
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vendor.url.bug=https://bugreport.java.com/bugreport/
java.io.tmpdir=C:\Users\Temp\
java.version=12.0.1
user.dir=C:\blog\systemProperty
os.arch=amd64
java.vm.specification.name=Java Virtual Machine Specification
sun.os.patch.level=Service Pack 1
java.library.path=C:\Program Files\Java\jre1.8\bin;...
java.vm.info=mixed mode, sharing
java.vendor=Oracle Corporation
java.vm.version=12.0.1+12
sun.io.unicode.encoding=UnicodeLittle
java.class.version=56.0

「sun.boot.library.path」も出力されていますね。

48行目です。

まとめ


いかがでしたでしょうか?
もし、“このアプリって本当に、意図したJavaみてるっけ?”と気になった時は、「System.getProperty」を使ってJavaのパスを確認した方がよいかと思います。
パスの設定が間違っていても、なかなか気が付かなかったりするので、実際にアプリケーションにデバッグブログラムをいれて確認すると安心ですね。


それではまた!



Apache Solrを使ったドキュメント検索 – Standard Highlighter

ApacheSolr

前回の記事で、Apache Solrを使って、登録・削除・検索を紹介しました。



今回は、検索結果をハイライト表示する方法を紹介します。

Apache Solrでのハイライト表示とは、検索結果として一致したキーワード前後の文字列を通知して、かつ、検索したキーワード部分を強調表示する機能になります。

本記事では、Apache Solrで最も一般的なハイライト表示である「Standard Hilighter」を使ってみます。

環境情報


環境情報は以下になります。

使用するのは、JavaとApache Solrの2つのみです。

  • Java 12.0.1
  • Apache Solr 6.4.2

スキーマ定義

ハイライト表示するためには、ハイライト表示するための準備が必要です。

Apache Solrのコンフィグである「managed-schema」に、フィールドタイプ定義とフィールド定義をおこないます。


フィールドタイプ定義

<fieldType name="text_general_content" class="solr.TextField" 
  positionIncrementGap="100" multiValued="true" 
  autoGeneratePhraseQueries="true">
  <analyzer type="index">
    <tokenizer class="solr.NGramTokenizerFactory" 
      minGramSize="1" maxGramSize="1"/>
    <filter class="solr.StopFilterFactory" 
      words="stopwords.txt" ignoreCase="true"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.NGramTokenizerFactory" 
      minGramSize="1" maxGramSize="1"/>
    <filter class="solr.StopFilterFactory" 
      words="stopwords.txt" ignoreCase="true"/>
    <filter class="solr.SynonymFilterFactory" 
      expand="true" ignoreCase="true" synonyms="synonyms.txt"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

フィールド定義

<field name="content" type="text_general_content" multiValued="false" indexed="true" stored="true"/>

「managed-schema」の定義を追加したら、ApacheSolrのサービスを再起動してください。


これで準備完了です。

以降に登録したドキュメントについて、ハイライト表示の文字列取得が可能になります。


Standard Highlighterのサンプルコード


「Standard Highlighter」を使った検索のサンプルコードは以下になります。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.Group;
import org.apache.solr.client.solrj.response.GroupCommand;
import org.apache.solr.client.solrj.response.GroupResponse;
import org.apache.solr.common.util.ContentStreamBase;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrDocument;

public class SolrSearch {

    public static void main(String[] args){
        System.out.print("start: main\r\n");

        // Solrのインスタンス作成
        SolrClient client = new HttpSolrClient.Builder(
            "http://localhost:8983/solr/java_sample").build();

        SolrQuery solrQuery = new SolrQuery();

        // 検索結果として、文書IDを返却するよう設定
        solrQuery.setFields("id");

        // 検索結果の上限は100件
        solrQuery.setRows(100);

        try {
            StringBuilder queryString = new StringBuilder();
            String keyword = args[0];
            if (keyword.equals("")) {
                queryString.append("*");
            } else {
                String queryPhrase = "\"" + ClientUtils.escapeQueryChars(keyword) + "\"";
                queryString.append("(");
                queryString.append("content:");
                queryString.append(queryPhrase);
                queryString.append(")");
            }

            // 検索実行
            System.out.println("q=" + queryString.toString());

            solrQuery.set("hl", true);
            solrQuery.set("hl.fl", "content");
            solrQuery.set("hl.simple.pre", "<b>");
            solrQuery.set("hl.simple.post", "</b>");
            solrQuery.set("hl.fragsize", 20);
            solrQuery.set("hl.maxAnalyzedChars", 100);
            solrQuery.set("q", queryString.toString());

            QueryResponse response = client.query(solrQuery);

            // 検索結果を表示
            SolrDocumentList list = response.getResults();
            if (list == null) {
                System.out.println("文書は存在しませんでした。");
            } else {
                System.out.println(list.getNumFound() + "件ヒットしました。");

                // ハイライト情報を取得して加工
                Map<String,Map<String,List<String>>> highlighting = response.getHighlighting();
                for (SolrDocument doc : list) {
                    String id = (String) doc.getFieldValue("id");
                    Map<String, List<String>> map = highlighting.get(id);
                    List<String> contentList = map.get("content");
                    for(String val : contentList) {
                        val = val.replaceAll("[\r\n\t]", "");
                        System.out.println("val=" + val);
                    }
                }
            }
        } catch (SolrServerException e) {
            System.out.print("SolrServerException Occured!\r\n");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.print("IOException Occured!\r\n");
            e.printStackTrace();
        } finally {
            try {
                // コミットして、コネクションをクローズ
                client.commit();
                client.close();
            } catch (Exception e) {
                System.out.print("Exception Occured!\r\n");
                e.printStackTrace();
            }
        }
        System.out.print("end: main\r\n");
    }
}

「Standard Highlighter」を使用するためのパラメータ設定は57~63行目です。

検索結果をハイライト文字列として取得しているのが76~83行目。

ハイライト文字をWEB画面上に出力することを想定して、改行とタブを削除しています。


以下のようなテキストファイルをApacheSolrに登録して、検索を試してみます。

主食と野菜をしっかり食べさせよう

このテキストファイルが登録されている状態で『野菜』というキーワードで検索してみます。

すると、以下のような文字列がハイライト文字としてApacheSolrから返却されてきます。

主食と<b>野</b><b>菜</b>をしっかり食べさせよう


これをWEBページに出力すると以下のような表示になります。

主食とをしっかり食べさせよう


検索してヒットした「野菜」という文字が強調表示されています。

これが、ハイライト表示の基本的な動きになります。


Standard Highlighter のパラメータ

サンプルプログラムで、Standard Highlighter を使用した検索をおこない、ハイライト文字を取得できます。

このハイライト表示はパラメータでチューニング可能です。

具体的には以下の部分。

    solrQuery.set("hl", true);
    solrQuery.set("hl.fl", "content");
    solrQuery.set("hl.simple.pre", "<b>");
    solrQuery.set("hl.simple.post", "</b>");
    solrQuery.set("hl.fragsize", 20);
    solrQuery.set("hl.maxAnalyzedChars", 100);

「Standard Highlighter」を使用するには、上記のパラメータを設定するだけでOKです。

各パラメータの意味合いは以下になります。


パラメータ

デフォルト

説明

hl

blank

このパラメータを「true」にする、ハイライトがオンになります。

デフォルトはブランク(オフ)です。

hl.fl

blank

ハイライトの対象となるフィールド。

複数定義する場合は、カンマ区切りで指定します。

hl.simple.pre

<em>

ハイライト表示する文字の前に挿入する文字。

hl.simple.post

</em>

ハイライト表示する文字の後に挿入する文字。

hl.fragsize

100

スニペットひとつあたりの最大文字数。

hl.maxAnalyzedChars

51200

スニペットの処理対象最大文字数。


スニペットとは、”検索キーワードを含む文書”です。

今回の例では「hl.fragsize」は20としているので、”検索キーワードを含む文書”は最大20文字です。


例えば、下のような150文字の文字列があるとします。

ああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ主食と野菜をしっかり食べさせよういいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいい

この文字に対して「野菜」を検索キーワードとして指定します。

その際の返却文字列は以下となります。20文字です。

ああああ主食とをしっかり食べさせよう

「hl.fragsize」は20なので、返却される文字列は最大20文字、ということですね。


まとめ

いかがでしたでしょうか?

「Standard Highlighter」の使い方について、ある程度わかって頂けたかと思います。


ハイライト表示は、「Standard Highlighter」以外に以下の2つがあります。

  • FastVector Highlighter
  • Postings Highlighter

次回は、「FastVector Highlighter」を使ったハイライト表示を紹介したいと思います。


それではまた!



Apache Solrを使ったドキュメント検索 – 環境構築とJavaからの実行まで

ApacheSolr

文書を管理するシステムの場合、文書の中身を検索する機能が必要だったりします。


例えば、”システムに登録されているWordファイルについて、「○△□」といった文字が存在するファイルだけ注出する”といった機能です。


でも、そういった機能をゼロから作るのは大変ですよね。

プログラムを作るとしたら、”ファイルを開いて”→ “ファイルの中身の文字を注出して”→”キーワードと一致する文字を検索して”といった作り込みが必要です。


今回は、Apache SolrをJavaから呼び出し、文書を登録、編集、削除する方法を説明していきます。


『Apache Solr』を導入すると、文書の管理(登録、編集、削除)や文書の検索をAPI形式で実行することができ、簡単に文書管理をおこなうシステムを構築することができます。

  • 文書の管理(登録、編集、削除)
  • 文書の検索
  • 文書検索結果の返却

今回は、Apache Solrの開発環境構築から、JavaからAPIを呼び出して結果を取得するまでを紹介します。


Apache Solrのインストール(サービス化)


まずは、Apache Solrをインストールします。

今回は、Apache Solrをサービス化する形でインストールします。

サービス化は、「nssm」を使用します。

nssmは、Microsoft Windows用のサービスマネージャです。

サービス化すると、バックグラウンドおよびフォアグラウンドのサービスとプロセスを管理する無料のユーティリティです。 プログラムは、失敗したサービスを自動的に再始動するように設定できます。

以下サイトからダウンロード可能です。


という訳で、環境情報としては以下になります。


  • 文書検索エンジン:Apache Solr 6.4.2
  • サービス化ツール:nssm 2.24

公式サイトからダウンロードしたApache Solrのモジュールとnssmを、任意のフォルダに配置します。

筆者は、Apache Solrを「C:\ApacheSolr」直下に、nssmを「C:\SolrInstall」に配置しました。


以下のような感じです。

ApacheSolrの配置
Solrの配置

Apache Solrの”インストール”というのは不要で、マシンに配置して完了です。

nssmを使用して、配置したApache Solrをサービス化します。


それでは、nssmでのサービス化をおこないます。

DOSプロンプトで、nssmを配置したディレクトリに移動し、nssm installコマンドを実行します。



コマンドを実行するとサービスインストーラのウィンドウがひらくので、必要な情報を入力します。


  • Path:Apache Solrの起動コマンドパス
  • Startup directory:ApacheSolrの起動ディレクトリ
  • Arguments:起動パラメータ
  • Service name:サービス名

以下のように入力します。


ApacheSolrのサービス化

「Arguments」には、起動パラメータと同時に使用するポートを記載します。

筆者は、8983ポートを使用するようにしました。


全ての入力が完了したら、「Install service」ボタンを押下します。

以下のダイアログが表示されたらインストール完了です。

ApacheSolrのサービス化完了

それでは、きちんとサービス化されたかどうかを確認してみましょう。 

サービス一覧で「Apace Solr」が存在すれば、サービス化完了です。

「開始」を選択して、Apache Solrを起動してください。

ApacheSolrの起動

ステータスが「開始」になったことを確認しましょう。


きちんと起動できたかを確認するためには、ブラウザでApache SolrのWeb画面を表示します。

ブラウザで入力するURLは「http://localhost:8984」です。

以下のようにダッシュボードが表示されれば、起動成功です。

ApacheSolrのダッシュボード

コアを作成


Apache Solrの準備ができたら、Apache Solrで『コア』を作成して使用するための準備をおこないます。


『コア』とは何か?という説明は、いまは省略します。

とりあえず動かしたいので。

イメージとしては、データベースのスキーマでしょうかね?


コアの作成方法はいろいろあるみたいなのですが、筆者はDOSプロンプトでコマンドを実行する形でコアを作成します。

コアの名前は「java_sample」としました。


ApacheSolrのコア作成

コアの作成が完了したら、Apache Solrのサービスを再起動します。

再起動後にダッシュボードを確認します。

「java_sample」というコアが作成されています。


コアを選択すると、ダッシュボードにコアの情報が表示されます。

ApacheSolrでのコア作成

これで、Apache Solrの準備完了です。


文書を登録


文書の登録を、JavaからAPIを実行する形でおこなうことが可能です。

サンプルプログラムは以下となります。


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;

import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.common.util.ContentStreamBase;

public class SolrInsert {

    public static void main(String[] args){
        System.out.print("start: main\r\n");

        // idとファイル名をパラメータから取得
        String id = args[0];
        String fileName = args[1];

        // Solrのインスタンス作成
        SolrClient client = new HttpSolrClient.Builder(
            "http://localhost:8983/solr/java_sample").build();

        try {
            // APIの実行準備
            File file = new File(fileName);
            ContentStreamUpdateRequest update = 
                new ContentStreamUpdateRequest("/update/extract");
            update.addContentStream(
                new ContentStreamBase.FileStream(file));

            // idとファイル名をパラメータに指定
            // 既に登録済のIDを指定した場合、登録ではなく更新となる
            update.setParam("literal.id", id);
            update.setParam("literal.filename", file.getName());

            // コマンドを実行
            client.request(update);
        } catch (SolrServerException e) {
            System.out.print("SolrServerException Occured!\r\n");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.print("IOException Occured!\r\n");
            e.printStackTrace();
        } finally {
            try {
                // コミットして、コネクションをクローズ
                client.commit();
                client.close();
            } catch (Exception e) {
                System.out.print("Exception Occured!\r\n");
                e.printStackTrace();
            }
        }
        System.out.print("end: main\r\n");
    }
}

重要な部分は、強調表示している26行目から37行目の部分です。

実際にSolrに対して、「/update/extract」というAPIを呼び出して登録コマンドを実行しています。


メインとなる使用クラスは「ContentStreamUpdateRequest 」。「addContentStream」で電子ファイルの実態を指定し、setParamでパラメータを指定しています。

指定しているパラメータは2つで、IDとファイル名。


コメントにも記載していますが、同じIDを指定した場合はドキュメントの更新になります


プログラムの動作結果を、ApacheSolrのダッシュボードで確認してみます。

まだ、1つドキュメントが登録されていない状態であれば、以下のようになります。


ApacheSolrのコンソール。ドキュメント数が0。

この状態でプログラムを実行してみます。


IDとファイル名はパラメータで指定可能となっていますが、IDは101、ファイル名はtemplate.xlsxを指定して、プログラムを実行します。

プログラムの実行後にコンソール画面を確認すると、ドキュメントが登録されていることが確認できます。


ApacheSolrのドキュメント数。0から1に。

登録した結果を、もうちょっと詳しくみてみます。

Apache Solrのダッシュボードでは、ドキュメントの検索が可能です。

この検索を使って、登録したドキュメントを確認してみます。


ApacheSolrダッシュボード。

登録のときに指定したIDとファイル名のドキュメントが登録されていることがわかります。


次に「更新」をおこなってみます。

プログラムは「登録」の時のプログラムと同様です。

同じIDを指定すれば、Apache Solrが更新をおこなってくれます。

試しに、IDは登録の時に指定したIDと同じ「101」を指定し、ファイル名を「template_2.xlsx」に変更して、登録の時と同じプログラムを実行してみます。


実行した後に、Apache Solrのダッシュボードを確認すると、以下のようになります。


ApacheSolrダッシュボード。更新後。

検索結果のドキュメント数は変わっておらず(numFoundが1)、id=101のドキュメントファイル名が、「template.xlsx」から「template_2.xlsx」に変わっています。

つまり、「登録」ではなく「更新」をおこなったことがわかります。


文書を全部削除


文書の削除もAPIから可能です。

まずは、全削除のAPIを作成して実行してみます。


削除するまえに、ApacheSolrにドキュメントを3つ登録してみました。

ApacheSolrのダッシュボードで、ドキュメントが3つ登録されていることを確認しておきます。


ApacheSolrダッシュボード。

ドキュメントが3つ登録されていることが確認できました。

この状態で、ドキュメント全削除のプログラムを実行します。


サンプルプログラムは以下です。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;

import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.common.util.ContentStreamBase;

public class SolrAllDelete {

    public static void main(String[] args){
        System.out.print("start: main\r\n");

        // Solrのインスタンス作成
        SolrClient client = new HttpSolrClient.Builder(
            "http://localhost:8983/solr/java_sample").build();

        try {
            // APIを実行
            String deleteQuery = "*:*";
            client.deleteByQuery(deleteQuery);
        } catch (SolrServerException e) {
            System.out.print("SolrServerException Occured!\r\n");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.print("IOException Occured!\r\n");
            e.printStackTrace();
        } finally {
            try {
                // コミットして、コネクションをクローズ
                client.commit();
                client.close();
            } catch (Exception e) {
                System.out.print("Exception Occured!\r\n");
                e.printStackTrace();
            }
        }
        System.out.print("end: main\r\n");
    }
}

実際の削除処理をおこなっている部分は、23行目と24行目になります。。

「SolrClient」クラスの「deleteByQuery」メソッドを使用して削除をおこなっています。

クエリパラメータに「*:*」を指定すると全削除、になります。


ApacheSolrのダッシュボードを確認するとドキュメント数が0になっており、全削除されていることがわかります。


ApacheSolrのダッシュボード。全削除後。

文書を一部削除


文書を全削除する方法を紹介しましたが、実際のシステムではあまりニーズはないかと思います。

あるとすれば、全削除ではなく指定したドキュメントのみを削除、ですかね。


指定したドキュメントのみを削除することも可能です。

サンプルプログラムは以下になります。


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;

import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.common.util.ContentStreamBase;

public class SolrOneDelete {

    public static void main(String[] args){
        System.out.print("start: main\r\n");

        // Solrのインスタンス作成
        SolrClient client = new HttpSolrClient.Builder(
            "http://localhost:8983/solr/java_sample").build();

        try {
            // APIを実行
            String deleteQuery = "id:(102)";
            client.deleteByQuery(deleteQuery);
        } catch (SolrServerException e) {
            System.out.print("SolrServerException Occured!\r\n");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.print("IOException Occured!\r\n");
            e.printStackTrace();
        } finally {
            try {
                // コミットして、コネクションをクローズ
                client.commit();
                client.close();
            } catch (Exception e) {
                System.out.print("Exception Occured!\r\n");
                e.printStackTrace();
            }
        }
        System.out.print("end: main\r\n");
    }
}

idが102のドキュメントを削除しています。

解り易いように、IDをハードコーディングしていますが、23行目と24行目です。


複数のドキュメントを削除する場合は、ID指定をORで繋いで指定すればよいです。

    String deleteQuery = "id:(201 OR 202)";
    client.deleteByQuery(deleteQuery);

文書を検索


次に文書の検索です。

ApacheSolrの肝となる部分ですね。

今回は「とりあえず動かす編」ということで、ファイル名での検索をおこないます。


本来であれば、登録したドキュメントの中身に対する検索をおこないたいところですが、それについてはまた次回、という事で。

今回は、とりあえず動かしちゃいましょう!


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.Group;
import org.apache.solr.client.solrj.response.GroupCommand;
import org.apache.solr.client.solrj.response.GroupResponse;
import org.apache.solr.common.util.ContentStreamBase;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrDocument;

public class SolrSearch {

    public static void main(String[] args){
        System.out.print("start: main\r\n");

        // Solrのインスタンス作成
        SolrClient client = new HttpSolrClient.Builder(
            "http://localhost:8983/solr/java_sample").build();

        SolrQuery solrQuery = new SolrQuery();

        // 検索結果として、文書IDを返却するよう設定
        solrQuery.setFields("id");

        // 検索結果の上限は100件
        solrQuery.setRows(100);

        try {
            StringBuilder queryString = new StringBuilder();
            String keyword = args[0];
            if (keyword.equals("")) {
                queryString.append("*");
            } else {
                String queryPhrase = "\"" + 
                    ClientUtils.escapeQueryChars(keyword) + "\"";
                queryString.append("(");
                queryString.append("filename:");
                queryString.append("*" + queryPhrase + "*");
                queryString.append(")");
            }

            // 検索実行
            solrQuery.set("q", queryString.toString());
            QueryResponse response = client.query(solrQuery);

            // 検索結果を表示
            SolrDocumentList list = response.getResults();
            if (list == null) {
                System.out.println("文書は存在しませんでした。");
            } else {
                System.out.println(list.getNumFound() + 
                    "件ヒットしました。");
                for (SolrDocument doc : list) {
                    System.out.println(doc.get("id"));
                }
            }
        } catch (SolrServerException e) {
            System.out.print("SolrServerException Occured!\r\n");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.print("IOException Occured!\r\n");
            e.printStackTrace();
        } finally {
            try {
                // コミットして、コネクションをクローズ
                client.commit();
                client.close();
            } catch (Exception e) {
                System.out.print("Exception Occured!\r\n");
                e.printStackTrace();
            }
        }
        System.out.print("end: main\r\n");
    }
}

まず、35行目と36行目で、返却するフィールドを定義しています。

このサンプルプログラムでは、「id」を返却するようにしています


検索条件の設定部分は、47行目から51行目部分です。

サンプルプログラムでは、ファイル名を格納している「filename」フィールドに対して検索をおこなうようにしています

あと、検索ワードはエスケープしています。


まとめ

いかがでしたでしょうか?


紹介した方法でApache Solrを構築してサンプルプログラムを実行すれば、といあえず一連の動作は動きます。

しかし、ApacheSolrの醍醐味はやっぱり検索です。

ApacheSolrの検索には、いろいろなオプションが存在しますので、次回の記事でそこら辺を紹介していきます。


それではまた!



さくさくのTips!よく使うLinuxコマンド集

Linux

こんにちは。
さくさくTECHブロガーの「さく」です。


Linuxコマンドで忘れやすいコマンドをまとめていきます。

自分用っていう部分もありますが、もしよければ参考にしてください。


Linuxコマンド

コピー

強制的にコピーするときは「-f」。

強制的というのは、いちいち”上書きします。よろしいですか?”をきかない、ということ。


cp -f a.txt b.txt


ディレクトリをコピーするときには「-r」。

コピー元ディレクトリ配下のファイル、および、サブフォルダ・サブファイルもコピーする。


cp -r directory1 directory1


ファイルの属性を保持したままコピーするときは「-p」。

ファイルの属性とは、ファイルのタイムスタンプ・権限、といったメタ情報。


cp -p a.txt b.txt

リスト

よく使うオプションは「-la」。

「l」は、詳細表示。

「a」は、全て表示。(先頭に . がついているファイルとか)


ls -la

ファイルのタイムスタンプをミリ秒まで表示したい場合は、「–full-time」


ls -la --full-time

履歴

コマンドの実行履歴をみたい場合はhistory

現在ログインしているユーザのコマンド実行履歴なので、ユーザを切り替えた場合は、切り替え前の実行履歴は表示されない。


history

履歴コマンドを実行すると、大概は大量にコマンドが出てくるので、パイプでつないでお目当てのコマンドを探す


history | grep ○△□

※「○△□」は探す対象のコマンドなど

エイリアス

OSに設定されてるエイリアスを確認する時はエイリアスコマンド


alias

登録されているエイリアスコマンドが確認できるが、たいがいのLinuxでは「ll(エルエル)」は “ls -l –color=auto” のエイリアス。


所有者とグループの変更

所有者・グループの変更はchownコマンド。


chown owner:group ○△□

「owner」はオーナー名。

「group」はグループ名。

「○△□」は、対象のフォルダ名とファイル名。


圧縮・解凍

一番簡単な圧縮コマンドは「gzip」


gzip file

解凍も「gzip」でいける
「-d」をつけると、圧縮ファイルは削除される。


gzip -d file

viエディタ

Linux上でファイルを直接修正する場合はviコマンド



vi ファイル名

「i」で編集モード、「esc」でコマンドモード、を切り替える。

コマンドモードでよく使うコマンドは以下。

コマンド 説明
/ (スラッシュ)

スラッシュをいれて検索ワードを入力。

エンターで検索開始。

n(小文字)で次検索。

N(大文字)で前検索。

Shift + g

ファイルの末尾に移動。

dd(dを2回押し)

1行削除

yy(yを2回押し)

行コピー

p

ペースト

シェル

シェルの実行

シェルを実行するときは、シェルが存在するディレクトリを明確にしたうえでシェルファイル名を指定するだけ。


./shell.sh


シェルをバックグラウンドで実行するときは、末尾に「&」をつける。

バックグラウンドで実行といっても、「huponexit」の設定次第では、実行端末を閉じるとシェル自体は停止するので注意が必要。


./shell.sh &

TeraTermマクロを使って、Linux上の指定ファイルダウンロードを自動化

Linux

Linuxのシステムを保守している技術者が日々直面するシーンとして、”特定のログファイルを取得する”という場面があるかと思います。


例えば、一日に1回、アプリケーションのログやミドルウェアのログを収集して、変なエラーが出てないか?を調査したりする場合ですね。


特に、サービスのローンチ直後はよくある場面かと思います。


今回は、TeraTermマクロを使って、ログイン→圧縮ファイル作成→ダウンロードを自動的に実施するマクロを紹介します。


いちいち、ログインしてー、ファイル圧縮してー、ダウンロードしてー、って面倒ですもんね!?

環境情報

今回は、WindowsマシンにTeraTermがインストールされている状態を前提とします。

TeraTermを使って、Linuxサーバにログインします。


  • クライアントOS:Windows7
  • ターミナルエミュレータ:TeraTerm
  • サーバOS:Linux

マクロを使って自動ログイン

自動ログインの部分は、以前、作成した記事を参照してください。



今回は、“パスの指定” “ダウンロード” の部分を中心に解説していきます。


マクロで自動ログインしてダウンロードまで

とりあえず、作成したマクロを紹介します。

このマクロで、“自動ログイン”→”対象フォルダへの移動”→”圧縮してダウンロード”が可能です。


; sample TeraTerm Macro
;
; FILE:     fileGet.ttl
; create:   2019/07/21
; Author:   SakuSaku

call login
call setCur
call dwnload
sendln 'exit'
end

;
; ログイン
;
:login
    ; ホスト名とログインアカウントを定義
    host = 'sakusaku.com:22'
    account = 'sakusaku'

    ; リモート認証に必要な固定文字列を定義
    msg = 'Enter password for user '
    strconcat msg account
    passwordbox msg 'Get password'

    ; 「msg」を作業領域とし、リモート認証に必要な文字列を作成する
    msg = host
    strconcat msg '/ssh /auth=password /user='
    strconcat msg account
    strconcat msg ' /passwd='
    strconcat msg inputstr

    ; 認証する
    connect msg
return

;
; 指定フォルダに移動
;
:setCur
    ; 入力できる状態までまつ
    wait '$ '

    ; フォルダを入力
    inputbox 'フォルダを指定してください(/区切り):' 'フォルダ入力'
    strscan inputstr '/'
    if result <= 0 then
        messagebox '正しいパスを指定して下さい' 'エラー'
        end
    endif

    ; 指定されたフォルダに移動
    cmd = "cd "
    strconcat cmd inputstr
    sendln cmd
return

;
; ダウンロード
;
:dwnload
    ; 入力できる状態までまつ
    wait '$ '

    ; テキストファイルを、すべてzipファイル化
    cmd = "find *.txt | zip -@ file.zip"
    sendln cmd

    ; 入力できる状態までまつ
    wait '$ '

    ; 圧縮ファイルのフルパスを取得
    sendln 'pwd'
    recvln
    recvln
    zipFile = inputstr
    strconcat zipFile '/file.zip'

    ; ダウンロード先のフルパスを取得
    getdir localfile
    strconcat localfile '/file.zip'

    ; ファイルをダウンロード
    scprecv zipFile localfile

return

それでは、ポイントを説明していきます。

ダウンロードマクロのポイント

loginメソッドのマクロについては、以下の記事を参照してください。


フォルダの指定はユーザ指定が可能

このマクロは、Linux上に存在する特定フォルダ配下のファイルを圧縮して、マクロが存在するクライアントPCの指定フォルダに圧縮ファイルをダウンロードします。


圧縮するファイルが存在するLinux上のフォルダですが、このマクロではユーザによる指定を可能としています。


マクロの「setCur」メソッドが、該当箇所になります。

具体的には以下の箇所。


    inputbox 'フォルダを指定してください(/区切り):' 'フォルダ入力'
    strscan inputstr '/'
    if result <= 0 then
        messagebox '正しいパスを指定して下さい' 'エラー'
        end
    endif

inputboxで入力ダイアログを表示し、受け取った文字列に「」’/’を付加して、パスを作成しています。


フォルダ入力ダイアログ

マクロが存在するフォルダにダウンロード

ダウンロードするまでに、いくつかの処理があります。


まずは、圧縮ファイルを作成しています。

拡張子が「txt」のファイルを検索して、file.zipという圧縮ファイルにまとめています。

    ; テキストファイルを、すべてzipファイル化
    cmd = "find *.txt | zip -@ file.zip"
    sendln cmd

次に圧縮ファイルのフルパス作成です。

ここでのフルパスは、Linux上にzipファイルのフルパスです。

現在フォルダ(pwd) + file.zip としています。

    ; 圧縮ファイルのフルパスを取得
    sendln 'pwd'
    recvln
    recvln
    zipFile = inputstr
    strconcat zipFile '/file.zip'

最後にファイルダウンロードです。

 

注意しなければいけないのが、「localfile」になります。

これは、”マクロが存在する場所”になります。

 


ダウンロード自体は簡単で、「scprecv」を呼び出すだけです。

「scprecv」で、セキュアなファイルダウンロードが可能になります。

    ; ダウンロード先のフルパスを取得
    getdir localfile
    strconcat localfile '/file.zip'

    ; ファイルをダウンロード
    scprecv zipFile localfile

まとめ

いかがでしたでしょうか?

TeraTermマクロを使って、ファイルをダウンロードするやり方がわかったかと思います。

まとめ
  • ユーザ入力は「inputbox 」で表示可能
  • ファイルのダウンロードは「scprecv 」

それではまた。



Googleアドセンスの広告が表示されない!原因はなに?

Googleアドセンス

こんにちは。
さくさくTECHブロガーの「さく」です。


最初に言っておきますが、この記事の初版は2019年7月7日です。

タイトルの通りの問題なのですが、どうやら長引きそうだなと判断致しまして、この記事で経緯をまとめる形にしました。


皆さんのGoogleアドセンス運用での助けになれば(なるのか?)と思います。


Googleアドセンスを導入して広告が出ない場合のHowTo になります。


Googleアドセンス審査に合格しました!

思ったよりも早くに合格しちゃいました!


GoogleAdseneceの合格

このメールがGoogleから届いたときはうれしかったですね。

2回目の申請で合格しました。

とはいっても1回目と2回目の間は1ヶ月くらいあって、その間は試行錯誤しました。。。

わたくし、昼間は都内でSIerをやっておりまして、基本は土日にしかまとまった時間がとれないんですよねー。


1回目申請時の不合格理由は『コンテンツが複製されているサイト』だったのですが、”コピーしてねーよ!””どこがコピーなんだよ!”って一人で悪態ついてました。

でも、冷静になっていろいろ調べたのですが、どうやら『あなたのブログは客観的すぎておもしろくありません!』って言われているということがわかったので、いろいろ修正に取り掛かることにしました。

記事の構成を変えたり、言葉の言いまわしを変えたり、記事を削除したり、ですね。 

申請時は15記事あったのですが、大幅にリストラしまして、合格時は8記事です。


同じ理由で不合格になった方は結構いらっしゃるようで、”15回目の申請でやっと合格した!””っていうか諦めた!”という阿鼻叫喚状態だったので心配していましたが、2回目で合格。


2回目で合格する俺ってすげー!って思ったのですが、そこからが苦難の始まりです。


アドセンスの広告が出ないんです!

合格後、4日経った今でも!

さあ、困りました。。。


広告が出ない原因を考えてみる

正確には言うと、広告が出ない訳ではないんですよ。

「合格直後は出ていたけど出なくなった」「一部は出る」って言うのが正確かなと。

合格直後はここに出ていた

確実に合格直後は出ていたんです!(信じて!)

“よくみるブログのよくみる広告”が出ていました。

よしよし、なーんて思ってました。


広告が出ていた箇所1
広告が出ていた箇所1

合格直後の4・5時間は広告が出ていたのですが、その後になぜかパタッと広告が出なくなりました!


なぜだ?!


ちなみに、ブラウザのキャッシュを削除して確認してみたり、ブラウザを変えて確認したり、会社のパソコンから確認したり、とやってみたのですが、現象は変わらずでした。

広告が出る部分もある

まったく広告出ないのであれば、”何か変な設定しちゃったかな?”と思えるのですが、実は広告が出る箇所もあるんです。

だから混乱しちゃってます。

スマートフォン画面でブログをみたときに、ヘッダ上部には広告が出ます。


モバイル上部への広告表示

モバイル上部の広告は出るのですが、サイドバー下部と記事下部の広告は出ないです。

これは、パソコンもスマートフォンも同様。



問題点を探っていく

ネットで検索したら良い記事がありました。

同じようなことで悩んでいる人はいっぱいいるってことですね。



この記事に沿って、16のチェック項目をチェックしていきます。


1.審査中

合格は頂いております。

クリア。


2.広告配信に適しているか審査中

どうやらGoogleは、「このブログにはどんてな広告を出した方がいいのかな?」っていう調べる時間があるようです。

「ブランドプロテクション」っていうらしい。

これが原因かもしれませんが、審査に合格してコードをいれてから4日ほど経っているのに、まだ時間が掛かっているとは考えにくい。

とはいっても可能性はあるので、要チェック。


3.YouTubeやBloggerでアカウントを取得した

そんなことしてません。

クリア。


4.PINを入力していない

収益が1,000円以上達した場合のお話のようです。

こちとら、1円も売り上がっていません。

クリア。


5.Javascriptが有効になっていない

有効です。

あと、キャッシュを全部削除しても同じでした。

クリア。


6.アドブロックを使用している

広告を非表示にするツールを「アドブロックツール」というらしいです。

これが有効になっていると広告が表示されない場合があると。

あやしい。要チェック。


7.コードが正しく設置できていない

正しく設置しているつもりだが。。。

確証を得るには、WordPressの設定も見直したり、もうちょっと調べた方がいい。

要チェック。


8.広告が多くなっていないか

広告はGoogleアドセンスしか設置していないのですが、参考サイトに気になる文書がありました。


逆にコンテンツが少ないページには広告を多く設置してはいけません。


広告は多くないのは確かだが、逆で、コンテンツが少ないと思われていてそれが原因?

要チェック。


9.コードが古いタイプ

ブログをSSL化した際にコードが古いと広告が表示されない場合があるようです。

このブログは最初からSSL化できています。

クリア。


10.NG キーワードが含まれる

健全です。

クリア。


11.ポリシー違反の状態で配信停止

アドセンスのコンソールで確認しましたが、通知は発生していません。

クリア。


12.トラフィックの品質が悪い

んー、怪しい。。。

このブログは2019年5月に公開したばっかりだし、記事も10記事もないし、だからPVも全然ないし。。。

要チェック。


※2019年9月1日

結果、原因はこれでした。

詳細な考察は、本記事の下に記載したのでそちらを参照してください。

Googleアドセンスの広告が出なくて悩んでいる人は参考にしてください。

ある程度PVがないと広告は出ないよ!ってことですね。


13.[サイト]に URL が追加され「準備完了」になっていない

「準備完了」になっています。

クリア。


14.今までアカウントが無効になったことがある

ありません。

クリア。


15.サイト単位(ドメイン)で停止

停止されていません。

クリア。


16.プラグインや他のシステムと干渉

んー、怪しい。。。

このブログはWordPressで作っているのですが、当然、プラグインはいくつか使っています。

このプラグインと干渉して広告が出ないなんてことはあり得る。

要チェック。



こうやって改めて確認していくと、怪しい個所がチラホラとありますね。

この「要チェック」個所をまずは調べていくしかないかなと思っています。


ads.txtのワーニングが出ている

広告が出ないことと関係ないとは思っているのですが、アドセンスの管理コンソールに以下のワーニングが表示され続けています。


ads.txtが配置されていないワーニング

この件は、「ads.txt」をドキュメントルールに配置すればよいという話だったのですが、配置後に4日経った今でもワーニングが消えません。

これが原因なのかなー?


※2019年7月21日

.htaccessの修正をおこないました。

詳細は、下の「2019年7月21日版」を参照。

ちょっと様子見します。


※2019年7月28日

めでたく、「ads.txt」のワーニングは消えました。
という訳で、この問題は解決しました。

よかった。。。


広告を出すために調査する

時間が掛かりそうな問題なので、進展があったら下に内容を追記していきます。

結果的に解決しました。

以下、試した順の降順で記載していきます。

以下の順番で、試しました。


ads.txtチェックツール
 ↓
ads.txtのワーニング
 ↓
自動広告ではなく広告ユニット
 ↓
Advanced Adsを使う


とはいっても、ちゃんと書籍を買って勉強してから試した方がいいかもしれないですね。

余計な時間ととってしまいました。



Advanced Adsを使う

進展があったので追記。

進展というか解決、です。


実は結構まえから解決はしていたんですが、ブログに書くのが遅くなりました。

結果、広告が出るようになりました。

やったことは以下の2つ。


  • 広告表示のツールを「Advanced Ads」に変更した。
  • ただ待ってみた。

一つ目のやつは、あんまり関係ないかもしれないです。

以前は「Header and Footer」を使って、自動広告を表示するためのJavaScriptを埋め込んでいました。

これを「Advanced Ads」に変更しました。


「Advanced Ads」は、GoogleアドセンスのアカウントIDを入力して、自動広告を表示するをチェックすれば、自動的にHTMLヘッダーにJavaScriptが挿入されます。



「Advanced Ads」に変更したら、広告が出るようになった(ような気がします)。

でもこれは、関係ないと思っています。

なぜなら、「Header and Footer」を使った結果と「Advanced Ads」を使った結果のJavaScriptの出力結果がまったく同じだったので。


結果、広告が表示されるようになったのは。。。「ただ待ってみた」だけかと思います。


「2 広告が出ない原因を考えてみる」を記載しましたが、「12.トラフィックの品質が悪い」が原因だったと思っています。


Googleは、ブログにアクセスされたトラフィックを解析して、このユーザにはどのような広告を出すか?といったことを解析しています。


あまりにもトラフィックが少ないと、Googleはどんな広告を出していいかが解らないので、結果、広告が出ない。

原因はこれかなと。


筆者のブログは、10PV/日あたりの時に広告を挿入しました。

これが良くなかったです。


ちゃんと広告をだすようにするには、少なくとも30PV/日くらいないとダメですね。

それ以下のPVだと、Googleが”このブログは広告を出す価値なし!“って判断しちゃいます。


自動広告ではなく広告ユニット

進展があったので追記。

広告の設定方法を変えてみました。

自動広告ではなく広告ユニットの配置で広告を表示するようにしました。


広告の選択方法

自動広告は、ヘッダにアドセンスのJavaScriptコードを配置して終わりってやつ。

広告ユニットは、自分で広告種類を選択して、広告表示位置も指定できるやつ。

広告ユニットを使って広告を表示するようにすると、きちんと広告がでるようになりました。

記事の下に表示する広告ユニットを作成したのですが、ちゃんと出ます。


アドセンスの広告ユニットの表示

筆者のブログはWordPressで構築しているのですが、広告の表示にはAdvanced Adsを使いました。


何か一応、ちゃんと広告がでるようにはなったが。。。

また急に広告が出なくなる可能性もあるので、もうちょい様子見!

ads.txtのワーニング

ads.txtのワーニングが消えました。

やはり、前回(7月21日)の対応がきいたようです。


.htaccessへの文字コード追記ですね。


という訳で、adx.txtワーニングの件は解決という事になりました。

肝心の広告は、思ったように出ないままですが。。。


ads.txtチェックツール

進展があったので追記。

相変わらず、広告自体は思ったように出ないんですが、「ads.txt」で進展がありました。

「ads.txtチェックツール」というサイトがあると。。。(知らなかった)



早速ためしてみたのですが、以下のエラーを検出!


““ISO-8859-1” は誤った文字コードです。utf-8で作成してください。”というエラーが出ています。

このエラーを消すためには、2つの対処が必要とのことです。


  • ads.txtの文字コードをUTF-8Nにする
  • .htaccessで文字コード指定する

文字コードの方はOKでした。

UTF-8Nとは、BOM無のUTF-8とのことですが、既にUTF-8Nでした。

しかし、2つ目の.htaccessの設定はおこなっていませんでした!


原因はこれだ!ということで、.htaccessに記述を追加しました。

筆者のブログは「ロリポップ」上にWordPressを使って構築しており、SSHでの接続を可能にしています。

なので、WinScpで接続して.htaccessを直接編集しました。

<Files ads.txt>~</Files>の部分を追記しました。


#==== SITEGUARD_RENAME_LOGIN_SETTINGS_END
#SITEGUARD_PLUGIN_SETTINGS_END

<Files ads.txt>
AddType "text/plain; charset=utf-8" .txt
</Files>

# BEGIN WordPress

.htaccessを修正したあとに再度チェックツールを実行してみたところ、見事にエラーが消えました!

これでエラーが消えるか?またしばらく様子見です。



Javaでエクセルを操作したい!POIの環境構築からセルの背景色を設定して出力まで

ApachePOI

こんにちは。

さくさくTECHブロガーの「さく」です。


Webアプリケーションの開発では、“○○○一覧画面の内容をエクセルに出力する”といった場面がよく出てきます。

さらに、“○○○の条件に一致したらセルを赤くして!”といったユーザからのリクエストもありえますね。


Javaからエクセルを操作するための方法として、POIを使ったエクセル操作がとても便利です。

ライブラリが豊富で、ある程度の要件ついては、ほぼ対応することができます。


という訳で今回は、POIを使ってJavaでエクセル操作をおこなう方法を紹介します。


Apache POI

Javaでエクセルを扱うといえば。。。『Apache POI』しかないでしょう!

Apache POIは、Java用のエクセル操作ライブラリになります。

エクセルファイルの読み書き、セルを指定して文字列を出力、セル背景色を変更、といった様々な機能をもっています。

Apache POIの詳細については公式ページを参照ください。

ライブラリ本体(JARファイル)も、公式ページからダウンロードできます。



環境を構築

Apache POIを組み込んだJavaのバッチプログラムを動かすための環境を構築します。

今回、サンプルプログラムを作成した実行した環境としては以下になります。

  • OS:Windows 7
  • Java:Java1.8.0_40
  • Apache POI:poi 4.1.0

Javaのメインクラスを作って、必要なライブラリをダウンロードしてクラスパスを通して。。。といった具合で環境は作れるのですが、筆者はいくつかつまずきました。

ビルドはすんなり通ったのですが、実行しようとしても「NoClassFound」が発生してしまう、などですね。

結果、うまくいったのですが、ビルドする際に必要なJARと実行する際に必要なJARを記載しておきます。


ビルドする際に必要なJAR

  • poi-4.1.0.jar
  • poi-ooxml-4.1.0.jar
  • poi-ooxml-schemas-4.1.0.jar
  • poi-scratchpad-4.1.0.jar

実行する際に必要なJAR

  • poi-4.1.0.jar
  • poi-ooxml-4.1.0.jar
  • poi-ooxml-schemas-4.1.0.jar
  • poi-scratchpad-4.1.0.jar
  • xmlbeans-3.1.0.jar
  • commons-collections4-4.3.jar
  • commons-compress-1.18.jar

サンプルコードを実行するためには、上記のJARをクラスパスに設定する必要があります。


サンプルコードと解説

では実際にプログラムを作成して実行してみます。

以下を実行するプログラムを作成しました。


  1. テンプレートファイルである「template.xlsx」を読み込み。
  2. 3つのセルに文字列を書き込み。同時にそれぞれのセルの背景色設定。
  3. 作成したエクセルファイルを「out.xlsx」として保存。

簡単なプログラムですが、セルに色を付ける方法は理解頂けると。

プログラムは以下になります。


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.IndexedColors;

public class PoiColor {

    public static void main(String[] args){
        System.out.print("start: main\r\n");

        Workbook tempbook = null;
        try {
            //--- テンプレートファイルをひらいて、シートを指定 --//
            Path tempPath = Paths.get("./template.xlsx");
            InputStream inSt = Files.newInputStream(tempPath);
            tempbook = new XSSFWorkbook(inSt);
            Sheet sheet = tempbook.getSheet("Sheet1");

            //--- A1セルへの書き込み --//
            //--- セル背景色は栗色 --//
            Row row = sheet.createRow(0);
            Cell cell = row.createCell(0);
            cell.setCellValue("あああ");
            CellStyle styleA1 = tempbook.createCellStyle();
            styleA1.setFillPattern(
                FillPatternType.SOLID_FOREGROUND);
            styleA1.setFillForegroundColor(
                IndexedColors.MAROON.getIndex());
            cell.setCellStyle(styleA1);

            //--- A2セルへの書き込み --//
            //--- セル背景色は青 --//
            row = sheet.createRow(1);
            cell = row.createCell(0);
            cell.setCellValue("いいい");
            CellStyle styleA2 = tempbook.createCellStyle();
            styleA2.setFillPattern(
                FillPatternType.SOLID_FOREGROUND);
            styleA2.setFillForegroundColor(
                IndexedColors.BLUE.getIndex());
            cell.setCellStyle(styleA2);

            //--- A3セルへの書き込み --//
            //--- セル背景色は緑 --//
            row = sheet.createRow(2);
            cell = row.createCell(0);
            cell.setCellValue("ううう");
            CellStyle styleA3 = tempbook.createCellStyle();
            styleA3.setFillPattern(
                FillPatternType.SOLID_FOREGROUND);
            styleA3.setFillForegroundColor(
                IndexedColors.GREEN.getIndex());
            cell.setCellStyle(styleA3);

            //--- out.xlsxとしてファイル出力 --//
            Path outPath = Paths.get("./out.xlsx");
            OutputStream outSt = Files.newOutputStream(outPath);
            tempbook.write(outSt);
        } catch (IOException e) {
            System.out.print("入出力例外が発生!");
        } finally {
            //--- テンプレートをクローズ --//
            try {
                if (tempbook != null) {
                    tempbook.close();
                }
            } catch (IOException e) {
                System.out.print("終了処理で入出力例外が発生!");
            }
        }
        System.out.print("end: main\r\n");
    }
}

このプログラムを実行すると、以下のエクセル(out.xlsx)が出力されます。

ApachePOIを使用したエクセルの出力

では、ポイントを説明していきます。

エクセルの読み込み・書き込み

Apahce POIは「XSSFWorkbook」というクラスでエクセルファイル(ブック)を管理します。

このファイルにInputStreamで読み込んだエクセルファイルを食わせてあげるだけですね。


    Path tempPath = Paths.get("./template.xlsx");
    InputStream inSt = Files.newInputStream(tempPath);
    tempbook = new XSSFWorkbook(inSt);
    Sheet sheet = tempbook.getSheet("Sheet1");

一番最後の「getSheet」は、対象となるシートを指定しています。

“Sheet1をカレントにしている”という感じですね。

セルの指定と文字列書き込み

行(row)と列(colum)を指定する形でセルを特定し、文字列出力などの操作をおこないます。

普段使っているエクセルでは、行は1始まりの番号で、列はAから始まるアルファベットですが、Apache POIは両方とも0オリジンの数値指定です。


    //--- A1セルへの書き込み --//
    //--- セル背景色は栗色 --//
    Row row = sheet.createRow(0);
    Cell cell = row.createCell(0);
    cell.setCellValue("あああ");

上はサンプルコードの一部抜粋ですが、このプログラムで、エクセルのA1セルに”あああ”という文字列を出力しています。

色の指定(スタイル指定)

セルに対する色指定は、スタイル指定という方法で可能です。

サンプルコードでは背景色を設定しています。


    CellStyle styleA1 = tempbook.createCellStyle();
    styleA1.setFillPattern(FillPatternType.SOLID_FOREGROUND);
    styleA1.setFillForegroundColor(IndexedColors.MAROON.getIndex());
    cell.setCellStyle(styleA1);

背景色の設定は、『塗り潰しパターン』と『色』を指定することで設定可能です。

『塗り潰しパターン』は、CellStyle クラスのsetFillPatternメソッドで変更可能です。

設定する値は、FillPatternTypeクラスに列挙型として定義されているようです。


NO_FILL

SOLID_FOREGROUND

FINE_DOTS

ALT_BARS

SPARSE_DOT

THICK_HORZ_BANDS

THICK_VERT_BANDS

THICK_BACKWARD_DIAG

THICK_FORWARD_DIAG

BIG_SPOTS

BRICKS

THIN_HORZ_BANDS

THIN_VERT_BANDS

THIN_BACKWARD_DIAG

THIN_FORWARD_DIAG

SQUARES

DIAMONDS

LESS_DOTS

LEAST_DOTS


試しに塗りつぶしパターンを「DIAMONDS」にしてみます。

そうすると、ちょっと出力結果が変わってきます。



格子上の塗りつぶしになりました。

これってつまり、エクセルのセルの書式設定で変更できるやつ、ですね。


FillPatternTypeをDIAMONDに指定

『色』は、CellStyle クラスのsetFillForegroundColorメソッドで変更可能です。

色については、「IndexedColors」に定義されている列挙型で定義されている色のインデックスを指定します。


AQUA

AUTOMATIC

BLACK

BLACK1

BLUE

BLUE_GREY

BLUE1

BRIGHT_GREEN

BRIGHT_GREEN1

BROWN

CORAL

CORNFLOWER_BLUE

DARK_BLUE

DARK_GREEN

DARK_RED

DARK_TEAL

DARK_YELLOW

GOLD

GREEN

GREY_25_PERCENT

GREY_40_PERCENT

GREY_50_PERCENT

GREY_80_PERCENT

INDIGO

LAVENDER

LEMON_CHIFFON

LIGHT_BLUE

LIGHT_CORNFLOWER_BLUE

LIGHT_GREEN

LIGHT_ORANGE

LIGHT_TURQUOISE

LIGHT_TURQUOISE1

LIGHT_YELLOW

LIME

MAROON

OLIVE_GREEN

ORANGE

ORCHID

PALE_BLUE

PINK

PINK1

PLUM

REDRED1

ROSE

ROYAL_BLUE

SEA_GREEN

SKY_BLUE

TAN

TEAL

TURQUOISE

TURQUOISE1

VIOLET

WHITE

WHITE1

YELLOW

YELLOW1

 


どんな色かは、名前からだいたいで察してもらえればと。

まとめ

いかがでしたでしょうか?

Apache POIの基本的な使い方と、セルの色設定方法についてわかって頂いたかと思います。



まとめ
  • Javaでエクセルを操作するためには、Apache POIをつかうべき!
  • Apache POIを使えば、エクセルへの文字列出力だけではなく、色設定も簡単におこなうことができる

それではまた!



Web画面での時間入力インターフェース!timedropperを使い倒してみる!

カレンダー

Webシステムの開発をおこなっていく上でよく必要となるのは、”日付入力””時間入力”のインターフェースです。

JavaScript(JQuery)を使って入力インターフェースを作るケースがほとんどかと思います。


メジャーなところでは、「DatePicker」「DateTimePicker」あたりですかね?

DatePicker
DateTimePicker

他にも「Material DatePicker」「pickadate」があり、各々で特徴があります。

しかし、Web画面のデザイン次第ではカレンダー形式ではない日付・時間の入力が必要となる場合があります。


という訳で今回は、「timedropper」を使ってみたいと思います。ちょっと面白いインターフェースです。

また、オプションについて一覧形式でまとまっているサイトがなかったので、まとめてみました。


timedropperを使ってみる

とりあえず動かしちゃいましょう。

サンプルソースコードと、サンプルソースコードで動作するインターフェースは以下になります。


サンプルはこちら



    timedropper
    
    
    


    
    


timedropperのサンプル

おもしろいインターフェースで、アナログ時計の意識したインターフェースになります。


バルーンが、アナログ時計での長針・短針になっています。
時間(Hour)を変更したい場合は時間(Hour)をクリックしてバルーンを動かします。

分(Minutes)も同様です。

timedropperの使い方

timedropperには、いくつかのオプションが用意されています。

解り易いオプションもあれば解り辛いオプションもあるのですが、使用方法含めて紹介していきます。

timedropperの基本的なオプション

まずは基本的なオプションを使ってみます。

色系ですね。

一覧でまとまっているサイトを見つけることができなかったので、まとめてみました。


オプション名

日本語名

デフォルト

説明

primaryColor

主色

#1977CC

バルーンで選択中の時・分の色です。

textColor

文字色

#555

バルーンで選択していない時・分の色です。

backgroundColor

背景色

#FFFFFF

背景は全てこの色になります。

“バルーン部分だけ別の色”というのは、オプションではできないようです。

borderColor

枠線色

#1977CC

枠線は全てこの色になります。

 

 

 

 

 

上記のオプションを実際に設定して動かしてみましょう。

色が自由に設定できるので、印象が違ってきますね。


基本的なオプションを指定したサンプルはこちら




    timedropper
    
    
    


    
    



基本的なオプションを指定したtimedropper

timedropperの応用オプション

色以外のオプションもあります。

あまり豊富ではありませんが、ちょっとしたカスタマイズができます。


オプション名

日本語名

デフォルト

説明

autoswitch

自動補正

false

時・分を切り替えた時に、バーン位置を自動的に選択位置に補正します。

meridians

12時間表記

false

24時間表記ではなく、12時間表記にします。

時計部分に、「AM」「PM」が表示されます。

format

時間のフォーマット

h:mm a

選択した時刻の表示フォーマット。

mousewheel

マウスホイールによる変更

false

マウスホイールによる変更を許可します。

init_animation

初期表示時のアニメーション

fadein

dropdown:上から下にフェードイン

※他にあるんですかね?すいません。見つけきれませんでした。。。

setCurrentTime

現在時刻の設定

true

デフォルトで現在時刻を設定するか。


上記のオプションを設定してみます。

formatは助かりますね。

よく使うと思います。

応用オプションを指定したサンプルはこちら




    timedropper
    
    
    


    
    




timedropperの応用オプション設定

まとめ

いかがでしたでしょうか?

timedropperのオプションは全て網羅しているかと思います。

もし、timedropperを使うことがあった場合は、ぜひ参考にして頂ければと思います。



トップページをカッコ良くしたい!Content Viewsを使って記事一覧を表示する。

記事一覧

こんにちは。
さくさくTECHブロガーの「さく」です。


いきなりなのですが、本ブログはWordPressで作っています。

テーマは「Sparkling」なのですが、デフォルトのトップページは直近10件の記事がただ表示されているだけでした。

“なんか恰好悪いなー”と思いまして。。。

今回は、WordPressのプラグインである「Content Views」を使用してトップページをカッコいい記事一覧にする方法を紹介します。


トップページの記事表示方法が変わると、サイト全体の印象が違ってきますからね。

こだわりたいところです。

Content Views(プラグイン)をインストール

まずはWordPressのプラグインであるContent Viewsをインストールします。

通常のWordPressプラグインインストールと手順は同じですね。


左メニューのプラグイン→新規追加を選択します。


プラグインの新規追加

キーワードに「Content Views」を入力して検索すると「Content Views – Post Grid & List for WordPress」が表示されるので、「今すぐインストール」を押下してインストールをおこいます。


ContentViewsのインストール

インストールが完了したら「有効化」ボタンを押下します。


ContentViewsの有効化

これで、Content Viewsが使える状態になりました。


記事リストを作成する

Content Viewsの使い方として、「記事リスト」という一覧表示テンプレートを作成して、そのテンプレートのタグを記事に埋め込む、という流れになりまます。


という訳で、早速記事リストを作成します。

まずは、記事リストのテンプレートを作成します。

Cotent Views → 新規追加を選択します。

 

ContentViewsの新規追加

まずはタイトルを入力します。

今回はトップページの記事一覧を作成するので、「トップページ記事一覧」とします。

タイトルの入力

次に、一覧の設定をおこなっていきます。

Content Viewsの設定は、「Filter Settings」「Display Settings」の2つになります。

Filter Settings

記事一覧を表示するためのフィルタ設定(絞込み設定)をおこなっていきます。

「Content Type」は、投稿ページと固定ページのどちらを一覧表示するかを設定します。

トップページは投稿記事を一覧表示したいので、「投稿ページ」を選択します。


ContentTypeの設定

Commonは、記事一覧の共通設定が可能です。

「Include Only」は、一覧に表示する記事のIDをカンマ区切り指定が可能です。

今回は新着記事を表示したいので空欄のままにします。



「Exclude」は、一覧から除外する記事のIDをカンマ区切り指定が可能です。
こちらも今回は空欄のままにします。


「Limit」は最大表示件数です。
特にこだわりもないですが、今回は10件とします。


Commonの設定

「Advance」は、表示する記事の表示条件を設定することができます。


  • Taxonomy (カテゴリー, タグ…)

Taxonomyは、特定のカテゴリーやタグの記事のみを一覧表示するための設定となります。

チェックをつけると、カテゴリーやタグの絞込み条件が表示されます。

今回は特に絞込みはおこなわないので、何も設定しないことにします。


  • ステータス

ステータスは、特定ステータスの記事のみを一覧表示するための設定となります。

ステータスとは、公開済・下書き、といった記事のステータスとなります。

今回は公開済記事のみを表示したいので、「公開済」を選択します。


  • Sort by

Sort by は記事の表示順になります。

今回は、公開日時の降順とします。

新しい記事が最初になる設定です。


  • キーワード

キーワードは、特定キーワードを含む記事のみを一覧表示するための設定となります。

今回は特に設定しません。


  • 作成者

作成者は、特定作成者の記事を表示、もしくは、特定作成者以外の記事を表示するための設定となります。

今回は特に作成者での絞込みは不要なので設定しません。


ここまで設定したら保存ボタンを押下して終了です。


Adbanceの設定ウィンドウ

Display Setting

Display Settingで記事の表示設定をおこなっていきます。


  • Layout

Layoutは記事のレイアウトになります。

今回はGridを選択します。

以下のような、格子状の表示となります。


LayoutがGrid

今回はGridを使用しますが、他設定も紹介しておきます。

Collapsible List は、タイトルをクリックすると記事概要の表示がおこなわれるレイアウトです。


Collapsible List

Scrollable Listは、横スライダーの表示のレイアウトです。


Scrollable List

Items per row は、1行あたりの表示数です。

今回は、2とします。

最初の例の通り、1行あたりに記事を2つ表示します。


  • Responsive

Responsiveは、モバイル端末での表示設定になります。

1行あたりの表示設定を、タブレットとモバイル(スマートフォン)で設定できます。

今回は、タブレットを2、モバイルを1とします。


Responsiveの設定

  • Format

Formatは、Grid表示のフォーマットを設定します。

Show thumbnail & text vertically は、上部にサムネイルで下に説明文、になります。

Layoutの説明で記載した通りになります。

Show thumbnail on the left/right of textは、サムネイル画像の左右にテキストを表示できます。

今回は、Show thumbnail & text verticallyとします。


  • Fields settings

Fields settings は、一覧に表示する要素を指定することができます。

Show Thumbnail(サムネイル表示)、Show Title(タイトル表示)、Show Content(説明文表示)、Show Meta Fields(メタ表示)の4つになります。

今回は、全て表示することにします。


Fields setting

  • タイトル

記事一覧のHTMLタグの設定になります。

筆者のブログの構成上、今回は「h2」が最適だと判断しましたので(トップページはh1しかなかったので。。。)「h2」を設定します。

タイトルのHTMLタグ

  • サムネイル

サムネイルは、記事一覧のサムネイル画像について設定できます。

今回は、サムネイル画像のサイズはMedium(300 × 300)を設定します。

WordPressのサムネイル画像を無効にできる設定もありますが、今回は無効にしないことにします。

サムネイ画像の設定

  • 内容

内容は、記事の説明文に関する表示設定をおこなうことができます。

今回は、出力文字は30文字、記事へのアンカー名は”More”にします。

説明文のHTMLタグも許可します。

記事の内容の設定

  • Meta Fields

Meta Fields で、表示するメタの内容を選択できます。

今回は、公開日とカテゴリー・タグのみを表示します。

メタの表示

記事一覧の固定ページ作成 

記事一覧のテンプレートは作成できたので、次に、記事一覧を表示するトップページを作成します。

トップページは固定ページで作成します。

固定ページ→新規追加 を選択し、固定ページの新規追加ウィンドウを表示します。


固定ページの新規追加

固定ページには、タイトルと記事一覧を表示するためのコードを記載します。


固定ページの内容

記事一覧を表示するためのコードは、Content Viewsの設定画面からコピーしてペーストします。

まず、Content Views → AllViews で一覧を表示します。

ContentViewsのAllViews

一覧を表示すると「ショートコード」が表示されています。

のショートコードをコピーして貼り付けるだけで、記事一覧が表示されます。


ContentViewsのショートコード

固定ページが完成したらプレビューで確認し、公開ボタンで公開しておきます。


固定ページをトップページに設定


最後に、作成した固定ページをトップページに設定します。

設定→表示設定を選択して、表示設定ウィンドウを開きます。


表示設定ウィンドウをひらく

ホームページの設定で、ホームページについて前手順で作成した固定ページを選択します。


トップページの設定変更

最後に「変更を保存」を押下すれば設定完了です。

トップページを表示してみてください。

トップページが、下のようにサムネイル付き記事一覧になっていれば設定完了です。


記事一覧のトップページ

最後に

いかがでしたでしょうか?

ここまで説明した方法で、トップページを記事一覧のページにすることができます。

まとめ
  • トップページをかっこいい記事一覧にするためには、Contet Viewsを使うと便利!
  • トップページは固定ページとして作成し、Content Viewsで作った記事一覧のタグを埋め込むことで記事一覧を表示可能

今回はトップページの記事一覧表示について説明しましたが、Content Viewsのレイアウトを設定すれば、他箇所(例えばサイドバー、など)に組み込む一覧パーツも作成可能です。


それではまた!


アイキャッチ画像の位置をタイトルの下に変更する方法

WordPress

WordPressの記事にアイキャッチ画像を設定している人は多いかと思います。

多いというよりも、もはや設定するのは常識ですね。

記事の見栄えも良くなるので、読者の興味を引きやすいです。


僕もWordPressでブログを立ち上げて記事を投稿していくなかで、”そろそろアイキャッチ設定するかなー”と思い、アイキャッチ画像をアップロードしたのですが、アイキャッチ画像がタイトルの上に表示されました。

アイキャッチ画像のデフォルト位置

好みかもしれませんが、”アイキャッチ画像はタイトルの下でしょ”って思いませんかね?

なんとなく、タイトルの上に画像だと記事の収まりが悪いといいますか。。。


では修正しよう!と思っても、この位置を変更するのは、WordPressに慣れていない人や、PHP初心者の方には難しい部分があります。


今回は、WordPress・PHP初心者の方もアイキャッチ画像位置の変更がおこなえるように、変更方法を説明していきます。



アイキャッチ画像とは

アイキャッチ画像とは、その名の通りアイ(ユーザの目線を)キャッチ(引き付ける)画像です。


ユーザが検索結果から様々な記事をみていく中で、”この記事を読んでみよう”と興味を持ってもらう必要があります。

 

そういった目的の中では、文字よりも画像の方が効果が大きいです。

アイキャッチ画像の設定は必須と思った方がよく、よりユーザ集客に効果的な画像を設定することが重要になります。


アイキャッチ画像位置を変更する

アイキャッチ画像の位置を修正するには、記事を構成するPHPファイルを修正する必要があります。


PHPファイルはWordPressのダッシュボードから修正可能ですが、今回は以下の流れでPHPファイルの修正をおこないます。


  1. SSHでサーバに接続して修正ファイルをバックアップ
  2. WordPressでPHPファイルを修正する

SSHでサーバに接続して修正ファイルをバックアップ 

PHPファイルを修正する際、バックアップを行うことを推奨します。

もし、修正を間違えるとWebページ自体が表示されなくなる可能性があります。


この場合、PHPファイルをバックアップしていれば元に戻すことは可能ですが、バックアップしていなければ元に戻すことができなくなる可能性があります。


という訳で、バックアップをおこないます。

僕のブログのWordPressは、ロリポップレンタルサーバ上で動作しているのですが、SSHが無料で使えます。


なので、WinScpを使用してSSHでサーバに接続します。

  • WordPress:WordPress5.2
  • テーマ:Sparkling

SSHでサーバに接続し、テーマ(Sparkling)のcontent-single.phpを確認します。

content-single.phpの格納場所

バックアップするファイルは以下になります。

  • フォルダ:/wp-content/themes/sparkling/template-parts
  • ファイル:content-single.php

パスをみて気が付くかもしれませんが、バックアップするのはテーマ(Sparkling)の中のPHPファイルになります。

このファイルを作業しているパソコンにダウンロードしておきましょう。


これで、バックアップ完了です。

アイキャッチ画像の位置変更作業で元に戻す必要が出てきた場合は、バックアップしたファイルに戻してください。

アイキャッチ画像位置を変更する

それではアイキャッチ画像の位置を変更してみます。


content-single.phpを直接してもよいのですが、今回はWordPressのダッシュボードから修正をおこないます


今回は、以下のように変更をおこないます。

  • アイキャッチ画像をタイトルの下にする

content-single.phpの修正画面をWordPressのダッシュボードで開きます。

まずは、テーマの更新ウィンドウをひらきます。

テーマエディタのひらきかた

テーマエディタが開いたら、右メニューでcontent-single.phpを選択します。

ダッシュボードでcontent-singleをひらく

アイキャッチ画像は、以下のコードで表示しています。

6行目から12行目の部分です。

<article id="post-<?php the_ID(); >" <?php post_class(); ?>
    <?php
    $featured_image_args = array(
        'class' =&amp;amp;gt; 'single-featured',
    );
    if ( is_page_template('page-fullwidth.php') ) {
        the_post_thumbnail(
       '    sparkling-featured-fullwidth', $featured_image_args);
    } else {
        the_post_thumbnail(
            'sparkling-featured', $featured_image_args);
    }
    >


the_post_thumbnailでアイキャッチ画像を表示しています。

このコードをタイトルの下に移動すればよいです。

正確には、メタ情報(作成日時、作成者、など)の下に移動します。


変更後のcontent-single.phpは以下になります。(一部抜粋)

<div class="post-inner-content">
<header class="entry-header page-header">
<h1 class="entry-title "><?php the_title(); ?></h1>
<div class="entry-meta">
<?php sparkling_posted_on(); ?>
<?php
    $categories_list = 
        get_the_category_list(esc_html__( ', ', 'sparkling' ) );
    if ( $categories_list && sparkling_categorized_blog() ) :
    ?>
    <span class="cat-links"><i class="fa fa-folder-open"></i>
    <?php printf( esc_html__(
        ' %1$s', 'sparkling'), $categories_list ); ?>
    </span>
    <?php endif; // End if categories ?>
    <?php if ( get_edit_post_link() ) : ?>
    <?php
        edit_post_link(
            sprintf(
            /* translators: %s: Name of current post */
            esc_html__( 'Edit %s', 'sparkling' ),
            the_title(
                '<span class="screen-reader-text">"', '"</span>', false )
            ),
            '<i class="fa fa-edit"></i><span class="edit-link">',
            '</span>'
        );
 ?>
<?php endif; ?>
</div><!-- .entry-meta -->
</header><!-- .entry-header -->
<?php
    $featured_image_args = array(
        'class' => 'single-featured',
    );
    if ( is_page_template( 'page-fullwidth.php' ) ) {
        the_post_thumbnail(
            'sparkling-featured-fullwidth', $featured_image_args);
    } else {
        the_post_thumbnail(
           'sparkling-featured', $featured_image_args);
    }
?>
<div class="entry-content">

34行目から43行目までがアイキャッチ画像の表示部分です。

その直前がメタ情報、直後がコンテンツ本体です。


最後に、ファイルを更新ボタンを押下すれば更新完了です。

content-single.phpの更新方法

変更後のアイキャッチ画像位置を確認

ここまでの作業でアイキャッチ画像の位置は変更されています。


既にアイキャッチ画像が設定されている記事を確認してみてください。

アイキャッチ画像がタイトルの下(正確にはメタ情報の下)になっていれば、更新完了です。

アイキャッチ画像位置の変更後

固定ページのアイキャッチ画像位置を変更する


「content-single.php」の修正をおこなうと投稿ページのアイキャッチ画像位置はタイトル下になるのですが、固定ページのアイキャッチ画像位置は変更されません。
変わらず、タイトルの上にアイキャッチ画像が表示されます。


固定ページのアイキャッチ画像位置を修正するには、「content-page.php」を修正する必要があります。
「content-single.php」の時と同じようにテーマエディタと「content-page.php」をひらきます。

content-page.phpをテーマエディタでひらく

<h1>~</h1>を囲んでいる<head>~</head>の上にサムネイル表示処理が記載されていると思います。
以下のように。

<?php
if ( is_page_template( 'page-fullwidth.php' ) ) {
    the_post_thumbnail(
        'sparkling-featured-fullwidth', array(
            'class' => 'single-featured',
        )
    );
} else {
    the_post_thumbnail(
        'sparkling-featured', array(
            'class' => 'single-featured',
        )
    );
}
?>

<div class="post-inner-content">
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    <header class="entry-header page-header">
        <h1 class="entry-title"><?php the_title(); ?></h1>
    </header><!-- .entry-header -->

これは以下のように修正します。
<head>~</head>の下に、サムネイル画像表示処理を記載するように変更します。

    <header class="entry-header page-header">
        <h1 class="entry-title"><?php the_title(); ?></h1>
    </header><!-- .entry-header -->
<?php
if ( is_page_template( 'page-fullwidth.php' ) ) {
    the_post_thumbnail(
        'sparkling-featured-fullwidth', array(
            'class' => 'single-featured',
        )
    );
} else {
    the_post_thumbnail(
        'sparkling-featured', array(
            'class' => 'single-featured',
        )
    );
}
?>

上記のように対応することで、固定ページもタイトルの位置にアイキャッチ画像が表示されるようになります。


月毎・カテゴリ毎・タグ毎ページのアイキャッチ画像位置を変更する


ここまでの説明でPHPファイルを修正しとしても、月毎・カテゴリ毎・タグ毎といった、集約ページのアイキャッチ画像位置は修正されていません。
集約ページのアイキャッチ画像位置を修正するには、「content.php」を修正する必要があります。

content.phpを修正

集約ページは、選択した月やカテゴリ・タグが<h1>~</h1>で使用されます。
タイトルは<h2>~</h2>となります。


なので、サムネイル画像を<h2>~</h2>の下に移動します。


変更前は以下のPHPファイルになります。
<h2>~</h2>の上にサムネイル画像表示処理が記載されています。

        <?php
        if ( is_page_template( 'page-fullwidth.php' ) ) {
            the_post_thumbnail(
                'sparkling-featured-fullwidth', array(
                    'class' => 'single-featured',
                )
            );
        } else {
            the_post_thumbnail(
                'sparkling-featured', array(
                    'class' => 'single-featured',
                )
            );
        }
        ?>
    </a>
<div class="post-inner-content">
    <header class="entry-header page-header">
        <h2 class="entry-title"><a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?></a></h2>

サムネイル画像表示処理を、<h2>~</h2>の下に変更します。

<div class="post-inner-content">
    <header class="entry-header page-header">

        <h2 class="entry-title"><a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
        <?php
        if ( is_page_template( 'page-fullwidth.php' ) ) {
            the_post_thumbnail(
                'sparkling-featured-fullwidth', array(
                    'class' => 'single-featured',
                )
            );
        } else {
            the_post_thumbnail(
                'sparkling-featured', array(
                    'class' => 'single-featured',
                )
            );
        }
        ?>

上記のように対応することで、集約ページもタイトルの位置にアイキャッチ画像が表示されるようになります。


まとめ

いかがでしたでしょうか?

アイキャッチ画像位置の変更できたかと思います。

まとめ
  • アイキャッチ画像は、デフォルトでタイトルの上に表示される。
  • アイキャッチ画像の位置を変更するには、PHPファイルを修正する必要あり。

僕のWordPressのテーマはSparklingですが、他テーマも基本的な変更方法は同じです。

アイキャッチ画像の活用にお役に立てればと思います。


それではまた!