diff --git a/src/Grid.php b/src/Grid.php index 0fe5d999c3..409b827ec5 100644 --- a/src/Grid.php +++ b/src/Grid.php @@ -355,6 +355,8 @@ public function build() $data = $this->processFilter(); + Column::setOriginalGridData($data); + $this->columns->map(function (Column $column) use (&$data) { $data = $column->fill($data); diff --git a/src/Grid/Column.php b/src/Grid/Column.php index 8d53a1c46a..56a2eb39fa 100644 --- a/src/Grid/Column.php +++ b/src/Grid/Column.php @@ -83,6 +83,13 @@ class Column */ protected $relationColumn; + /** + * Original grid data. + * + * @var array + */ + protected static $originalGridData = []; + /** * @param string $name * @param string $label @@ -331,7 +338,7 @@ public function editable() */ public function value(Closure $callable) { - $this->valueCallback = $callable->bindTo($this); + $this->valueCallback = $callable; return $this; } @@ -410,27 +417,58 @@ protected function htmlWrap($value, $row = []) */ public function fill(array $data) { - foreach ($data as &$item) { - $this->original = $value = array_get($item, $this->name); + foreach ($data as $key => &$row) { + $this->original = $value = array_get($row, $this->name); + + $isCustomColumn = !array_has($row, $this->name); $value = $this->htmlEntityEncode($value); - array_set($item, $this->name, $value); + array_set($row, $this->name, $value); if ($this->hasValueCallback()) { - $value = call_user_func($this->valueCallback, $this->original); - array_set($item, $this->name, $value); + + $input = $isCustomColumn ? $row : $this->original; + + $callback = $this->bindOriginalRow($this->valueCallback, $key); + $value = call_user_func($callback, $input); + array_set($row, $this->name, $value); } if ($this->hasHtmlCallback()) { - $value = $this->htmlWrap($value, $item); - array_set($item, $this->name, $value); + $value = $this->htmlWrap($value, $row); + array_set($row, $this->name, $value); } } return $data; } + /** + * Set original grid data to column. + * + * @param Closure $callback + * @param int $key + * + * @return Closure + */ + protected function bindOriginalRow(Closure $callback, $key) + { + $originalRow = static::$originalGridData[$key]; + + return $callback->bindTo((object)$originalRow); + } + + /** + * Set original data for column. + * + * @param array $input + */ + public static function setOriginalGridData(array $input) + { + static::$originalGridData = $input; + } + /** * Convert characters to HTML entities recursively. * diff --git a/tests/UserGridTest.php b/tests/UserGridTest.php index b50f4494ed..d3385747f9 100644 --- a/tests/UserGridTest.php +++ b/tests/UserGridTest.php @@ -158,6 +158,19 @@ public function testFilterRelation() ->seeInElement('td', $user->end_at); } + public function testValueCallback() + { + $this->seedsTable(1); + + $user = UserModel::with('profile')->find(1); + + $this->visit('admin/users') + ->seeInElement('th', 'Column1 not in table') + ->seeInElement('th', 'Column2 not in table') + ->seeInElement('td', "full name:{$user->profile->first_name} {$user->profile->last_name}") + ->seeInElement('td', "{$user->email}#{$user->profile->color}"); + } + public function testHasManyRelation() { factory(\Tests\Models\User::class, 10) diff --git a/tests/controllers/UserController.php b/tests/controllers/UserController.php index b32a7b7adc..2f84dc0c61 100644 --- a/tests/controllers/UserController.php +++ b/tests/controllers/UserController.php @@ -85,6 +85,14 @@ protected function grid() $grid->profile()->start_at('开始时间'); $grid->profile()->end_at('结束时间'); + $grid->column('column1_not_in_table')->display(function ($row) { + return 'full name:'.$row['full_name']; + }); + + $grid->column('column2_not_in_table')->display(function ($row) { + return $this->email.'#'.$this->profile['color']; + }); + $grid->tags()->value(function ($tags) { $tags = collect($tags)->map(function ($tag) { return "{$tag['name']}";