简体   繁体   English

在 Kohana 3.1.3 中使用接口

[英]Using Interfaces in Kohana 3.1.3

I'm trying to build a form wizard in Kohana and am learning a bit as I go.我正在尝试在 Kohana 中构建一个表单向导,并且我正在学习一点 go。 One of the things that I've learn might work best is utilizing a state pattern in my class structure to manage the different steps a user can be in during the form process.我学到的最有效的一件事是在我的 class 结构中使用 state 模式来管理用户在表单过程中可以执行的不同步骤。

After doing some research, I've been thinking that the best approach may be to use an interface and have all of the steps act as states that implement the interface.在做了一些研究之后,我一直认为最好的方法可能是使用接口,并让所有步骤都充当实现接口的状态。 After a state validates, it will change a session variable to the next step, which can be read upon the initial load of the interface and call the correct state to use.一个 state 验证后,它将更改一个 session 变量到下一步,可以在接口的初始加载时读取并调用正确的 state。

Does this approach make sense?这种方法有意义吗? If so, how the heck do I make it happen (how do I best structure the filesystem?)如果是这样,我该怎么做(如何最好地构建文件系统?)

Here is the rough start I've been working on:这是我一直在努力的艰难开始:

<?php defined('SYSPATH') or die('No direct script access.');

/**
* Project_Builder @state
* Step_One @state
* Step_Two @state
**/

interface Project_Builder 
{
    public function do_this_first();
    public function validate();
    public function do_this_after();
}

class Step_One implements Project_Builder {

    public function __construct
    {
        parent::__construct();

        // Do validation and set a partial variable if valid

    }

    public function do_this_first() 
    {
        echo 'First thing done';
        // This should be used to set the session step variable, validate and add project data, and return the new view body.
            $session->set('step', '2');


    }
    public function do_this_after()
    {
        throw new LogicException('Have to do the other thing first!');
    }

}

class Step_Two implements Project_Builder {
    public function do_this_first()
    {
        throw new LogicException('Already did this first!');
    }
    public function do_this_after()
    {
        echo 'Did this after the first!';
        return $this;
    }
}

class Project implements Project_Builder {
    protected $state;
    protected $user_step;
    protected $project_data

    public function __construct()
    {
        // Check the SESSION for a "step" entry. If it does not find one, it creates it, and sets it to "1".
        $session = Session::instance('database');

        if ( ! $session->get('step'))
        {
            $session->set('step', '1');
        }

        // Get the step that was requested by the client.
        $this->user_step = $this->request->param('param1');

        // Validate that the step is authorized by the session.
        if ($session->get('step') !== $this->user_step)
        {
            throw new HTTP_Exception_404('You cannot skip a step!');
        }

        // Check if there is user data posted, and if so, clean it.
        if (HTTP_Request::POST == $this->request->method())
        {
            foreach ($this->request->post() as $name => $value)
            {
                $this->project_data["$name"] = HTML::chars($value);
            }
        }   

        // Trigger the proper state to use based on the authorized session step (should I do this?)
        $this->state = new Step_One;
    }
    public function doThisFirst()
    {
        $this->state = $this->state->do_this_first();
    }
    public function doThisAfter()
    {
        $this->state = $this->state->do_this_after();
    }
}

$project = new Project;
try
{
    $project->do_this_after(); //throws exception
}
catch(LogicException $e)
{
    echo $e->getMessage();
}

$project = new Project;
$project->do_this_first();
$project->validate();
$project->do_this_after();
//$project->update();

Your way certainly looks possible, however I would be tempted to keep it simpler and use some of Kohanas build in features to take care of what you want.你的方式看起来确实可行,但是我很想保持它更简单,并使用一些 Kohanas 内置功能来处理你想要的东西。 For example, I would use Kostache (mustache) and have separate View classes (and potentially templates) for each step.例如,我会使用 Kostache(mustache)并为每个步骤设置单独的 View 类(以及可能的模板)。 Then the controller becomes quite simple.那么controller就变得相当简单了。 See the example below (missing session stuff and validation of the step_number).请参见下面的示例(缺少 session 内容和对 step_number 的验证)。 All of the validation is handled in the model.所有验证都在 model 中处理。 If there is a validation error, an exception can be thrown which can then pass error messages back to the View.如果存在验证错误,则会引发异常,然后将错误消息传递回视图。

<?php

class Wizard_Controller {

    function action_step($step_number = 1)
    {
        $view = new View_Step('step_' + $step_number);

        if ($_POST)
        {
            try
            {
                $model = new Model_Steps;
                $model->step_number = $step_number;
                if ($model->save($_POST))
                {
                    // Go to the next step
                    $step_number++;
                    Request::current()->redirect('wizard/step/'.$step_number);    
                }
            }
            catch (Some_Kind_Of_Exception $e)
            {
                $view->post = $_POST;
                $view->errors = $e->errors();
            }
        }

        $view->render();
    }
}
?>

Hope this makes sense.希望这是有道理的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM