CodeIgniter でつくる、あゆ板風何か vol.4

提供品の表示、登録機能を実装していきます。

提供品詳細に取得データを表示

一覧画面で表示される提供品名の部分に show/{id} というリンクを張ったので、id を渡すと指定した提供品の詳細を表示する show アクションを実装します。

// controllers/items.php
  public function show( $id ) {
    if( ! $id ){ redirect('/'); }
    $this->load->model( 'Thank_model' );
    $data = array(
      'item' => $this->Item_model->find_by_id( $id ),
      'thanks' => $this->Thank_model->find_all( $id ),
      'is_closed' => $this->Item_model->is_closed( $id ),
    );
    $this->load->view( 'items/show', $data );
  }

指定された ID の提供品を取得、お礼書き込みを取得をおこない、ビューに渡します。

次いで、モデルとビューも実装します。

// models/item_model.php
  public function find_by_id( $id ){
    $res = $this->db
      ->select( 'items.*, types.name type_name' )
      ->join( 'types', 'items.type = types.id' )
      ->where( 'items.id', $id )
      ->get( 'items' );
    return $res->row();
  }
  public function is_closed( $id ){
    return ( 1 === $this->db
      ->select( 'id' )
      ->where( 'id', $id )
      ->where( 'dl_limit <= dl_count' )
      ->where( 'dl_limit !=', 0 )
      ->get( 'items' )->num_rows() );
  }
  public function is_force_post( $id ){
    return !empty( $this->db
      ->select( 'force_post' )
      ->where( 'id', $id )
      ->get( 'items' )->row()->force_post );
  }

id から提供品を探すメソッドと、提供終了と要お礼の確認メソッドを追加しました。

// views/items/show.php
<html>
<?php echo $this->view( 'shared/head' ) ?>
<body>

<?php echo $this->view( 'shared/header' ) ?>

<div id="container">
  <?php echo $this->view( 'shared/nav' ) ?>
  <div id="provider">
    <h3><?php echo h($item->name) ?></h3>
    <h4><?php echo h($item->provider_name) ?></h4>
    <p><?php echo h($item->provider_comment) ?></p>
    <p><?php echo date( 'Y/m/d H:i:s', strtotime( $item->created_at ) ) ?></p>

  <?php if( commented( $item->id, $this->session->userdata( 'gots' ) ) ): ?>
    <pre><?php echo h($item->uri) ?></pre>
  <?php elseif( $item->force_post ): ?>
    <pre>[ 要お礼書き込み ]</pre>
  <?php elseif( $is_closed ): ?>
    <pre>[ 提供終了 ]</pre>
  <?php else: ?>
    <?php echo form_open( "items/get/{$item->id}" ) ?>
      <?php echo form_submit( 'get', '取得' ) ?>
    <?php echo form_close() ?>
  <?php endif ?>

    <p>
    <?php echo form_open( "items/edit" ) ?>
      <?php echo form_hidden( 'id', $item->id ) ?>
      <?php echo form_input( 'confirm_pw_edit', set_value( 'confirm_pw_edit' ) ) ?>
      <?php echo form_submit( 'edit', '編集' ) ?>
      <?php echo form_label( '削除', 'destroy' ) ?>
      <?php echo form_checkbox( 'destroy', 1, set_value('destroy') ) ?>
    <?php echo form_close() ?>
    </p>
  </div>

  <?php echo validation_errors() ?>

  <div id="thanks">
    <?php foreach( $thanks as $t ): ?>
    <div class="post">
      <p><?php echo h($t->name) ?></p>
      <p><?php echo date( 'Y/m/d H:i:s', strtotime( $t->created_at ) ) ?></p>
      <pre><?php echo h($t->comment) ?></pre>
    </div>
    <?php endforeach ?>
  </div>

  <div id="post">
    <?php echo form_open( 'items/comment' ) ?>
      <?php echo form_hidden( 'id', $item->id ) ?>

      <p>
      <?php echo form_label( 'お名前', 'name' ) ?>
      <?php echo form_input( 'name', set_value('name') ) ?>
      </p>

      <p>
      <?php echo form_label( 'メールアドレス', 'email' ) ?>
      <?php echo form_input( 'email', set_value('email') ) ?>
      </p>

      <p>
      <?php echo form_label( '発言', 'comment' ) ?>
      </p>
      <p>
      <?php echo form_textarea( 'comment', set_value('comment') ) ?>
      </p>

      <p>
      <?php echo form_submit( 'post', '送信' ) ?>
      </p>
    <?php echo form_close() ?>
  </div>
