yii2 增删改查后仍留在当前页的方法 - 编程思维

序言

实现增删改查操作成功后仍留在当前页,能给用户一个良好的体验。但是 Yii2 框架本身是没有在增删改查操作成功后仍留在当前页的效果的,要实现这样的一个效果得自己写。我的原则是不动核心代码,始终坚持自己的原则,现实现了我把它分享出来。殊途同归,如有更好的实现方法,欢迎交流。

需求分析

1、实现增删改查后操作成功后仍然留在当前页面。

效果图

1、链接的效果图

封装代码

共有两个文件ActionColumn.php和Helper.php
1、ActionColumn.php文件

<?php

use Closure;
use kartik\icons\Icon;
use Yii;
use yii\grid\Column;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Url;
use common\components\Helper;

/*
*重写ActionColumn
 */
class ActionColumn extends Column
{  
    public $buttons;

    private $defaultButtons = [];

    private $callbackButtons;
    
    public $controller;

    public $urlCreator;

    public $url_append = '';

    public $appendReturnUrl = true; //默认为true,返回当前链接

    public function init()
    {
        parent::init();
       
        $this->defaultButtons = [
            [
                'url' => 'view',
                'icon' => 'eye',
                'class' => 'btn btn-success btn-xs',
                'label' => Yii::t('yii', 'View'),
                'appendReturnUrl' => false,
                'url_append' => '',
                'keyParam' => 'id',//是否传id,不传设置null
            ],
            [
                'url' => 'update',
                'icon' => 'pencil',
                'class' => 'btn btn-primary btn-xs',
                'label' => Yii::t('yii', 'Update'),
            ],
            [
                'url' => 'delete',
                'icon' => 'trash-o',
                'class' => 'btn btn-danger btn-xs',
                'label' => Yii::t('yii', 'Delete'),
                'options' => [
                    'data-action' => 'delete',
                ],
            ]
        ];


        if (null === $this->buttons) {
            $this->buttons = $this->defaultButtons;
        } elseif ($this->buttons instanceof Closure) {
            $this->callbackButtons = $this->buttons;
        }
    }

   
    public function createUrl(
        $action,
        $model,
        $key,
        $index,
        $appendReturnUrl = null,
        $url_append = null,
        $keyParam = 'id',
        $attrs = []
    ) {
        if ($this->urlCreator instanceof Closure) {
            return call_user_func($this->urlCreator, $action, $model, $key, $index);
        } else {
            $params = [];
            if (is_array($key)) {
                $params = $key;
            } else {
                if (is_null($keyParam) === false) {
                    $params = [$keyParam => (string)$key];
                }
            }
            $params[0] = $this->controller ? $this->controller . '/' . $action : $action;
            foreach ($attrs as $attrName) {
                if ($attrName === 'model') {
                    $params['model'] = $model;
                } elseif ($attrName === 'mainCategory.category_group_id' && $model->getMainCategory()) {
                    $params['category_group_id'] = $model->getMainCategory()->category_group_id;
                } else {
                    $params[$attrName] = $model->getAttribute($attrName);
                }
            }
            if (is_null($appendReturnUrl) === true) {
                $appendReturnUrl = $this->appendReturnUrl;
            }
            if (is_null($url_append) === true) {
                $url_append = $this->url_append;
            }
            if ($appendReturnUrl) {
                $params['returnUrl'] = Helper::getReturnUrl();
            }
            return Url::toRoute($params) . $url_append;
        }
    }


    protected function renderDataCellContent($model, $key, $index)
    { 
        if ($this->callbackButtons instanceof Closure) {
            $btns = call_user_func($this->callbackButtons, $model, $key, $index, $this); 
            if (null === $btns) {
                $this->buttons = $this->defaultButtons;
            } else {
                $this->buttons = $btns;
            }
        }
        $min_width = count($this->buttons) * 34; //34 is button-width
        $data = Html::beginTag('div', ['class' => 'btn-group', 'style' => 'min-width: ' . $min_width . 'px']);
        foreach ($this->buttons as $button) {
            $appendReturnUrl = ArrayHelper::getValue($button, 'appendReturnUrl', $this->appendReturnUrl);
            $url_append = ArrayHelper::getValue($button, 'url_append', $this->url_append);
            $keyParam = ArrayHelper::getValue($button, 'keyParam', 'id');
            $attrs = ArrayHelper::getValue($button, 'attrs', []);
            Html::addCssClass($button, 'btn');
            Html::addCssClass($button, 'btn-sm');
            $buttonText = isset($button['text']) ? ' ' . $button['text'] : ''; 
            $data .= Html::a(
                    $button['label'] . $buttonText,
                    $url = $this->createUrl(
                        $button['url'],
                        $model,
                        $key,
                        $index,
                        $appendReturnUrl,
                        $url_append,
                        $keyParam,
                        $attrs
                    ),
                    ArrayHelper::merge(
                        isset($button['options']) ? $button['options'] : [],
                        [
                            //'data-pjax' => 0,
                            // 'data-action' => $button['url'],
                            'class' => $button['class'],
                            'title' => $button['label'],
                        ]
                    )
                ) . ' ';
        }
        $data .= '</div>';  
        return $data;
    }

}

2、Helper.php文件

<?php

use Yii;

class Helper
{   
    private static $returnUrl;
    public static $returnUrlWithoutHistory = false;

    /**
     * @param int $depth
     * @return string
     */
    public static function getReturnUrl()
    {
        if (is_null(self::$returnUrl)) {
            $url = parse_url(Yii::$app->request->url);
            $returnUrlParams = [];
            if (isset($url['query'])) {
                $parts = explode('&', $url['query']);
                foreach ($parts as $part) {
                    $pieces = explode('=', $part);
                    if (static::$returnUrlWithoutHistory && count($pieces) == 2 && $pieces[0] === 'returnUrl') {
                        continue;
                    }
                    if (count($pieces) == 2 && strlen($pieces[1]) > 0) {
                        $returnUrlParams[] = $part;
                    }
                }
            }
            if (count($returnUrlParams) > 0) {
                self::$returnUrl = $url['path'] . '?' . implode('&', $returnUrlParams);
            } else {
                self::$returnUrl = $url['path'];
            }
        }
        return self::$returnUrl;
    }
}

视图调用

1、直接调用,把Yii2自带的['class' => 'yiigridActionColumn']换成我们新写的['class' => 'common\components\ActionColumn']
2、如直接调用不能满足你的要求可以自定义链接,自定义链接的写法如下:

[
  'class' => 'common\components\ActionColumn',
  'urlCreator' => function($action, $model, $key, $index) use ($id) {
        //自定义链接传的参数
        $params = [
              $action,
              'option_id' => $model->option_id, 
              'id' => $id,
        ];
        $params['returnUrl'] = common\components\Helper::getReturnUrl();
        return yii\helpers\Url::toRoute($params);
   },
   'buttons' => [
                  [
                   'url' =>'view',
                   'class' => 'btn btn-success btn-xs',
                   'label' => Yii::t('yii', 'View'),
                   'appendReturnUrl' => false,//是否保留当前URL,默认为true
                   'url_append' => '',
                   'keyParam' => 'id', //是否传id,不传设置null
                  ],
                  [
                   'url' => 'update',
                   'class' => 'btn btn-primary btn-xs btn-sm',
                   'label' => Yii::t('yii', 'Update'),
                   'appendReturnUrl' => true,//是否保留当前URL,默认为true
                   'url_append' => '',
                   'keyParam' => 'id', //是否传id,不传设置null
                  ],
                  [
                   'url' => 'delete',
                   'class' => 'btn btn-danger btn-xs btn-sm',
                   'label' => Yii::t('yii', 'Delete'),
                   'options' => [
                        'data-action' => 'delete',
                   ],
                   'appendReturnUrl' => true,//是否保留当前URL,默认为true
                   'url_append' => '',
                   'keyParam' => 'id', //是否传id,不传设置null
                 ],
    ],

],

3、新增的话,这么引用<?= Html::a(Yii::t('yii', 'Create'), ['create','returnUrl' => Helper::getReturnUrl()], ['class' => 'btn btn-success']) ?>

控制器逻辑

1、用get获取returnUrl,代码:$returnUrl = Yii::$app->request->get('returnUrl');
2、跳转到的URL:return $this->redirect($returnUrl);。

分析总结

1、此方法的好处是不动核心代码,调用方式保留了Yii2自带的方式。
2、不足之处是在自定义链接的时候需要把每一个操作update、view、delete都写出来,不能用这种'template' => '{view}{update}{delete}'简单且看着舒服能根据需求去写了。
~本文完。

版权声明:本文版权归作者所有,遵循 CC 4.0 BY-SA 许可协议, 转载请注明原文链接
https://segmentfault.com/a/1190000005749662

《javascript web应用开发》作者nicolas:恰巧,爱好变职业(图灵访谈) - 编程思维

本文仅用于学习和交流目的,不得用于商业目的。非商业转载请注明作译者、出处,并保留本文的原始链接:http://www.ituring.com.cn/art... 访谈嘉宾: Nicolas Bevacqua,阿根廷人,是一位富有激情的JavaScript工程师,热衷于打造健壮的构建流程和清晰的应用架构。喜欢谈论关于Ja

《json必知必会》学习笔记(一) - 编程思维

什么是JSON JSON全称是Javascript Object Notation(对象表示法),是一种在不同平台间传递数据的文本格式(数据交换格式)。常见的数据交换格式有XML、JSON两种,我们主要研究JSON。 数据交换格式十分重要,开发人员需要使用它们来实现不同系统之间的数据交换。 JSON基于Javascri

新手必须要注意的编程范式 - 编程思维

编程语言与成百种编程语言(Programming Language)相比,编程范式(Programming Paradigm、范式)要少得多。如图所示,共有 27 种范式。多数范式之间仅相差一个或几个概念。主要的范式最常用的范式有三个:过程试编程,面向对象编程(OOP),函数式编程(FP)。然后我们介绍一下新兴的第四种

什么是移动应用开发的最佳编程语言?(一)python?c++? - 编程思维

什么是移动应用开发的最佳编程语言?移动应用程序的三种类型:•本机应用程序:这是设备操作系统本机支持的一种编码类型。•混合应用程序:应用程序以一种特定的语言编码,可以轻松地在多个平台上运行。•渐进式Web应用程序:这是一个轻量级应用程序,它在设备的Web浏览器的URL中运行。我们根据需求和受欢迎程度讨论您需要学习的顶级编

在大型软件项目中如何处理错误和异常 - 编程思维

我在测试中没有发现bug,所以系统没有bug,对吧?不幸的是,大规模的软件太复杂,无论多少测试都无法做到没有bug。你无法对用户使用应用程序的所有不同方式进行测试。因此,理解应用程序中错误和异常的区别是非常重要的,同时要了解处理它们的正确方法,以便你可以采取主动的方式为开发团队和终端用户提供健康的应用程序。测试的局限性

正在暑假中的《课多周刊》(第1期) - 编程思维

正在暑假中的《课多周刊》(第1期) 我们的微信公众号:fed-talk,更多精彩内容皆在微信公众号,欢迎关注。 若有帮助,请把 课多周刊 推荐给你的朋友,你的支持是我们最大的动力。 远上寒山石径斜,白云深处有人家。停车坐爱枫林晚,霜叶红于二月花。 杜牧 -《山行》 HTML/CSS 【译】22个必备的CSS小技巧(@

即将立秋的《课多周刊》(第2期) - 编程思维

即将立秋的《课多周刊》(第2期) 我们的微信公众号:fed-talk,更多精彩内容皆在微信公众号,欢迎关注。 若有帮助,请把 课多周刊 推荐给你的朋友,你的支持是我们最大的动力。 独立寒秋,湘江北去,橘子洲头。看万山红遍,层林尽染;漫江碧透,百舸争流。鹰击长空,鱼翔浅底,万类霜天竞自由。怅寥廓,问苍茫大地,谁主沉浮?携

jquery高级应用之deferred对象 - 编程思维

在实际开发中常常遇到这样的问题:B函数中需要用到的变量或者参数,只有等A函数执行完毕了才能获取到。比如A函数中有一个ajax请求,而B函数中所需要的position变量需要在A函数中ajax请求完成才能得到它的准确值。 function A() { $.ajax({ url: '/api/tes

【转】理解css模块化 - 编程思维

原文链接: https://www.sitepoint.com/und... 在瞬息万变的前端开发世界中,很难找到一个真正有意义的概念,并且将其清晰明了的向广大人民群众普及。 把目光投向CSS,一个重大转折就是CSS预处理器的出现(在工具方面来看),其中, Sass应该是最为著名的一个。此外,还有 PostCSS,它和

玩转react样式 - 编程思维

很久很久以前,就有人用CSS来时给HTML内容添加样式。CSS可以最大限度的分离样式和内容,选择器也可以很方便的给某些元素添加样式。你根本找不到任何不用CSS的理由。 但是在React这里就是另外一回事了,虽然React不是不用CSS。但是,它在给元素添加样式的时候方式不同。React的核心哲学之一就是让可视化的组件自