お問い合わせフォームを再設置いたしました

日頃よりご愛顧いただきましてありがとうございます。

先日より当ホームページのお問い合わせフォームが表示されない不具合が発生していましたが、お客様にご指摘いただき発見いたしました。

この度はご迷惑をおかけし、申し訳ありませんでした。
ご指摘いただきましたお客様には、改めてお礼申し上げたいと思います。

お問い合わせフォームはこちらに再設置いたしました。

今後もどうぞよろしくお願いいたします。

2018.6.13 福田康弘

画面にHTMLを表示する、時刻を表示する

PHPでHTMLを表示する場合はprint または echo を使用します。

<?php

print('ここに記入')

?>

時刻を表示するときはdateを使用します。

<?php
print(date('Y m j s'));
?>

dateファンクションは画面に表示する機能はもっておらず、【戻り値】として内容を得られるだけです。文字列と連結するときは、
.(ドット)を使って戻り値と文字列を連結します。

<?php
print('現在は'.date('G i s').'です')
?>

CakePHPでVirtualFieldsを使う

virtualfieldsは任意のSQL表現をつくり、モデルのフィールドとして割り当てることができます。作成したフィールドは保存することができません。find関数等で他の引数と渡すとエラーになりますので注意が必要です。その場合は渡す前に空にもどしましょう。その他データベースにバーチャルフィールドと同じ名前があるとエラーを引き起こします。

バーチャルフィールドの作り方
モデルAにバーチャルフィールドを作成します。

1:モデルAのバーチャルフィールドを追加します。

$this->virtualFields = array(
  ‘rank’ => ‘sum(User.rate)’,
  );

2:フィールドに追加します。

  $fields = array(
   ’conditions’ => array(‘User.agecheck’ => 1),
‘fields’ => array(
‘User.id’,
‘User.rate’
‘User.rank’
)
);

$res = $this->ModelA->find(‘all’, $fields);

ザックリかきすぎてしまった。
また今度書き直そう・・・ではっ!

cakephp パスワードリマインダー機能の実装

cakephpでパスワードリマインダー機能を追加しました。あまり探してなかったので、フローとメモを記しておきます。

準備:

・Controller

UsersController.php

・Model

User.php

EmailSend.php

PasswordRemind.php

・View

forgot_password.ctp

reset_password.ctp

=========================================

流れ

①【forgot_password.ctp】 

*Controllerに渡すデータ値 

ユーザーネーム(メールアドレス)

これらをFormヘルパー:createの’action’ => ‘forgot_password’,で渡しています

================================================

②【UsersController.php】

*あるユーザーネームだけ取得します

function forgot_password(){

// フォームからポストされたデータがあるかどうか
if ($this->request->is(‘post’)) {
// 登録されているメールアドレスが存在するかどうか
$username = !empty($this->request->data[‘User’][‘username’])?$this->request->data[‘User’][‘username’]:”;  
$user_id = $this->User->userNameExists($username);  ・・・・・①

if(!empty($user_id)){ ・・・・②
// 存在すればURLを作成し、メール送信し、リセットパスワードを送信
//アクチベーション用のURLを作成
$url =
DS . strtolower($this->name) . // コントローラ
DS . ‘reset_password’ . // アクション
DS . $this->User->getPasswordRemindHash($user_id);
$url = Router::url( $url, true);
$this->EmailSend->sendPasswordRemindMail($username, $url, ‘forgot_password’);

$this->Session->setFlash(__(‘入力されたメールアドレス宛にパスワードリセットURLが記載されたメールを送信しました。メールを確認し記載されたURLにアクセスしてパスワードを新しいパスワードに更新してください。’));
return $this->redirect(array(‘controller’ => ‘users’,’action’ => ‘forgot_password’ ));
}else{
// 存在しなければ
$this->Session->setFlash(__(‘このメールアドレスは登録されていません。’));
}
}

=========================================================

①はModelのUser.phpにて、ユーザーIDでユーザー名(メールアドレス)が存在するかどうかを取得しています。

public function userNameExists($username) {
$result = $this->find(‘first’, array(
‘fields’ =>array(
$this->alias.’.id’,
),
‘conditions’ => array(
$this->alias.’.username’ => $username,
$this->alias.’.retired’ => false, ・・・・これは削除されていないよって意味だよ。削除されているユーザーを取得することはないのでここで指定しているんだよ。
),
‘recursive’ => -1, //Userのみ取得する
));
// 存在すればIDを返し、存在しなければfalseを返す
return !empty($result[‘User’][‘id’])?$result[‘User’][‘id’]:false;
}

*find関数 

*三項演算子 (条件式)?trueの時:falseの時;

===========================================================

【ここ重要!】

②はModel/User.phpのgetPasswordRemindHashアクションで

始めにユーザーネーム(メールアドレス)を取得し、次にハッシュ値を生成し、

そのユーザーネームに対するURLにハッシュをくっつけてます。

$this->log(“———-function getPasswordRemindHash–“.__FILE__.__LINE__.”\n”);
// ユーザIDの有無確認
if ($this->exists($user_id)) {
// 更新日時を取得しハッシュ化
$result = $this->find(‘first’, array(
‘conditions’ => array(
‘User.id’ => $user_id,
‘User.retired’ => false,
),
‘fields’ => array(
‘User.username’,
),
‘contain’ => array(),
‘recursive’ => -1, //Userのみ取得する
));
//modifiedによりハッシュを作成する。
$hash = $this->PasswordRemind->makeHash( $result[‘User’][‘username’]);
$this->PasswordRemind->saveHash($user_id, $hash);
return $hash;
}else{
//ユーザーが存在しなければfalse
return false;
}

====================================================

Model/PasswordRemind.php にて

public function makeHash($email = ”) {
//現在時刻とemailによりハッシュを作成する。
return Security::hash( $email . date(‘Y-m-d H:i:s’), ‘sha1’, true);
}

public function saveHash($user_id, $hash) {
$this->create();
$savedata = array(
‘user_id’ => $user_id,
‘hash’ => $hash,
‘created’ => date(‘Y-m-d H:i:s’), // 一応明示的に現在時刻をいれてあげる
);
return $this->save($savedata);
}

========================================================-

さあ、ここでEmailを送るのだが、いくつか注意点があります。(てか、いくつかエラーがでた)

ここではModel/EmailSend.php でメール送信を行っていますが、

まず、ソースは

function sendPasswordRemindMail($Email, $url, $template = null){

// メール送信

$email = new CakeEmail(‘password_remind’);
try {
$email->config(‘password_remind’);
// メーラー情報の削除 cake phpで作成されたことがバレバレになってしまうため。
$email->addHeaders(array(‘X-Mailer’ => false));
$email->emailPattern(‘/^[-+.\\w]+@[-a-z0-9]+(\\.[-a-z0-9]+)*\\.[a-z]{2,6}$/i’);
$email->to(array($Email));
$email->viewVars(compact(‘Email’));
$email->viewVars(compact(‘url’));
$email->template(‘refresh_password’, ‘default’);
$email->subject(Configure::read(‘MAIL_SUBJECT_HEADER’).Configure::read(‘MAIL_SUBJECT.password_remind’));

$result = $email->send();
$this->log(‘登録メール送信’.__FILE__.__LINE__);
} catch(Exception $e) {
try {
// “”で囲む処理を入れる
$arr = explode(‘@’,$Email);
$arr[0] = ‘”‘ .$arr[0] .'”‘ ;
$mail = $arr[0].’@’.$arr[1];

debug($e->getMessage());
$email->config(‘password_remind’);
// メーラー情報の削除 cake phpで作成されたことがバレバレになってしまうため。
$email->addHeaders(array(‘X-Mailer’ => false));
// “を許可する
$email->emailPattern(‘/^[-“+.\\w]+@[-a-z0-9]+(\\.[-a-z0-9]+)*\\.[a-z]{2,6}$/i’);
# $email->to(array($request_data[‘User’][‘username’]));
$email->to(array($mail));
$email->viewVars(compact(‘Email’));
$email->viewVars(compact(‘url’));

$email->template(‘refresh_password’, ‘default’);
$email->subject(Configure::read(‘MAIL_SUBJECT_HEADER’).Configure::read(‘MAIL_SUBJECT.password_remind’));

$result = $email->send();
$this->log(‘登録メール送信’.__FILE__.__LINE__);
} catch(Exception $e) {
debug($e->getMessage());
}
}
}

ですが、テンプレート指定や送信内容(POSTとかホストとか・・)は調べれば出てきます。

私がエラーで困っていた場所は、メールサーバーの部分で起きていた。

メールシステムの簡単なおさらい

 
どうやら開発で混乱している? ようなので……
 

ポート番号??

 
ポート番号ってのはTCP/IPに出てくる仕組みの一つで、
通信相手としてIPアドレスだけじゃなくてポート番号も指定することで
通信相手(プログラム)を特定する。
電話にたとえると家に掛けて『○○さんお願いします』と言うようなもの。
 
メールの送信(配送)に関係するポートはこの3つ
 
25 SMTP 通常のメール配送に使うポート メールサーバー間のメールのやり取りは今でもここが基本
587 submission SPAM対策で25番のかわりに使われるポート PCからサーバーにメールを渡すとき使う 通常は暗号化されないがオプションで暗号化も可能(STARTTLS)
465 SMTP over SSL 暗号化したSMTP通信を行うときのポート PCからサーバーにメールを渡すとき使う 常に暗号化される
 

サーバーどこ?

 
メールサーバー mail.parafamily.net
パラファミリー顧客の使うメール機能を一手に引き受けるサーバー
ポートは 25 587 465 が空いている
25 このサーバーで管理するメールアドレス宛のメールのみ受け取る
(ただしサーバー内部から接続して送信すると、外部サーバーへもメールを出せる)
465 SMTP認証が通った場合のみメールを受け取る
587 暗号化(STARTTLS)利用可能、SMTP認証が通った場合のみメールを受け取る
 
それ以外のサーバー(cs1とか)
これらのサーバーでもSMTPは動作しているが、送信専用である
25 サーバー内部からしか接続を受け付けない 外部サーバーへもメールを出せる
 
というわけで、WebシステムからSMTPでメールを出したい場合は、
localhost:25 へ接続してメールを出すのがよい。
(メールサーバーを経由しようとすると認証が必要なため面倒)

ここは処理とかじゃなく、メールサーバーも関係してくるので注意して欲しい。(泣)

========================================================

さて、ここで第一段階がおわりました。第二段階は送られたURLがリンクできるか、

パスワードと確認用パスワードが一致し、登録できるかの処理をいたします。

=========================================================

【UserController.php】 function reset_password(){}

// ハッシュのチェック ただしまだ完了フラグ(falseにする)は立てない
//ハッシュ文字列の情報があったら、Formから取得する
if(empty($in_hash) and !empty($this->request->data[‘User’][‘in_hash’])) {
$in_hash = $this->request->data[‘User’][‘in_hash’];
}
$user_id = $this->User->PasswordRemind->checkHash($in_hash, null, false); ・・・①
//$user_id = $this->User->getUserName($user_id);
if (empty($user_id)) {
throw new NotFoundException(__(‘Invalid Page’));
}
//↑↑↑↑Postデータが渡されるのは、パスワードと確認用パスワードなので、user_idは先に取得しておく必要がある。
// ポストデータがあれば保存をする(保存ボタンが押された場合以下の処理がはしる)
if ($this->request->is(‘post’)) {

$password = null;
$password_confirm = null;
if(!empty($this->request->data[‘User’][‘password’])) {
$password = $this->request->data[‘User’][‘password’];
}
if(!empty($this->request->data[‘User’][‘password_confirm’])) {
$password_confirm = $this->request->data[‘User’][‘password_confirm’];
}
$save = array(
‘id’ => $user_id,
‘password’ => $password,
‘password_confirm’ => $password_confirm,
);

$fieldList = array(
‘id’,
‘password’,
‘password_confirm’,
);

$this->User->id = $user_id;
//保存する
if($this->User->save($save,true,$fieldList)){
//保存成功したらハッシュを削除させるためにチェックを回す
$this->User->PasswordRemind->checkHash($in_hash);
$this->Session->setFlash(__(‘パスワードの更新に成功しました’));
// パスワード変更したんだから、ログイン画面がいいと思う
return $this->redirect(array(‘controller’ => ‘users’,’action’ => ‘login’));
}else{
$this->Session->setFlash(__(‘パスワードの更新に失敗しました’));
$errors = $this->User->validationErrors;

}
// これしちゃだめ→ unset($this->request->data[‘User’]);
} else {
// メールのURLからアクセスしたとき(POSTではない)
$this->request->data[‘User’][‘in_hash’] = $in_hash;
// 画面に$this->Form->hidden(‘in_hash’);を作る。
}
}

①ではcheckHashアクションで

================================================================

public function checkHash($hash, $time = null, $checking = true) {
if(empty($time)){
// 指定された時間がなければ
// 30分前の時間を取得
$time = date(‘Y-m-d H:i:s’, strtotime(date(‘Y-m-d H:i:s’) . ‘ -30minute’));
}
$hash = $this->find(‘first’, array(
‘fields’ => array(
‘PasswordRemind.id’,
‘PasswordRemind.user_id’,
),
‘conditions’ => array(
‘PasswordRemind.hash’ => $hash,
‘PasswordRemind.deleted’ => false,
‘PasswordRemind.created >’ => $time, //指定された時間よりも新しいhashの中で存在するかどうかのチェック
),
‘contain’ => array(),
));
// 存在すればUser_idを返し、存在しなければfalseを返す
if(!empty($hash[‘PasswordRemind’][‘id’])){
if($checking){
// checkingがtrueならば、同時に削除フラグを立てる
$savedata = array(
‘id’ => $hash[‘PasswordRemind’][‘id’],
‘deleted’ => true,
);
$this->save($savedata);
}
return $hash[‘PasswordRemind’][‘user_id’];
}else{
return false;
}
}

=============================================================

以上になります。第二段階のポイントはsave();ではなく、saveFields();関数で、

必要なデータやカラムを取得しているところとcheckHashアクションで保存前は、

削除フラグを立てず、保存した後に削除フラグをたてる(始めはfalseで、保存時にtrueにする)ところがポイントです。

Cakephp エラー対処法 warning: missing argument ~ 

warning: missing argument ~ というのは、

定義された引数と、呼び出す引数が違いますよというエラーです。

例えば、

 

function f_name ($x, $y) {
 echo $x . "ok";
 echo $y . "ok";
}

と定義して、呼び出すときに

f_name($y);

だとエラーになってしまいます。

こういうときは、初期値をにすればいいでしょう。

function name($x = null){
 if($y){
  処理1
 }else{
  処理2
 }
}

Cakephp Modelのテストケース作成

あるユーザーが職業選択ができて、そのラジオボタンを削除したり追加したりできるような仕様ががあった場合のテストケースを作成しました。そこでcakephp2のModelにtestSave()とtestDelete()を作成しました。

Fixtureに登録しているユーザーデータに基づいて記述してみました。

public function testSave(){

// もともとid=4まである、4件Fixtureに書いてある
$result = $this->MstJobType->find(‘count’);
$this->assertEquals(4, $result);

// idが4番まであったら、次に登録するデータは5番になるはず
// まだ登録していないので5番のデータが取れないチェック
$result = $this->MstJobType->find(‘first’, array(
‘conditions’ => array(
‘MstJobType.id’ => 5,
),
‘contain’ => false
));
$expected = array(); // 結果とれない!
$this->assertEquals($expected, $result);

// 5番になるデータを登録する
$update = array(
// MstJobTypeに登録するための項目(画面と同じだからadd.ctp/edit.ctpをチェック)
‘MstJobType’ => array(
‘name’ => ‘公務員’,
‘slug’ => ‘civilworker’,
‘deleted’ => 1
)
);
$this->MstJobType->create(); // 初期化(おまじない)
$this->MstJobType->save($update); // 保存

// 5番のデータが作成されたので、データが取れる
$result = $this->MstJobType->find(‘first’, array(
‘conditions’ => array(
‘MstJobType.id’ => 5,
),
‘contain’ => false
));
$expected = array(
‘MstJobType’ => array(
‘id’ => 5,
‘slug’ => ‘civilworker’,
‘deleted’ => true,
‘name’ => ‘公務員’,
)
);
unset($result[‘MstJobType’][‘created’]); // 作成時間:実行した時間が登録されちゃうと比較できないので、検索結果から消しておく
unset($result[‘MstJobType’][‘modified’]); // 更新時間:これも同じ
$this->assertEquals($expected, $result);

// テーブルの中身が1件増えたので5件になってる
$result = $this->MstJobType->find(‘count’);
$this->assertEquals(5, $result);
}