</div>

<?php echo $this->view( 'shared/footer' ) ?>

</body>
</html>

提供品情報の表示と、お礼表示、お礼フォームを実装しました。

提供品URL は提供品の状態によって、分岐させています。

提供品URLの表示

取得ボタンを押すと、提供品URLが表示されるように実装します。

  // controllers/items.php
  public function get( $id ){
    if(
      ! $this->Item_model->is_force_post( $id ) &&
      ! $this->Item_model->is_closed( $id )
    ){
      $this->save_got_item( $id );
    }
    redirect( "items/show/{$id}" );
  }
  private function save_got_item( $id ){
      $gots = $this->session->userdata( 'gots' );
      $gots[] = $id;
      $this->session->set_userdata( array(
        'gots' => $gots
      ) );
      $this->Item_model->consume_count( $id );
  }

さらに、取得ボタンが押されると、DL数を増やすメソッドも追加します。

  // models/items_model.php
  public function consume_count( $id ){
    $cnt = 1 + $this->db->select( 'dl_count' )->where( 'id', $id )->get( 'items' )->row()->dl_count;
    $this->db->set( 'updated_at', 'NOW()', FALSE );
    $this->db->where( 'id', $id );
    $res = $this->db->update( 'items', array( 'dl_count' => $cnt ) );
    return $res;
  }

強制書き込みが有効でなく、DL制限を超えていなければ取得ボタンをクリックすることで、提供品URLが表示されます。

このままではセッション管理が Cookie なので、強制書き込みや制限を回避できてしまいます。

DB でセッションを管理

ちょっとした設定と作業で DB によるセッション管理を有効にできるので、設定してみます。

* 追記予定

新規提供品UP機能の実装

新規に提供品を投稿できる機能を実装します。

提供品には種類の項目があるので、テーブルで管理されている種類の一覧を取得するモデルを作ります。

種類の取得

コントローラーで種類のデータを取得するために type_model.php を作成します。

// models/type_model.php
class Type_model extends CI_Model {
  public function find_all(){
    $res = $this->db
      ->select( '*' )
      ->get( 'types' );
    return $res->result();
  }
  public function get_dropdown() {
    $res = $this->find_all();
    $types = array();
    foreach( $res as $type ){
      $types[ $type->id ] = $type->name;
    }
    return $types;
  }
}

全件ひっぱるだけの find_all() と その結果から form_dropdown() に渡す用の形式に配列を作り直す get_dropdown() をつくりました。

可能なら find_all() の結果をそのまま渡せると便利なんですが、もうちっといいやり方はないんでしょうか。アドバイス募集です。

新規提供品UP機能の実装

コントローラーで選択用の種類を取得し、ビューを作成します。

// controllers/items.php
  public function add() {
    $data = array(
      'types' => $this->Type_model->get_dropdown(),
    );
    $this->load->view( 'items/add', $data ) ;
  }

// views/items/add.php
<html>
<?php echo $this->view( 'shared/head' ) ?>
<body>

<?php echo $this->view( 'shared/header' ) ?>

