このガイドでは、プログラミング初心者〜中級者の方を対象に、自分のパソコンで「会社の備品の登録・編集・削除・一覧表示」ができるWebシステムを、基本から応用まで一気通貫で開発する手順を解説します。
このガイドで作るもの
- システム: 品名、管理者、保管場所、利用状況を管理できる備品管理システム
- 特徴: WordPressの投稿機能とは完全に分離された、備品専用のデータベーステーブルでデータを管理します。これにより、クリーンで高性能なデータ操作を実現します。
- 技術:
- Local: 簡単なWordPress開発環境
- PHP: データベーステーブルと専用API(データの対話窓口)の作成
- JavaScript: Webページ上の操作画面(UI)の構築
## ステップ1:開発環境の準備 (Localのインストール)
まず、開発の拠点となるWordPress環境を、自分のパソコンの中に簡単に構築できるツール「Local」を準備します。
- Localのダウンロード 公式サイト localwp.com にアクセスし、お使いのOS(Windows/Mac)用のインストーラーをダウンロードして、インストールします。
- 新しいサイトの作成
- Localを起動し、左下の「+」ボタン(Create a new site)をクリックします。
- サイト名(例:
bihin-system
)を入力し、「Continue」をクリックします。 - 環境設定は「Preferred」のままでOKです。「Continue」をクリックします。
- WordPressの管理者ユーザー名とパスワード、メールアドレスを設定します。これらは後でログインに使うので、忘れないようにメモしておきましょう。「Add Site」をクリックすると、数分であなた専用のWordPressサイトがPC内に作成されます。
- サイトへのアクセス
- サイトが作成されると、Localの画面右上に「WP Admin」「Open Site」というボタンが表示されます。
- WP Admin: WordPressの管理画面にログインするためのボタンです。
- Open Site: 実際に表示されるサイトを確認するためのボタンです。
これで、開発の土台となる環境準備は完了です。
## ステップ2:PHPで備品用の「データベーステーブル」と「専用API」を作る
ここが今回の核心です。プラグインに頼らず、PHPコードを書いて「データの器(データベーステーブル)」と「データの対話窓口(API)」の両方を作成します。
作業するファイル: この作業は、WordPressのテーマファイル内にある functions.php
というファイルで行います。
- ファイルの開き方: Localのサイト管理画面で、サイト名のすぐ下にあるパス(例:
/Users/yourname/Local Sites/bihin-system/app/public/
)をクリックしてフォルダを開きます。そこからwp-content
>themes
>twentytwentyfour
(または有効化しているテーマ) の中にあるfunctions.php
をテキストエディタで開きます。 - ⚠️ 注意: このファイルはWordPressの重要な設計図です。編集を間違えるとサイトが表示されなくなることがあるので、慎重に作業し、念のためファイルのコピーを取ってから始めましょう。
2.1 専用テーブルを作成するPHPコード
以下のPHPコードを、functions.php
ファイルの一番下にコピー&ペーストしてください。 このコードは、WordPressのデータベースに wp_bihin_master
という名前の備品専用テーブルがなければ作成する、という処理です。
/**
* 備品管理用のカスタムテーブルを作成する
*/
function create_bihin_custom_table() {
global $wpdb; // WordPressのデータベースを操作するためのグローバル変数
$table_name = $wpdb->prefix . 'bihin_master'; // テーブル名(wp_bihin_master となる)
$charset_collate = $wpdb->get_charset_collate();
// テーブルがなければ作成するSQL文
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
hinmei text NOT NULL,
kanrisha varchar(255) NOT NULL,
hokan_basho text,
riyou_joukyou varchar(55) DEFAULT '保管中' NOT NULL,
updated_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
// WordPressのデータベースアップグレード用関数を読み込む
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql ); // SQLを実行してテーブルの状態をチェック・更新
}
// WordPressのテーマが読み込まれた後に一度だけ実行する
add_action( 'after_setup_theme', 'create_bihin_custom_table' );
コードを貼り付けたらファイルを保存し、一度WordPressサイトを表示してください。 これでデータベース内にテーブルが作成されます。
2.2 専用APIを作成するPHPコード
次に、作成したテーブルとJavaScriptが対話するための「専用API」を作ります。このコードも、先ほどのコードの下に続けて functions.php
に貼り付けてください。
GET /items
: 備品一覧を取得POST /items
: 新しい備品を登録POST /items/{ID}
: 既存の備品を更新DELETE /items/{ID}
: 備品を削除
/**
* 備品管理用のカスタムAPIエンドポイントを作成する
*/
add_action( 'rest_api_init', function () {
$namespace = 'bihin-api/v1'; // APIのグループ名
// 備品一覧を取得 (GET)
register_rest_route( $namespace, '/items', [
'methods' => 'GET',
'callback' => 'get_all_bihin_items',
'permission_callback' => '__return_true', // 誰でも閲覧可能
]);
// 備品を新規登録 (POST)
register_rest_route( $namespace, '/items', [
'methods' => 'POST',
'callback' => 'create_bihin_item',
'permission_callback' => function () {
return current_user_can( 'edit_posts' ); // ログインユーザーのみ許可
},
]);
// 備品を更新 (POST)
register_rest_route( $namespace, '/items/(?P<id>\d+)', [
'methods' => 'POST',
'callback' => 'update_bihin_item',
'permission_callback' => function () {
return current_user_can( 'edit_posts' );
},
]);
// 備品を削除 (DELETE)
register_rest_route( $namespace, '/items/(?P<id>\d+)', [
'methods' => 'DELETE',
'callback' => 'delete_bihin_item',
'permission_callback' => function () {
return current_user_can( 'edit_posts' );
},
]);
});
// GET /items の処理
function get_all_bihin_items() {
global $wpdb;
$table_name = $wpdb->prefix . 'bihin_master';
$results = $wpdb->get_results( "SELECT * FROM $table_name ORDER BY id DESC" );
return new WP_REST_Response( $results, 200 );
}
// POST /items の処理
function create_bihin_item( $request ) {
global $wpdb;
$table_name = $wpdb->prefix . 'bihin_master';
$params = $request->get_json_params(); // 送信されたデータを取得
$wpdb->insert( $table_name, [
'hinmei' => sanitize_text_field( $params['hinmei'] ),
'kanrisha' => sanitize_text_field( $params['kanrisha'] ),
'hokan_basho' => sanitize_text_field( $params['hokan_basho'] ),
'riyou_joukyou' => sanitize_text_field( $params['riyou_joukyou'] ),
'updated_at' => current_time( 'mysql' ),
]);
return new WP_REST_Response( ['message' => '登録しました'], 201 );
}
// POST /items/{id} の処理
function update_bihin_item( $request ) {
global $wpdb;
$table_name = $wpdb->prefix . 'bihin_master';
$id = (int) $request['id'];
$params = $request->get_json_params();
$wpdb->update( $table_name, [
'hinmei' => sanitize_text_field( $params['hinmei'] ),
'kanrisha' => sanitize_text_field( $params['kanrisha'] ),
'hokan_basho' => sanitize_text_field( $params['hokan_basho'] ),
'riyou_joukyou' => sanitize_text_field( $params['riyou_joukyou'] ),
'updated_at' => current_time( 'mysql' ),
], ['id' => $id] );
return new WP_REST_Response( ['message' => '更新しました'], 200 );
}
// DELETE /items/{id} の処理
function delete_bihin_item( $request ) {
global $wpdb;
$table_name = $wpdb->prefix . 'bihin_master';
$id = (int) $request['id'];
$wpdb->delete( $table_name, ['id' => $id] );
return new WP_REST_Response( ['message' => '削除しました'], 200 );
}
ここまでで、システムの裏側(バックエンド)は完成です。
## ステップ3:操作画面の作成 (フロントエンド)
次に、ユーザーがブラウザで操作する画面を作ります。この作業は2段階に分かれます。
3.1 functions.php
:JavaScriptへ設定を渡す
まず、PHPからJavaScriptへ安全に情報を渡すための準備をします。 functions.php
ファイルの一番下に、以下のコードを追加して保存してください。このコードが、ページのヘッダーに必要なJavaScript変数を自動的に埋め込んでくれます。
/**
* フロントエンドのJavaScriptにAPI設定を渡す
*/
function my_script_vars() {
// '備品管理システム'というタイトルの固定ページの時だけ、このスクリプトを出力する
if ( is_page('備品管理システム') ) {
?>
<script>
// APIのURLと認証キーをJavaScriptのグローバル変数として定義
const WPApiSettings = {
root: "<?php echo esc_url_raw( rest_url() ); ?>",
nonce: "<?php echo wp_create_nonce( 'wp_rest' ); ?>"
};
const API_ENDPOINT = WPApiSettings.root + 'bihin-api/v1/items';
</script>
<?php
}
}
add_action( 'wp_head', 'my_script_vars' );
【ポイント】 is_page('備品管理システム')
の部分は、次のステップで作成する固定ページのタイトルと完全に一致させてください。
3.2 固定ページ:HTMLとJavaScriptで画面を組み立てる
- 固定ページの作成 WordPress管理画面の左メニュー「固定ページ」>「新規追加」をクリックし、タイトルを「備品管理システム」にします。
- コードの貼り付け 本文の入力エリアで、右上の「+」ボタンから「カスタムHTML」ブロックを選択します。そして、以下のコードを全てコピーして貼り付けてください。
<div id="bihin-form-container">
<h2 id="form-title">新しい備品を登録</h2>
<form id="bihin-form">
<input type="hidden" id="bihin-id" value="">
<div class="form-group">
<label for="hinmei">品名:</label>
<input type="text" id="hinmei" required>
</div>
<div class="form-group">
<label for="kanrisha">管理者:</label>
<input type="text" id="kanrisha" required>
</div>
<div class="form-group">
<label for="hokan-basho">保管場所:</label>
<input type="text" id="hokan-basho" required>
</div>
<div class="form-group">
<label for="riyou-joukyou">利用状況:</label>
<select id="riyou-joukyou">
<option value="保管中">保管中</option>
<option value="貸出中">貸出中</option>
<option value="修理・点検中">修理・点検中</option>
</select>
</div>
<div class="form-actions">
<button type="submit" id="submit-button">登録する</button>
<button type="button" id="cancel-edit-button" style="display:none;">キャンセル</button>
</div>
</form>
</div>
<hr>
<h2>備品一覧</h2>
<table id="bihin-list-table">
<thead>
<tr>
<th>品名</th>
<th>管理者</th>
<th>保管場所</th>
<th>利用状況</th>
<th>最終更新</th>
<th>操作</th>
</tr>
</thead>
<tbody id="bihin-list-body"></tbody>
</table>
<style>
#bihin-form-container { background: #f9f9f9; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
.form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; font-weight: bold; }
.form-group input, .form-group select { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; }
.form-actions button { padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; }
#submit-button { background-color: #0073aa; color: white; } #cancel-edit-button { background-color: #999; color: white; }
#bihin-list-table { width: 100%; border-collapse: collapse; }
#bihin-list-table th, #bihin-list-table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
#bihin-list-table th { background-color: #f2f2f2; }
.edit-btn, .delete-btn { margin-right: 5px; padding: 5px 10px; cursor: pointer; color: white; border: none; border-radius: 3px; }
.edit-btn { background-color: #2271b1; } .delete-btn { background-color: #d63638; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
// API設定は、functions.phpからwp_head経由で提供されます
const form = document.getElementById('bihin-form');
const formTitle = document.getElementById('form-title');
const bihinIdField = document.getElementById('bihin-id');
const hinmeiField = document.getElementById('hinmei');
const kanrishaField = document.getElementById('kanrisha');
const hokanBashoField = document.getElementById('hokan-basho');
const riyouJoukyouField = document.getElementById('riyou-joukyou');
const submitButton = document.getElementById('submit-button');
const cancelEditButton = document.getElementById('cancel-edit-button');
const bihinListBody = document.getElementById('bihin-list-body');
// ■ 備品リストを取得して表示
async function fetchBihinList() {
bihinListBody.innerHTML = '<tr><td colspan="6">読み込み中...</td></tr>';
try {
const response = await fetch(API_ENDPOINT);
if (!response.ok) throw new Error('データ取得失敗');
const bihins = await response.json();
bihinListBody.innerHTML = '';
bihins.forEach(bihin => {
const row = `
<tr data-id="${bihin.id}">
<td>${bihin.hinmei}</td>
<td>${bihin.kanrisha}</td>
<td>${bihin.hokan_basho}</td>
<td>${bihin.riyou_joukyou}</td>
<td>${new Date(bihin.updated_at).toLocaleString('ja-JP')}</td>
<td>
<button class="edit-btn" data-id="${bihin.id}">編集</button>
<button class="delete-btn" data-id="${bihin.id}">削除</button>
</td>
</tr>
`;
bihinListBody.insertAdjacentHTML('beforeend', row);
});
} catch (error) {
bihinListBody.innerHTML = `<tr><td colspan="6">${error.message}</td></tr>`;
}
}
// ■ フォーム送信時の処理
form.addEventListener('submit', async function(event) {
event.preventDefault();
const bihinId = bihinIdField.value;
const isEditing = bihinId !== '';
const data = {
hinmei: hinmeiField.value,
kanrisha: kanrishaField.value,
hokan_basho: hokanBashoField.value,
riyou_joukyou: riyouJoukyouField.value
};
const url = isEditing ? `${API_ENDPOINT}/${bihinId}` : API_ENDPOINT;
try {
const response = await fetch(url, {
method: 'POST', // 更新もPOSTで行う
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': WPApiSettings.nonce
},
body: JSON.stringify(data)
});
if (!response.ok) throw new Error('処理に失敗しました。');
const result = await response.json();
alert(result.message);
resetForm();
fetchBihinList();
} catch (error) {
alert(error.message);
}
});
// ■ 編集・削除ボタンの処理
bihinListBody.addEventListener('click', async function(event) {
const target = event.target;
const id = target.dataset.id;
// 削除
if (target.classList.contains('delete-btn')) {
if (!confirm('本当にこの備品を削除しますか?')) return;
try {
const response = await fetch(`${API_ENDPOINT}/${id}`, {
method: 'DELETE',
headers: { 'X-WP-Nonce': WPApiSettings.nonce }
});
if (!response.ok) throw new Error('削除失敗');
const result = await response.json();
alert(result.message);
fetchBihinList();
} catch(error) {
alert(error.message);
}
}
// 編集
if (target.classList.contains('edit-btn')) {
const row = target.closest('tr');
bihinIdField.value = id;
hinmeiField.value = row.cells[0].textContent;
kanrishaField.value = row.cells[1].textContent;
hokanBashoField.value = row.cells[2].textContent;
riyouJoukyouField.value = row.cells[3].textContent;
formTitle.textContent = '備品を編集';
submitButton.textContent = '更新する';
cancelEditButton.style.display = 'inline-block';
window.scrollTo(0, 0);
}
});
// ■ キャンセル処理
cancelEditButton.addEventListener('click', resetForm);
function resetForm() {
form.reset();
bihinIdField.value = '';
formTitle.textContent = '新しい備品を登録';
submitButton.textContent = '登録する';
cancelEditButton.style.display = 'none';
}
// ★ 初期表示
fetchBihinList();
});
</script>
- 保存して確認 右上の「公開」ボタンをクリックし、「ページを表示」して動作を確認します。フォームが表示され、備品の登録、編集、削除ができれば成功です。
## ステップ4:他のPCやスマホからアクセスする (LAN内共有)
【参考】以下の方法は動画と異なります。
Localには、作成したサイトを一時的にインターネットに公開し、同じネットワーク(LAN)にいる他の人や自分のスマホからアクセスできるようにする「Live Link」という便利な機能があります。
- Live Linkを有効にする Localのサイト管理画面の下部にある「Live Link」という文字の横の「Enable」ボタンをクリックします。
- URLを共有 有効になると、
xxxxx.loca.lt
のようなURLが発行されます。このURLに、同じWi-Fiに接続しているPCやスマートフォンのブラウザからアクセスしてみてください。- 注意: この機能は、あなたがLocalを起動している間だけ有効です。
これで、部署やチーム内で簡易的にシステムを共有することも可能です。
## まとめと次のステップ
お疲れ様でした!これで、あなただけの本格的な備品管理システムが完成しました。
専用テーブル方式のメリット:
- WordPressの投稿機能とは独立しているため、データ構造を完全に自由に設計できる。
- データが純粋なため、将来的に大量のデータを扱う場合でもパフォーマンス上有利になることがある。
この経験は、単なるWordPressユーザーから、一歩進んだ開発者になるための重要なステップです。ここからさらに、検索機能やCSVエクスポート機能などをPHPで追加していくことで、より高度なシステム開発に挑戦できます。
コメントを残す
コメントを投稿するにはログインしてください。