2016-04-22 46 views
0

私はすべての研究エンドポイント(ドキュメント、Google、SOなど)を使い果たしてしまったので、この質問を公にするように励まされました。私の問題の本質は、「ビューに動的データを追加する」と題されたセクションのCodeIgniter 3.0.6公式ドキュメントによって解決されているはずです。私の視点でアクセスするコントローラ。入力フォームを再入力するときに、codeigniterコントローラの変数が表示テンプレートにアクセスできない

コンテンツの公開アプリケーションにカスタム変更を1つ追加しました。編集ページでは、コンテンツをテーブルデータの更新用IDで取得しています。第1の形式。

个人设定

<div class="row"> 
    <div class="col-md-12"> 
    <h3>Update post</h3> 
     <form method="post" action="<?php echo base_url('post/update'); ?>" enctype="multipart/form-data"> 
    <div class="form-group"> 
     <label for="title">Title</label> 
     <input type="text" name="title" id="title" placeholder="News title" value="<?php echo $data['post']->title; ?>" class="form-control" /> 
    </div> 
    <div class="form-group"> 
     <label for="category">Category</label> 
      <select name="category" id="category" class="form-control"> 
      <?php foreach($data['categories'] as $category): ?> 
       <option value="<?php echo $category->idcategory; ?>" <?php echo set_select('category', $category->idcategory); ?>><?php echo $category->title; ?></option> 
      <?php endforeach; ?> 
      </select> 
    </div> 
    <div class="form-group"> 
     <label for="image">Image</label> 
     <input type="file" name="image" id="image" class="form-control" placeholder="Upload an image" /> 
    </div> 
    <div class="form-group"> 
     <label for="body">Post detail</label> 
      <textarea name="body" id="body" class="form-control" placeholder="Provide news content. Basic HTML is allowed."><?php echo $data['post']->body; ?></textarea> 
    </div> 
    <div class="form-group"> 
     <label for="tags">Tags</label> 
     <input type="text" name="tags" id="tags" value="<?php echo set_value('tags'); ?>" class="form-control" placeholder="Comma separated tags" /> 
    </div> 
      <button type="submit" class="btn btn-primary">Submit</button> 
    </form> 
    </div> 
</div> 

私は(変更する必要はありませんでした私は、フォームのタイトルとポストの詳細入力の場合に移入必要な値をターゲットに入力値を編集しましたカテゴリ入力用のものはどれも、ドロップダウンはすばらしく動作します)、トラブルシューティング中に出力レイアウトを破らないようにタグを入力として残します。コントローラ/ファンクションPost.phpはオリジナルの 'add'関数から抜き出されました。問題のコードチャンクと感じるよりも、全体を含めています。

更新機能

public function update($idpost) { 
    $this->load->helper('form'); 
    $data['title'] = 'Update post | News Portal'; 
    $data['post'] = $this->posts->get($idpost); 
    $this->load->model('category_model', 'cm'); 
    $data['categories'] = $this->cm->get_all(); 

    $this->load->library('form_validation'); 

    $this->form_validation->set_rules('title', 'title', 'trim|required'); 
    $this->form_validation->set_rules('body', 'post body', 'trim|required'); 
    $this->form_validation->set_rules('tags', 'tags', 'required'); 

    if($this->input->method(TRUE) == 'POST' && $this->form_validation->run()) { 

     $config['upload_path'] = './assets/uploads/'; 
     $config['allowed_types'] = 'gif|jpg|png'; 
     $config['max_size'] = '2000'; 
     $config['max_width'] = '2000'; 
     $config['max_height'] = '1200'; 
     $config['encrypt_name'] = TRUE; 

     $this->load->library('upload', $config); 

     if (!$this->upload->do_upload('image')) { 
      $this->template->alert(
       $this->upload->display_errors(), 
       'danger' 
      ); 
     } else { 
      $upload_data = $this->upload->data(); 
      $idpost = $this->posts->add(array(
       'iduser' => $this->user->id(), 
       'title' => $this->input->post('title'), 
       'body' => $this->input->post('body'), 
       'image' => $upload_data['file_name'] 
      )); 
      $tags = $this->input->post('tags'); 
      if(strlen($tags) > 0) { 
       $this->load->model('tag_model', 'tm'); 
       $tags = explode(',', trim($tags)); 
       $tags = array_map(array($this->tm, 'set_tag'), $tags); 
       $this->load->model('post_tag_model', 'ptm'); 
       foreach($tags as $idtag) { 
        $this->ptm->add(array(
         'idpost' => $idpost, 
         'idtag' => $idtag 
        )); 
       } 
      } 
      $idcategory = $this->input->post('category'); 
      if($idcategory) { 
       $this->load->model('post_category_model', 'pcm'); 
       $this->pcm->add(array(
        'idpost' => $idpost, 
        'idcategory' => $idcategory 
       )); 
      } 

      $this->template->alert(
       'Updated news item successfully', 
       'success' 
      ); 
      redirect('post'); 
      return; 
     } 
    } 

    $this->template->view('post/edit', $data); 
}  

この変数($タグ)は何とかのvar_dump($この - > _ ci_cached_vars)を用いて確認コントローラとビューの間に失われました。を使用して、対応するビュー内の使用可能なすべてのオブジェクトを確認します。フォーム入力に適切なデータを再入力するには、変数$ tagsが必要です。この機能の中に$ tagsの初期化がなかったのはどうでしたか?

は、私は完全にそれが(私の以前のvar_dumpによって確認されたように)非existantですので、変数は対応するビューに渡されないことを理解し、私は、関数のスコープ内$タグを描画する方法を正確にと迷ってしまいましたターゲットデータを取得するための入力フォームの作成に役立ちますか?他のすべての入力は、必要に応じて再投入されます。そして、脇に、私は実際にこのプロジェクトの元の開発者を追跡し、彼にこれについて与えました。私は彼が概説した2つのアプローチを論じようとしましたが、空白になったり、ページに誤りがありました。最も近いのは理論的には彼の2番目のポイントに来ることができます。すでにニュースビューの部分に少しのコードを適用しています。常に未定義のインデックス/変数またはIを解決するために私の首を破るしようとする他のいくつかの天罰が下るのエラーメッセージで終了しますが、単に泥沼に沈んさらに続ける

<?php 
    if($tags = get_tags($data['news']->idpost)) { 
     echo '<div class="tags">'; 
     echo 'Terms: '; 
     foreach($tags as $tag) { 
      echo ' <i class="fa fa-fw fa-link"></i> <a href="' . base_url('news/tag/' . $tag->idtag) . '">' . $tag->title . '</a> '; 
     } 
     echo '</div>'; 
    } 
    ?> 

(笑!)。それはのSEEMS私の問題の根拠に簡単ですが、私は酔ってめまいになり、私が始めたよりも10時間も失われるまで、周りを回り続けます。誰かが理解の塊を提供することができますか?

私が意味するところは、ここで提供されている答えと同じくらい単純なものでなければならないからです。@Passing variable from controller to view in CodeIgniterしかし、悲しいかな、どんな明確なリードについても、事前に感謝していません。

@DFriend - 構造をあまりにも変更したくないです。

a)は、このからだまされるコードが働いていると唯一の目標は、そのフォームの入力に適切なテーブルからデータを取得することです

b)は、私は現在の機能を妨害したり、誤って別のを開くためにしたくありません

c)正しい要素をゼロにしようとしています。

お時間をありがとうございます、@DFriend。

答えて

0

あなたの問題の理由は、redirectコールのためだと思います。基本的にブラウザに新しいURLを設定していることを呼び出します。ウェブサイトはステートレスです。セッションやその他の手段を使用せずに、URLの各要求は一意です。だからredirectと呼んで、$tagsの知識を拭いています。

$tags$_SESSIONアレイにプッシュし、postコントローラで確認して取得することで、この問題を回避できます。

post()が同じコントローラにある場合は、リダイレクトの代わりに簡単に呼び出すことができます。 post()は引数を受け入れるように変更するか、$tagsはコントローラクラスのプロパティでなければなりません。

だから、オプションの引数に

public function post($tags=null){ 

    //somewhere in here 
    if(isset($tags)){ 
     //$data is sent to views 
     $data['tags'] = $tags; 
    } 
} 

拡大回答を受け入れるようにその後のポストを定義し、この

$this->post($tags); 
return; 

を行う代わりに、

redirect('post'); 
    return; 

の、投稿する直接呼び出すには: 方法CodeigniterでPost/Read/Getパターンを実装し、引き続きフィールドの検証と再生成されたフォームフィールドを使用します。

処理のためにPRGパターンを実装するためにCodeigniter(CI)を使用するには、CI_Form_validationクラスの拡張が必要です。次のコードは、あなたが、私は$this->load->view()に戻って落ち使用しているテンプレートライブラリがないと/application/libraries/MY_Form_validation.php

<?php 
/** 
* The base class (CI_Form_validation) has a protected property - _field_data 
* which holds all the information provided by validation->set_rules() 
* and all the results gathered by validation->run() 
* MY_Form_validation provides a public 'setter' and 'getter' for that property. 
* 
*/ 
class MY_Form_validation extends CI_Form_validation{ 

