CSSしかわからない女子大生がWPでユーザー投稿型アイテム検索サイトをつくった話


この記事はわたしのつくったフロントエンド投稿+投稿を様々な条件から検索できるサイトの仕組みを、使用したプラグインを紹介しつつざっくり解説するものです。

http://vroid.wear-virtual.com/
具体的にはBOOTHで販売されているバーチャルファッションアイテムの価格やカテゴリをフォームを埋めて送信し、自動でサイトに記事として投稿&カテゴリや価格など複数の検索を可能としたサイトです。フロントエンドからユーザーに直接アイテムを登録してもらうだけでなく、管理者の方でCSVをインポートして一括登録もできます。

タイトルの通り、わたしは制作当初HTMLとCSSしか使えず、phpとjsについてはプログラミング言語であるということしか知りませんでした。しかもCSSが使えるというのも【ブログカスタマイズ】とついてる記事のCSSコードのセレクタやプロパティの値がちょっといじれるというガバガバ判定です。そんな自分でもなんかすごいサイトがつくれたんだからワードプレスは神です。

すごいサイトなのですが、いくつか運営の効率上問題があったり時間の都合がとれないためこのサイトのこれ以上のアップデートをやめることにしました。せめてわたしがググって悩んで頑張って完成させた過程が誰かの役に立てばいいなと思い投稿に至りました。

大まかなサイトの仕組み


ざっくり言うと、
1.User Frontendでログイン無しで投稿&編集ができるフォームをつくる
2.1で入力したカスタムフィールド値をサイトに表示させるためにfunctions.phpをいじる
3.WP Custom Fields Searchでカスタムフィールド値から検索できるウィジェットをつくる

感じです。このほかにもサイト内お気に入り機能やCSVによる一括登録、Twitter連携によるログインなども機能として存在しますが、すべての実装方法を一気に解説するのは心が折れるので、今回はタイトル通りユーザー投稿と検索機能の実装方法のみ書くことにします。

1UserFrontendを使ってフォームを作成する

プラグイン>新規追加>プラグインの検索で「UserFrontend」と打てばでてきます。

UserFrontend>PostFormから作成できます。

右のMetaKeyに入力した文字がカスタムフィールド名になります。この画像でいうとフォームに入力したブランド名は{name} に格納されるということです。Field Labelが英数字の場合は自動的にMetaKeyもおなじ文字が入りますが、日本語を使うとうまく行かないみたいです。自分でカスタムフィールド名を入力する必要がでてきます。

Settingから送信した内容はどの投稿タイプか、公開済みにするか、レビュー待ちにするかなどが選択できます。完成したら右上のSaveFormをクリックしてショートコードをコピー、固定ページに貼り付けてそのまま公開すると、ログインしていないユーザーでも投稿フォームを使えるようになります。

2カスタムフィールド値をphpをいじって表示する

カスタムフィールド値の出力方法は以下の通りです。
<?php echo post_custom('カスタムフィールド名');?>
(いまでもphpはよくわからないのでちゃんと解説できません。ごめんなさい)
1でいうとブランド名を表示するなら<?php echo post_custom('{name}');?>ということです。わたしはWPテーマ「SANGO」を使っているので子テーマのfunctions.phpに以下を追加、記事一覧で表示されるタイトルや画像にプラスでカスタムフィールド値をつけたしています。参考程度に眺めてみてください。

記事を{rida}に格納されたURLにリダイレクト

function page_redirect(){
  global $post;
  $output = "";
  $series = get_post_meta($post->ID, '{rida}', true);
  if(is_single()){
    if($series) {
        wp_redirect( $series , 301);
        exit;
    }
  }
}
add_action( 'get_header', 'page_redirect' );
記事一覧で表示される情報にカスタムフィールド値を追加
function sng_normal_card()
  { ?>
  <article class="cardtype__article">
    <a class="cardtype__link" href="<?php echo post_custom('{rida}');?>"target="_blank" rel="noopener noreferrer">
      <p class="cardtype__img">
        <img src="<?php echo featured_image_src('thumb-520'); ?>" alt="<?php the_title();?>">
      </p>
      <div class="daikate">
      <?php echo post_custom('{syo}');?>
      </div>
      <div class="cardtype__article-info">
          <?php if (!get_option('remove_pubdate')): ?>
          <?php endif;?><h2><?php the_title();?> <p class="neda">¥<?php echo post_custom('{nada}');?></p></h2>
      </div>
    </a>
  <?php
    // カテゴリーを出力
    if (!is_archive()) {
      output_catogry_link();
    }
    // newマーク
    newmark();
  ?><p class="burand"><?php echo post_custom('{name}');?></p><p class="gazou"><button class="simplefavorite-button preset" data-postid="<?php the_ID(); ?>" data-siteid="1" data-groupid="1" data-favoritecount="1" style=""><i class="sf-icon-favorite"></i> Favorite</button>
     <a href="http://vroid.wear-virtual.com/edit?pid=<?php the_ID(); ?>&amp;_wpnonce=bbde596489"><img class="alignnone wp-image-7195 size-full" src="http://vroid.wear-virtual.com/wp-content/uploads/2019/10/編集.png" alt="" width="20" height="20" /></a> <a href="<?php echo post_custom('提供URL');?>" target="_blank" rel="noopener"></a>
</article><?php
}
function sng_card_link($atts)
{$id=substr($atts['id'], -4);
  $output = '';
  if ($id) {
    $ids = (explode(',', $id)); //一旦配列に
  }
  $target = isset($atts['target']) ? ' target="_blank"' : "";
  if (isset($ids)) {
    foreach ($ids as $eachid) {
      $img = (get_the_post_thumbnail($eachid)) ? get_the_post_thumbnail($eachid, 'thumb-300') : '<img src="' . featured_image_src('thumb-300', $eachid) . '">';
     $url = esc_url(get_permalink($eachid)); //URL
      $title = esc_attr(get_the_title($eachid));
      $burando = get_field('{name}',$id);
      $onedan = get_field('{nada}',$id);
      $toko = get_field('toko',$id);
      if ($url && $title) {
          $output .= <<<EOF
        <a class="c_linkto" href="{$url}"target="_blank" rel="noopener"}>
        <span>{$img}</span><span class="c_linkto_text">{$title}</span><span class="onedan">{$onedan}円</span>
        <span class="burando">{$burando}{$toko}</span>
        </a>
EOF;
      } //endif
    } //endforeach
  } else { $output = '';}
  return $output;
} //END get_entry_link

クラス名が適当、色々汚いのは見逃してください

3WP Custom Fields Searchを使ってカスタムフィールド値から検索できるようにする

プラグイン>新規追加>プラグインの検索で「WP Custom Fields Search」と打てばでてきます。

歯車アイコンをクリックすると詳細が設定できます。ここに書いてあるショートコードをサイドバーのカスタムHTMLにコピペすると下のような検索ウィジェットを自動で表示してくれます。


編集画面はこんな感じ。ブランドは60近く登録してあってラジオボタンじゃ列数がやばくなるのでドロップダウン形式にして、完全一致(ExactMath)にしています。これだけで{name}に格納されている値全部がドロップダウン形式で表示されます。もしカスタムフィールド名に格納されている値で表示したくないものがあったら、さらに歯車アイコンをクリックして手動で選択もできます。

問題点1:seo的にリダイレクト多用はマズい

リダイレクトそのものはseo評価に影響はないようですが
記事内容(postcontent)が一切ない状態の記事が量産されることになるため、検索機能のみではGoogleの検索結果に載ることはかなり困難だと思います。表示はしないもののpostcontentに価格やブランド名、商品の説明文などをぶっこんでおくといいかもしれません。

問題点2:荒らし対策が大変

ログインなしで投稿できるため、荒らしが現れた場合の対処方法が難しいです。UserFrontendの画像アップロードボタンは一度選択しただけでサーバーにアップロードされてしまうためファイルサイズが大きい画像をイタズラでたくさんあげられようもんなら、重くなってしまいます。わたしのサイトには沸かないであろうとは思いましたが、不安だったので一応Twitter連携でログインした人しか投稿機能をつかえないようにしました。

運営してみた感想

一回システムをつくってしまえば放置、たまに変な投稿がないか見に行けばいいだけなので楽だなという感じです。ユーザー投稿と検索機能の面では自分の想像してたものがちゃんとつくれたのでよかったです。

ただ、人のショップサイト情報にカテゴリ情報を追加して画像をお借りするというサイトの性質上、セキュリティや規約に慎重になさざるをえず、画像使用の許可取りや投稿に関するルールの表記、荒らし対策など本来わたしがやりたいことではないことにたくさんの時間を割かなければならず、あまりに趣味で運営するには辛かったためこれ以上のアップデートをやめることにしました。(収益化して、誰か雇って大規模なサイトを作ろうかとも一瞬考えましたが、似たようなサイトで大手のバーチャルマーケットがあり、また規模が大きくなるにつれて画像の使用で問題が発生した場合に誰かと衝突して界隈に居づらくなるのが嫌だったのもあります)

サイトのデザインも標準SANGOから大幅に変更しており、自分の目指す「シンプル&スタイリッシュ」がまぁまぁ実現できたのではないかと思います。特にフォームデザイン、チェックボックスなどは標準のデザインを消してまるまる作り直したので時間はかかりましたが満足のいくできになりました。余白のとりかたが若干ダサくなってしまったのでそこだけ残念です。

じぶんが思う最強のおしゃれなファッションサイトがみたい一心でつくってきたので後悔はありません。前身となるVRoidCollectionから数えると約一年間かけてアップデートを重ねてきて、その中でたくさん成長することができました。

春から4年。就活時期です自分にWEB業界の適性があるのかはわからないけど、サイトづくりと運営はVRchatと同じくらい楽しいので多分やっていけるのではないかと勝手に考えてます。頑張ります!(謎の締め)