/**
* testDelete
* @return void
*/
public function testDelete() {
// 今あったものが無くなる(削除される)テスト
// 削除されていないデータがテーブルの中に2件ある(Fixtureに記載されているデータの件数)
$result = $this->MstJobType->find(‘count’, array(
‘conditions’ => array(
‘MstJobType.deleted’ => false
)
));
$this->assertEquals(2, $result);

// Fixtureに記載されているあるデータが取得できるかチェック
$result = $this->MstJobType->find(‘first’, array(
‘conditions’ => array(
‘MstJobType.id’ => 3,
)
));
$expected = array(
‘MstJobType’ => array(
‘id’ => 3,
‘name’ => ‘会社員’,
‘slug’ => ‘employee’,
‘created’ => ‘2015-02-22 15:35:03’,
‘modified’ => ‘2015-02-22 15:35:03’,
‘deleted’ => false
),
‘User’ => array()
);
$this->assertEquals($expected, $result);

// このもともとあった↑データを削除する
$this->MstJobType->id = 3;
$this->MstJobType->delete();

// 今削除されたものがちゃんと取得できなくなったかのチェック
// 最初に実行したfindと同じ条件で再度チェックする
$result = $this->MstJobType->find(‘first’, array(
‘conditions’ => array(
‘MstJobType.id’ => 3,
)
));
$expected = array(
‘MstJobType’ => array(
‘id’ => 3,
‘name’ => ‘会社員’,
‘slug’ => ‘employee’,
‘created’ => ‘2015-02-22 15:35:03’,
‘deleted’ => true
),
‘User’ => array()
);
unset($result[‘MstJobType’][‘modified’]); // 更新時間:削除されたときの実行時間が登録されてしまうので、消しておく
$this->assertEquals($expected, $result);

// 削除されていないデータは、テーブルの中に1件になった
$result = $this->MstJobType->find(‘count’, array(
‘conditions’ => array(
‘MstJobType.deleted’ => false
)
));
$this->assertEquals(1, $result);
}

【注意点】

*削除されていないデータ、つまりdeleted=>falseの数を変更すること。
*削除対象のデータに対して ’User’ => array();を追加することで、
その職業で登録されているユーザーデータも削除されるという感じで
必ず記述する(array()の中は何も書かなくていい)。

*実際に削除されたということを記述するにはdeleted=>falseから
deleted=>trueに変更して、現在の削除されていないデータ(deleted=>false)は
1件になったので$this->assertEquals(1, $result);と記述する。

テストケースの要点 Cakephp

テストケースは、開発したプログラミングに対して、意図しない動作をしないかを確認する作業です。

テストケースの書き方は

例えば

/Model/Articles.phpの
       * article名のみ取得する
public function getArticleName($article_id = null) {
$result = $this->find(‘first’, array(
‘conditions’ => array(
$this->alias.’.id’ => $article_id,
$this->alias.’.deleted’ => false,
),
‘fields’ => $this->alias.’.title’,
‘contain’ => array(),
));
return $result;
}

処理のテストケースを作成します。

===========================

補足

実行方法(teraterm)

・・・app]

全てのページを検証する場合

./Console/cake testsuite app AllTests

一つのページを検証する場合

./Console/cake testsuite app Model/Article

あるページの関数を検証する場合(debug(変数)等の中身おを調べたいとき)

./Console/cake testsuite app Model/Article –filter getArticleName(関数名)

==================================

検証する論理値(仮定しなければいけないこと)

実行する処理(今回は記事のタイトルを取得する)に対して、仮定することはいくつかあります。

①id(個人データ)があったら、そのタイトル名(Articleのtitle)を取得できるか

②削除済みのタイトルは取れない

③存在しないタイトルは取れない場合(削除されていない場合)

【実際のテストケース】

Model/Article.php

/**
* testGetTheAge method
*
* @return void
*/
public function testArticleName(){
// 存在しないタイトルは取れない
$result = $this->Article->getArticleName(99999999);
$compare = array(); //debug($result)
$this->assertEquals($compare, $result);
// 削除済みのタイトルは取れない
$result = $this->Article->getArticleName(6);
$compare = array();
$this->assertEquals($compare, $result);
// タイトルが取れる 
$result = $this->Article->getArticleName(3);
$compare = array(
‘Article’ => array(
‘title’ => ‘うぁーがんばろー’,
)
);
$this->assertEquals($compare, $result);
}

======================

【補足②】

始めに

@return void(->何も返さないよ) とか

@return array(->配列の返すよ)

など、返り値を設定しておきます。

*deletedの考え方

deleted = 削除済みのものを取ってくる

type P = false =>0、true=>1

*debug()関数に関して

debug()関数は取得したいデータを取ってきたい場合

実行したときにそのデータ処理が取得できます。

 

======================

Fixture(テストケースのデータ格納場所)の追加に関して

Fixtureに情報(データ)を格納したら、AllTestsをするとき、

そのときにでたエラーを修正していきます。

========================

このように、実行したい処理が何をしている処理なのか

(データを取得したいのか、削除したデータを取ってきたいのか、IF文で別々に処理しているのか、空の場合の処理なのか)

など、考えた上で、

テストケースは10パターンほど考えます。多ければ多いほどよいです。

このようにもし何かの不具合が見つかったら、何処が悪かったのかを検証できるので

基本的なことですがしっかりと見につけていけたらいいですね。

CAKEPHP nl2br() に関して

nl2br ・・・・・ 改行文字の前に HTML の改行タグを挿入する関数です。

書式:string nl2br( string string )

nl2br()は指定された文字列に含まれる全ての改行文字(\nなど)の前に、HTMLの改行タグ(<br />など)を挿入します。改行文字とは、行の最後に挿入して、そこで行を変えることを示す制御文字の一種である。ソフトによっては、矢印などを表示する場合があるが、通常、改行文字は目に見えない。

改行文字としては、キャリッジリターン(CR)、ラインフィード(LF)、この2つを連続したものなどが使用される。UNIX系OSではLF、Macintosh系ではCR、Windowsやインターネット電子メールはCR+LFが標準となっている。

返り値:改行文字の前にHTMLの改行タグを挿入した文字列を返します。

<?php

$str = 1行目\n2行目;

print nl2br($str);

?>

出力結果

1行目
2行目

get_template_directory_uriとget_stylesheet_directory_uri の違い

get_template_directory_uri()はWordPressテーマディレクトリまでのURLを取得する関数です。

もう一方で、

get_stylesheet_directory_uri()はWordPressテーマディレクトリまでのURLを取得できる関数です。

違いは、WordPressテーマの親子関係にあります。

get_template_directory_uri()をもう少し細かくいうと、親テーマで使用した場合は、get_stylesheet_directory_uri()と変わらずに有効化してあるWordPressテーマのテーマディレクトリURLの取得します。小テーマで使用した場合は、子テーマのstyle.cssに書かれている「Template」をみてテーマディレクトリURLを取得しています。

もし、子テーマを指定し、そこからURLを取得する場合は、get_template_directory_uri()とget_stylesheet_directory_uri()が違います。get_template_directory_uri()は親テーマのテーマディレクトリURLを出力してくれますが、get_stylesheet_directory_uri()は子テーマのテーマディレクトリURLを出力してくれます。

<まとめ>

get_template_directory_uri()とget_stylesheet_directory_uri()の違いについて紹介しました。WordPressのテーマ開発をするときはget_template_directory_uri()は親テーマで使い、get_stylesheet_directory_uri()子テーマで使うといった感じに分けるといいでしょう。

 それでは・・・

カスタム投稿の作成

カスタム投稿は、自由に投稿できる【投稿】です。いままでは、投稿と固定ページの2種類でした。それ以外に、独自で作成した投稿=カスタム投稿を作成することが出来ます。

プラグインで作成することもできますが、勉強もかねて、function.phpに書く方法を記しておこうと思います。

 

【function.php】の中

add_action('init', 'add_websites_post_type');
function add_websites_post_type() {
    $params = array(
            'labels' => array(
                    'name' => 'サイト',
                    'singular_name' => 'サイト',
                    'add_new' => '新規追加',
                    'add_new_item' => 'サイトを新規追加',
                    'edit_item' => 'サイトを編集する',
                    'new_item' => '新規サイト',
                    'all_items' => 'サイト一覧',
                    'view_item' => 'サイトの説明を見る',
                    'search_items' => '検索する',
                    'not_found' => 'サイトが見つかりませんでした。',
                    'not_found_in_trash' => 'ゴミ箱内にサイトが見つかりませんでした。'
            ),
            'public' => true,
            'has_archive' => true,
            'supports' => array(
                    'title',
                    'editor',
                    'author',
                    'custom-fields',
            ),
            'taxonomies' => array('websites_category','websites_tag')
    );
    register_post_type('websites', $params);
}

 

add_adtion()関数は、【指定したタイミングで、指定した関数を実行する】関数です。

任意の名前は、安全に名前をつけたいなら、名前の最初にオリジナルの名前を記入したほうがいいと思います。また、基本的に指定した名前はサイト運用中に変更することが出来ません。

適用させる引数は、たくさんあるので割愛します。

 

投稿できるようになったら、それをどこ(単一ページ、固定ページなど)に表示させるかということろですが、長くなってしまうので改めて書いていきたいと思います。