    public function __construct($rules = array()) 
    { 
     parent::__construct($rules); 

    } 
    //Getter 
    public function get_field_data() { 
     return $this->_field_data;  
} 
    //Setter 
    public function set_field_data($param=array()){ 
     $this->_field_data = $param; 
    } 

} 

にする必要があります。あなたのモデルや関連するデータにアクセスすることなく、私はいくつかの仮定をしなければならず、場合によってはdb呼び出しを残していました。

全体的に、構造をあまり変更しないようにしました。しかし、私はまた、formヘルパー関数の便利な使い方を実証したかったのです。

ほとんどの場合、私がやったリストラは主に明確な例を提供する試みでした。私が成功したら、あなたはこれをかなり簡単に実装できるはずです。

ここに改訂版のビューがあります。これは、 'フォーム'ヘルパー関数をより多く使用します。

<head> 
    <style> 
    .errmsg { 
     color: #FF0000; 
     font-size: .8em; 
     height: .8em; 
    } 
    </style> 
</head> 
<html> 
    <body> 
    <div class="row"> 
     <div class="col-md-12"> 
     <h3>Update post</h3> 
     <?php 
     echo form_open_multipart('posts/process_posting'); 
     echo form_hidden('idpost', $idpost); 
     ?> 

     <div class="form-group"> 
      <label for="title">Title</label> 
      <input type="text" name="title" id="title" placeholder="News title" value="<?php echo $title; ?>" class="form-control" /> 
      <span class="errmsg"><?php echo form_error('title'); ?>&nbsp;</span> 
     </div> 
     <div class="form-group"> 
      <label for="category">Category</label> 
      <?php 
      echo form_dropdown('category', $categories, $selected_category, ['class' => 'form-control']); 
      ?> 
     </div> 
     <div class="form-group"> 
      <label for="image">Image</label> 
      <input type="file" name="image" id="image" class="form-control" placeholder="Upload an image" /> 
     </div> 
     <div class="form-group"> 
      <label for="body">Post detail</label> 

      <textarea name="body" id="body" class="form-control" placeholder="Provide news content. Basic HTML is allowed."><?php echo $body; ?></textarea> 
      <span class="errmsg"><?php echo form_error('body'); ?>&nbsp;</span> 
     </div> 
     <div class="form-group"> 
      <label for="tags">Tags</label> 
      <input type="text" name="tags" id="tags" value="<?php echo $tags ?>" class="form-control" placeholder="Comma separated tags" /> 
      <span class="errmsg"><?php echo form_error('tags'); ?>&nbsp;</span> 
     </div> 
     <button type="submit" class="btn btn-primary">Submit</button> 
     <?= form_close(); ?> 
     </div> 
    </div> 
    </body> 
</html> 

このソリューションの要点は、検証に失敗したときにセッションにform_validation->_field_dataを保存することです。ビューロード機能は、セッションデータ内の障害フラグを探し、フラグが真であれば、を現在のform_validationインスタンスにリストアします。

私はコメントに多くの説明を入れようとしました。コントローラーには、表示方法と処理方法があります。

class Posts extends CI_Controller 
{ 
    function __construct() 
    { 
    parent::__construct(); 
    $this->load->library('session'); 
    $this->load->library('form_validation', NULL, 'fv'); 
    } 

    /** 
    * post() 
    * In this example the function that shows the posting edit page 
    * Note the use of the optional argument with a NULL default 
    */ 
    function post($idpost = NULL) 
    { 
    $this->load->model('category_model', 'cm'); 
    $categories = $this->cm->get_all(); 
    /* 
    * Your model is returning an array of objects. 
    * This example is better served by an array of arrays. 
    * Why? So the helper function form_dropdown() can be used in the view. 
    * 
    * Rather than suggest changing the model 
    * these lines make the conversion to an array of arrays. 
    */ 
    $list = []; 
    foreach($categories as $category) 
    { 
     $list[$category->idcategory] = $category->title; 
    } 
    $data['categories'] = $list; // $data is used exclusivly to pass vars to the view 


    if(!empty($idpost)) 
    { 
     //if argument is passed, a database record is retrieved. 
     $posting = $this->posts->get($idpost); 


     //Really should test for a valid return from model before using it. 
     //Skipping that for this example 
     $title = $posting->title; 
     $body = $posting->body; 
     //assuming your model returns the next two items like my made up model does 
     $selected_category = $posting->category; 
     $tags= $posting->tags; 
    } 
    else 
    //a failed validation (or a brand new post) 
    { 
     //check for failed validation 
     if($this->session->failed_validation) 
     { 
     // Validation failed. Restore validation results from session. 
     $this->fv->set_field_data($_SESSION['validated_fields']); 
     } 
    } 

    //setup $data for the view 

    /* The 'idpost' field was add to demonstrate how hidden data can be pasted to and from 
    * a processing method. In this case it would be useful in providing a 'where = $value' 
    * clause on a database update. 
    * Also, a lack of any value could be used indicate an insert is requried for a new record. 
    * 
    * Notice the ternary used to provide a default value to set_value() 
    */ 
    $data['idpost'] = $this->fv->set_value('idpost', isset($idpost) ? $idpost : NULL); 

    $data['title'] = $this->fv->set_value('title', isset($title) ? $title : NULL); 
    $data['body'] = $this->fv->set_value('body', isset($body) ? $body : NULL); 
    $data['tags'] = $this->fv->set_value('tags', isset($tags) ? $tags : NULL); 
    $data['selected_category'] = $this->fv->set_value('category', isset($selected_category) ? $selected_category : '1'); 

    $this->load->view('post_view', $data); 
    } 

    public function process_posting() 
    { 
    if($this->input->method() !== 'post') 
    { 
     //somebody tried to access this directly - bad user, bad! 
     show_error('The action you have requested is not allowed.', 403); 
     // return; not needed because show_error() ends with call to exit 
    } 

    /* 
    * Note: Unless there is a rule set for a field the 
    * form_validation->_field_data property won't have 
    * any knowledge of the field. 
    * In Addition, the $_POST array from the POST call to the this page 
    * will be GONE when we redirect back to the view! 
    * So it won't be available to help repopulate the <form> 
    * 
    * Rather than making a copy of $_POST in $_SESSION we will rely 
    * completely on form_validation->_field_data 
    * to repopulate the form controls. 
    * That can only work if there is a rule set 
    * for ANY FIELD you want to repopulate after failed validation. 
    */ 

    $this->fv->set_rules('idpost', 'idpost', 'trim'); //added any rule so it will repopulate 
    // in this example required would not be useful for 'idpost' 

    $this->fv->set_rules('title', 'title', 'trim|required'); 
    $this->fv->set_rules('body', 'post body', 'trim|required'); 
    $this->fv->set_rules('tags', 'tags', 'required'); 
    //add rule for category so it can be repopulated correctly if validation fails 
    $this->fv->set_rules('category', 'category', 'required'); 

    if(!$this->fv->run()) 
    { 
     // Validation failed. Make note in session data 
     $this->session->set_flashdata('failed_validation', TRUE); 

     //capture and save the validation results 
     $this->session->set_flashdata('validated_fields', $this->fv->get_field_data()); 

     //back to 'posts/index' with server code 303 as per PRG pattern 
     redirect('posts/post', 'location', 303); 
     return; 

    } 
    // Fields are validated 
    // Do the image upload and other data storage, set messges, etc 

    // checking for $this->input->idpost could be used in this block 
    // to determine whether to call db->insert or db->update 
    // 
    // When process is finished, GET the page appropriate after successful <form> post 
    redirect('controller/method_that_runs_on_success', 'location', 303); 
    } 

//end Class 
} 

質問がありますか?コメント?侮辱?

+0

ルックオーバーありがとうございますが、私の問題の原因がリダイレクトになっていることについてあなたに同意しないといけません(もし私がPRGパターンを真似しようとすると、リダイレクトは私に更新された結果 - これは "add"関数でテストされます)。コントローラに呼び出されたビューに追加するタグの宣言がなければならないということに私は同意します。私は$ data ['tags'] = $ tagsを置くことでそれをテストしています。 index()関数で使用します。 – HomeOffice

+0

私はあなたのPRGパターンの使い方について理解しています。残念ながら、CIはそれを達成するのは容易ではありません。私のPRGソリューションは、CI_Form_validationを拡張するカスタムライブラリを使用します。これは、保護されたプロパティ '_field_data'のセッターとゲッターを追加します。別の方法は、検証結果に応じて適切にリダイレクトするフォームの「アクション」です。失敗した場合、検証結果を最初のフォームに戻すためにflashdataが使用されます。そのページは、フラッシュデータを検索し、存在する場合はそれに基づいて動作します。私はあなたが好きなら、私は完全な例で私の答えを編集することができます - しかし、月曜日まで。 :) お知らせ下さい。 – DFriend

+0

私は完全に感謝していますし、狂気の慌てもありませんので、週末には目を覚ますつもりです。これまでのすべての助けを賞賛するが、編集機能を持たないコンテンツ公開アプリを聞いたことのある人(初心者の声を聞いたことのある人)が第1位の常識に含まれるように叫んだ機能を「カスタマイズ」する必要がある。 )?ちょうど;) – HomeOffice

関連する問題