<div id="container">
  <?php echo $this->view( 'shared/nav' ) ?>

  <?php echo validation_errors() ?>

  <?php echo form_open( 'items/create' ) ?>
    <p>
    <?php echo form_label( 'お名前', 'provider_name' ) ?>
    <?php echo form_input( 'provider_name', set_value('provider_name', '名無しの職人') ) ?>
    </p>

    <p>
    <?php echo form_label( 'メールアドレス' , 'provider_email' ) ?>
    <?php echo form_input( 'provider_email', set_value('provider_email', '774@example.com') ) ?>
    </p>

    <p>
    <?php echo form_label( '編集用パスワード', 'pw_edit' ) ?>
    <?php echo form_input( 'pw_edit', set_value('pw_edit') ) ?>
    </p>

    <p>
    <?php echo form_label( '提供品名', 'name' ) ?>
    <?php echo form_input( 'name', set_value('name') ) ?>
    </p>

    <p>
    <?php echo form_label( '提供品種別', 'type' ) ?>
    <?php echo form_dropdown( 'type', $types, set_value('type') ) ?>
    </p>

    <p>
    <?php echo form_label( '提供品URL', 'uri' ) ?>
    </p>
    <p>
    <?php echo form_textarea( 'uri', set_value('uri') ) ?>
    </p>

    <p>
    <?php echo form_label( '強制書き込み要求', 'force_post' ) ?>
    <?php echo form_checkbox( 'force_post', 1, set_value('force_post') ) ?>全員に書き込みをさせる
    </p>

    <p>
    <?php echo form_label( 'ダウンロード制限数', 'dl_limit' ) ?>
    <?php echo form_input( 'dl_limit', set_value('dl_limit', 0) ) ?>(制限なしの場合は「0」)
    </p>

    <p>
    <?php echo form_submit( 'add', '送信' ) ?>
    </p>
  <?php echo form_close() ?>
</div>

<?php echo $this->view( 'shared/footer' ) ?>

</body>
</html>

こんな感じで。

登録データ検証の作成

POST されたデータを検証し、検証失敗なら入力画面に戻し、成功ならデータを登録して、完了画面へ遷移させます。

views/add.php でフォームのアクションを items/create に設定したので、controllers/items.php に  create アクションを作り、検証(バリデーション)の実装を行います。

// models/item_model.php
  public function get_rules(){
    return array(
     array(
       'field'   => 'provider_name',
       'label'   => 'お名前',
       'rules'   => 'required'
      ),
      array(
       'field'   => 'provider_email',
       'label'   => 'メールアドレス',
       'rules'   => 'required|valid_email'
      ),
      array(
       'field'   => 'pw_edit',
       'label'   => '編集用パスワード',
       'rules'   => 'required|alpha_numeric'
      ),
      array(
       'field'   => 'name',
       'label'   => '提供品名',
       'rules'   => 'required'
      ),
      array(
       'field'   => 'type',
       'label'   => '提供品種別',
       'rules'   => 'required|is_natural'
      ),
      array(
       'field'   => 'uri',
       'label'   => '提供品URI',
       'rules'   => 'required'
      ),
      array(
       'field'   => 'force_post',
       'label'   => '強制書き込み要求',
       'rules'   => 'is_natural|less_than[2]'
      ),
      array(
       'field'   => 'dl_limit',
       'label'   => 'ダウンロード制限数',
       'rules'   => 'required|is_natural'
      ),
    );
  }

バリデーションルールをモデルに持たせました。

// controllers/items.php
  public function create() {
    $this->form_validation->set_rules(
      $this->Item_model->get_rules()
    );
    $data = array(
      'provider_name' => $this->input->post( 'provider_name' ),
      'provider_email' => $this->input->post( 'provider_email' ),
      'pw_edit' => $this->input->post( 'pw_edit' ),
      'name' => $this->input->post( 'name' ),
      'type' => $this->input->post( 'type' ),
      'uri' => $this->input->post( 'uri' ),
      'force_post' => $this->input->post( 'force_post' ),
      'dl_limit' => $this->input->post( 'dl_limit' ),
    );
    if( TRUE === $this->form_validation->run() && $this->Item_model->create( $data ) ){
      $this->load->view( 'items/create' );
    }else{
      $this->add();
    }
  }

models/item_model.php にバリデーションルールを返させるメソッドを追加しました。

コントローラーではそれを使って、ルールをセットして、検証を走らせています。

データ登録成功なら、views/create.php を読み込み、失敗なら items/add に戻ります。

<html>
<?php echo $this->view( 'shared/head' ) ?>
<body>
<?php echo $this->view( 'shared/header' ) ?>
<?php echo $this->view( 'shared/nav' ) ?>

<div id="container">
  <?php echo $this->view( 'shared/nav' ) ?>
  <p>登録完了</p>
</div>

<?php echo $this->view( 'shared/footer' ) ?>
</body>
</html>

items/create.php は単にメッセージを出すだけにしました。

新規に登録して、それを参照できるようになりました。

完了画面でリロードすると、同じ内容がポストされますが、create メソッドにポストすることで登録が出来る仕様ということにしてよしとしました。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする