Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 Laravel 5.x » Требуется помощь с выгрузкой в laravel nova данных cтолбца в exel? » 14.09.2019 08:08:10

josho
Ответов: 0

Добрый день форумчане , есть готовый скрипт который выгружает данные в формате эксель, то есть есть готовый ресур, в котором реализованы поля и значения а так же есть акшен который выполняет саму запись значений в эксель и экспорт.
Мне нужна помощь по тому чтобы экспортировать в эксель значение функции которая рассчитывает стаж работника на рабочем месте, остальное все и так работает отлично.
Кстати в ресурсе на странице выводится в поле Стаж и сам период стажа . Реализовано это вот так и  оно работает

Text::make('Стаж', function () {
if ($first = $this->employment_date) {
$second = $this->dissmissal_date ?? Carbon::today();
return ru_year_month_interval($first->diffInMonths($second));
}
return '—';
})->OnlyOnDetail(),

Дальше при выборе всех сотрудников я экспортирую их в экселе и в самом эксель фаиле хочу увидеть столбец со стажем и его значениями на каждого сотруднка, у меня возникла сложность с передачей в массив значения функции которая выводит стаж.

То есть Название столбца "Стаж" у меня выводиться в экспортированном экселе , а вот  значения стажа (которые получаю из функции), нет ... ?

Ниже я прилагаю  код, это ресурс и код экшиона который производит  выгрузку.
1) "Ресурс", обращаю ваше внимание что  значения полей все берутся из базы, кроме значения поля стаж, его формирует функция,
которая считает разницу во времени поля 'дата принятия на работу' и поля 'дата уволнения'  или текущей метки времени.



<?php

namespace App\Nova;

use Carbon\Carbon;
use Laravel\Nova\Fields\Boolean;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\Textarea;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Fields\DateTime;
//use Laravel\Nova\Fields\Date;
use Laravel\Nova\Fields\Select;
use Laravel\Nova\Fields\Number;
use Illuminate\Http\Request;
use App\Nova\Actions\DownloadExcel;
use App\Traits\NovaSearchesRelationsWithArrays;
use PositionPicker\PositionPicker;

class Position extends Resource
{
    use NovaSearchesRelationsWithArrays;

    public static $searchRelations = [
        'user' => [
            'name',
            'surname',
            ['surname', 'name'],
        ],
    ];

    public static $searchRelationsGlobally = false;

    public static $model = 'App\Position';

    public static $title = 'id';

    public static $search = [
        'id',
    ];

    public static function label()
    {
        return 'Должности';
    }

    public static $with = [
        'user',
        'department',
        'company',
        'leader',
        'positionName',
    ];

    /**
     * Get the fields displayed by the resource.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function fields(Request $request)
    {
        return [
            ID::make()->sortable(),

            Text::make('Статус', function () {
                return $this->status;
            }),

            BelongsTo::make('Человек', 'user', 'App\Nova\User')->searchable()->prepopulate(),

            BelongsTo::make('Отдел', 'department', 'App\Nova\Department')
                ->searchable()
                ->prepopulate()
            ,

            PositionPicker::make('Должность', 'positionName', 'App\Nova\PositionName')
                ->nullable(),

            BelongsTo::make('Руководитель', 'leader', 'App\Nova\User')
                ->searchable()
                ->nullable(),

            BelongsTo::make('Компания', 'company', 'App\Nova\Company')
                ->searchable()
                ->prepopulate()
                ->nullable(),

            BelongsTo::make('Вид договора', 'contractType', 'App\Nova\ContractType')
                ->hideFromIndex(),

         Date\Date::make('Дата приёма', 'employment_date')
//                ->format('DD.MM.Y')
                ->nullable()
                ->hideFromIndex(),

            Text::make('Стаж', function () {
                    if ($first = $this->employment_date) {
                        $second = $this->dissmissal_date ?? Carbon::today();
                        return ru_year_month_interval($first->diffInMonths($second));
                    }
                    return '—';
                })->OnlyOnDetail(),

      Date\Date::make('Контрольный срок', 'control_date')
//                ->format('DD.MM.Y')
                ->nullable()
                ->hideFromIndex(),

            Text::make('IP Телефон', 'phone_ip_number')
                ->rules('max:50')
                ->hideFromIndex(),

            Number::make('Срок подбора', 'recruitment_term')
                ->step(1)
                ->hideFromIndex(),

            BelongsTo::make('Канал подбора', 'recruitmentChannel', 'App\Nova\RecruitmentChannel')
                ->searchable()
                ->prepopulate()
                ->nullable()
                ->hideFromIndex(),

            Textarea::make('Комментарий подбора', 'recruitment_channel_comment')
                ->alwaysShow(),

            BelongsTo::make('Рекрутёр', 'recruiter', 'App\Nova\User')
                ->searchable()
                ->nullable()
                ->hideFromIndex(),

           Date\Date::make('Дата увольнения', 'dissmissal_date')
//                ->format('DD.MM.Y')
                ->nullable()
                ->hideFromIndex(),

            Select::make('Причина увольнения', 'dissmissal_reason')
                ->options(dissmissal_reason_map())
                ->displayUsingLabels()
                ->sortable()
                ->hideFromIndex(),

            Textarea::make('Комментарий', 'dissmissal_comment')
                ->alwaysShow(),

            Boolean::make('Экспортировать в Wiki', 'show_on_wiki')
                ->hideFromIndex(),

            DateTime::make('Последнее изменение', 'updated_at')->onlyOnDetail(),

            BelongsTo::make('Последний изменивший', 'updatedBy', 'App\Nova\User')->onlyOnDetail(),
        ];
    }

    public function filters(Request $request)
    {
        return [
            new Filters\DepartmentFilter,
            new Filters\CompanyFilter,
            new Filters\ContractTypeFilter,
            new Filters\PositionCategoryFilter,
            new Filters\DistributionGroupFilter,
            new Filters\WorkExperienceFilter,
            new Filters\PositionStatusFilter,
        ];
    }

    public function lenses(Request $request)
    {
        return [
            new Lenses\PositionControlDates(new \App\Position),
        ];
    }

    public function actions(Request $request)
    {

   
     return =
        [new DownloadExcel(
                [
                    'user' => 'Сотрудник',
                    'user_email' => 'Почта',
                    'company' => 'Компания',
                    'department' => 'Отдел',
                    'positionName' => 'Должность',
                    'positionCategory' => 'Категория сотрудника',
                    'contractType' => 'Вид договора',
                    'leader' => 'Руководитель',
                    'control_date' => 'Контрольный срок',
                    'employment_date' => 'Дата приёма',
                    'dissmissal_date' => 'Дата увольнения',
                    'dissmissal_reason' => 'Причина увольнения',
                    'dissmissal_comment' => 'Комментарий',
                    'recruitment_term' => 'Срок подбора',
                    'recruitmentChannel' => 'Канал подбора',
                    'recruitment_channel_comment' => 'Комментарий подбора',
                    'recruiter' => 'Рекрутёр',
                    'distribution_group' => 'Группа рассылки',
                ],
                'positions',
                ['control_date', 'employment_date', 'dissmissal_date'],
                [
                    'user' => 'fio',
                    'user_email' => ['user', 'email'],
                    'company' => 'name',
                    'department' => 'name',
                    'positionName' => 'name',
                    'positionCategory' => ['positionName', 'positionCategoryName'],
                    'distribution_group' => ['positionName', 'distributionGroupName'],
                    'contractType' => 'name',
                    'leader' => 'fio',
                    'recruitmentChannel' => 'name',
                    'recruiter' => 'fio',
                ],
                [
//                    'distribution_group' => distribution_group_map(),
                    'dissmissal_reason' => dissmissal_reason_map(),
                ]
            ),
        ];
    }
}

код экшина :

<?php
namespace App\Nova\Actions;
use Illuminate\Bus\Queueable;
use Illuminate\Support\Facades\Hash;
use Laravel\Nova\Actions\Action;
use Illuminate\Support\Collection;
use Laravel\Nova\Fields\ActionFields;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Laravel\Nova\Fields\Boolean;
use Laravel\Nova\Fields\Text;

class  DownloadExcel extends Action
{
    use InteractsWithQueue, Queueable, SerializesModels;

    private $columns;
    private $default_name;
    private $dates;
    private $foreign;
    private $enums;
    private $borders;

    public $name = 'Экспорт в Excel';

    public function __construct($columns, $default_name = null, $dates = [], $foreign = [], $enums = [], $borders = false)
    {
        $this->columns = $columns;
        $this->default_name = $default_name;
        $this->dates = $dates;
        $this->foreign = $foreign;
        $this->enums = $enums;
        $this->borders = $borders;
    }

    /**
     * Perform the action on the given models.
     *
     * @param  \Laravel\Nova\Fields\ActionFields  $fields
     * @param  \Illuminate\Support\Collection  $models
     * @return mixed
     */
    public function handle(ActionFields $fields, Collection $models)
    {
        $attrs = $fields->getAttributes();
        unset($attrs['file_name']);

        $l = 'A';
        $columns = [];
        foreach ($attrs as $column => $value) {
            if ($value) {
                if (in_array($column, $this->dates))
                    $type = 'date';
                elseif (in_array($column, array_keys($this->foreign)))
                    $type = 'foreign';
                elseif (in_array($column, array_keys($this->enums)))
                    $type = 'enum';
                else
                    $type = 'string';
                $columns[$l++] = [
                    'name' => $column,
                    'type' => $type,
                ];
            }
        }
        $array = [];
        foreach ($models as $i => $model) {
            $t = [];
            foreach ($columns as $l => $column) {
                $value = '';
                switch ($column['type']) {
                    case 'date':
                        if ($model->{$column['name']}) {
                            $value = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($model->{$column['name']});
                        }
                        break;
                    case 'foreign':
                        if (is_array($this->foreign[$column['name']])) {
                            if (isset($model->{$this->foreign[$column['name']][0]}))
                                $value = $model->{$this->foreign[$column['name']][0]}->{$this->foreign[$column['name']][1]};
                        } elseif (isset($model->{$column['name']}))
                            $value = $model->{$column['name']}->{$this->foreign[$column['name']]};
                        break;
                    case 'enum':
                        if (isset($model->{$column['name']}))
                            $value = $this->enums[$column['name']][$model->{$column['name']}];
                        break;
                    default:
                        $value = $model->{$column['name']} ?? '';
                        break;
                }

                $t[$l] = $value;
            }
            $array[] = $t;
        }
        return $array;
    }

    public function handleResult(ActionFields $fields, $results)
    {
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        try {
            $spreadsheet->setActiveSheetIndex(0);
        } catch(\PhpOffice\PhpSpreadsheet\Exception $e) {
            return Action::danger('Произошла ошибка, обратитесь а администратору.');
        }

        $attrs = $fields->getAttributes();
        $file_name = $attrs['file_name'];
        unset($attrs['file_name']);
        $l = 'A';
        $columns = [];

        try {
            $active_sheet = $spreadsheet->getActiveSheet();
        } catch(\PhpOffice\PhpSpreadsheet\Exception $e) {
            return Action::danger('Произошла ошибка, обратитесь а администратору.');
        }

        foreach ($attrs as $column => $value) {
            if ($value) {
                $active_sheet->setCellValue($l . '1', $this->columns[$column]);
                $active_sheet->getColumnDimension($l)->setAutoSize(true);
                if (in_array($column, $this->dates))
                    $type = 'date';
                elseif (in_array($column, array_keys($this->foreign)))
                    $type = 'foreign';
                elseif (in_array($column, array_keys($this->enums)))
                    $type = 'enum';
                else
                    $type = 'string';
                $columns[$l++] = [
                    'name' => $column,
                    'type' => $type,
                ];
            }
        }
        $i = 2;
        foreach ($results as $result)
            foreach ($result as $r) {
                foreach ($columns as $l => $column) {
                    if ($column['type'] === 'date') {
                        $active_sheet->getStyle($l . $i)
                            ->getNumberFormat()->setFormatCode('dd.mm.YYYY');
                    }

                    $active_sheet->setCellValue($l . $i, $r[$l]);
                }
                $i++;
            }

        if ($this->borders) {
            $styleArray = ['borders' => ['allBorders' => ['borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN]]];
            $active_sheet->getStyle('A1:' . --$l . ($i - 1))->applyFromArray($styleArray);
        }


        $fn = \Auth::user()->id . '-' . $file_name;//Hash::make($file_name);
        try {
            $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, "Xlsx");
            $writer->save(storage_path("app/public/excel_tmp/$fn.xlsx"));
        } catch(\PhpOffice\PhpSpreadsheet\Exception $e) {
            return Action::danger('Произошла ошибка, обратитесь а администратору.');
        }

        return Action::download(
            url('/download_excel?') . http_build_query([
                'path'     => storage_path("app/public/excel_tmp/"),
                'filename' => "$fn.xlsx",
                'ffn' => "$file_name.xlsx",
            ]),
            "$file_name.xlsx"
        );
    }

    public function fields()
    {
        $fields = [Text::make('Имя файла', 'file_name')->withMeta(["value" => $this->default_name])];
        foreach ($this->columns as $name => $caption) {
            $fields[] = Boolean::make($caption, $name)->withMeta(["value" => "true"]);
        }
        return $fields;
    }
}

Подвал раздела