douyanjing0822 2013-11-26 20:13
浏览 22
已采纳

在CakePHP 2.x中使用命名参数

I have the following method which takes a query to search my notes:

function search( $q = null )
{
    if ( $q == null )
    {
        $this->redirect(array('action' => 'index'));
    }

    $this->paginate = array(
    'limit'=>5,
    'order'=>'Note.datetime DESC',
    'conditions' => array(
        'OR' => array(
            'Note.title LIKE' => '%'. $q . '%',
            'Note.content LIKE' => '%'. $q . '%'
            )
        ),
        'Note.status'=>1
    );

    $this->set('notes', $this->paginate());

    $this->render('index');
}

As you can see it takes a single parameter called 'q' which is used to query the model data.

I have hooked up this to the router like so:

Router::connect('/notes',
    array('controller'=>'notes','action'=>'index', 'page' => 1),
    array(
        'pass' => array('page')
    )
);

Router::connect('/notes/page/:page', 
    array('controller' => 'notes', 'action' => 'index'),
    array(
        'pass' => array('page'),
        'page' => '[1-9]+'
        )
);

Router::connect('/notes/search/:page/:q',
    array('controller'=>'notes','action'=>'search', 'page' => 1),
    array(
        'pass' => array('page','q')
    )
);

Router::connect('/notes/search/:q/page/:page', 
    array('controller' => 'notes', 'action' => 'search'),
    array(
        'pass' => array('page','q'),
        'page' => '[1-9]+'
        )
);

This way I should be getting urls like:

domain.com/notes - loads page 1 of notes

domain.com/notes/page/2 - loads page 2 of notes

domain.com/notes/search/Hello - searches for Hello in notes

domain.com/notes/search/Hello/page/2 - shows page 2 of the above search

The pager in the view looks like:

<?php if(isset($this->request->params['named']['q'])) { ?>
<?php $this->Paginator->options(array('url'=>array('controller' => 'notes', 'action' => $action, 'q' => $this->request->params['named']['q']))); ?>
<?php } else { ?>
<?php $this->Paginator->options(array('url'=>array('controller' => 'notes', 'action' => $action))); ?>
<?php } ?>

It works fine for the index method, but for the search method it is getting confused as when I do a search it's not matching the pager with the route as expected. For example I'm getting urls like domain.com/notes/search/2/:q

Also I don't really like having to wrap the paginator options in an if statement so if I can get it to figure out the url automatically that would be awesome as it's messy having to do this and seems to be the cause of the above problems.

I have connected the named parameter at the top of the router like so:

Router::connectNamed(array('q'));
  • 写回答

1条回答 默认 最新

  • douyin4561 2013-11-27 23:42
    关注

    In the end I opted to make my search working using POST instead of GET so that everything is handled sever-side instead of doing it with messy url rewrites and trying to be clever.

    Here's what I made the form look like:

    <?php echo $this->Form->create('search', array('url'=>array('controller'=>'notes','action'=>'search'),'class'=>'search')); ?>
        <label class="placeholder" for="q">Search</label>
        <?php if( isset($q) ) { $term = $q; } else { $term = ''; } ?>
        <?php echo $this->Form->input('q', array('label'=>false,'id'=>'q','value'=>$term)); ?>
        <button type="submit" class="btn ss-icon ss-search"></button>
    <?php echo $this->Form->end(); ?>
    

    the search method:

    function search()
    {
        if ($this->request->is('post')) {
    
            $this->Session->write('q', $this->request->data['search']['q']);
    
            $this->redirect(array('action' => 'search'));
    
        } else {
    
            $q = $this->Session->read('q');
    
            $this->paginate = array(
            'limit'=>5,
            'order'=>'Note.datetime DESC',
            'conditions' => array(
                'OR' => array(
                    'Note.title LIKE' => '%'. $q . '%',
                    'Note.content LIKE' => '%'. $q . '%'
                    )
                ),
                'Note.status'=>1
            );
    
            $this->set('q',$q);
    
            $this->set('action','search');
    
            $this->set('notes', $this->paginate());
    
            $this->render('index');
    
        }
    
    }
    

    and the routes:

    Router::connect('/notes/search',
        array('controller'=>'notes','action'=>'search', 'page' => 1),
        array(
            'pass' => array('page')
        )
    );
    Router::connect('/notes/search/page/:page', 
        array('controller' => 'notes', 'action' => 'search'),
        array(
            'pass' => array('page'),
            'page' => '[1-9]+'
            )
    );
    

    and I clean up the session if any other page but the search method is being used in the AppController:

    if(strpos($this->here, Router::url(array('controller'=>'notes','action'=>'search'))) === 0 ) {
    
        //echo 'yes';
    
    } else {
    
        $this->Session->delete('q');
    
    }
    

    Which gives me urls like:

    domain.com/notes - loads page 1 of notes

    domain.com/notes/page/2 - loads page 2 of notes

    domain.com/notes/search - searches for Hello in notes (stored in session)

    domain.com/notes/search/page/2 - shows page 2 of the above search

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换