代码之家  ›  专栏  ›  技术社区  ›  Odyssee

Laravel:更新前模型id变为真

  •  0
  • Odyssee  · 技术社区  · 8 年前

    我的情况很奇怪。我有一段代码在过去从来没有给出任何问题。从昨晚开始就这样了。

        public function export(Request $request, VeniceService $service, Invoice $invoice)
        {
            $invoice = $invoice->load([
                'user', 'customer', 'extension.referenceValues.definition', 'lines'
            ]);
            $this->enforce([
                new CheckCstNum($invoice->customer),
                new CheckReferences($invoice->extension),
            ], 432);
    
            if ($invoice->to_export) {
                DB::beginTransaction();
                try {
                    var_dump($invoice->id); // returns the id
                    $data = $service->export($invoice);
                    var_dump($invoice->id); // returns the true
                    $invoice->book_date = Carbon::now();
                    $invoice->doc_num = $data['doc_num'];
                    $invoice->sys_num = $data['sys_num'];
                    $invoice->tsm_num = $data['tsm_num'];
    
                    $invoice->to_export = false;
                    $invoice->is_ticked = false;
    
    
                    var_dump($invoice->id); // This returns true
                    var_dump($invoice); // All the values are correct, except the id, this is set to true
    
                    $invoice->save(); // With the id as true, this throws an exception. Duplicate entries for PRIMARY key id, '1'
    
                    DB::commit();
                    $service->attachPdf($invoice, Printer::print($invoice)->output());
                } catch (VeniceException $e) {
                    DB::rollBack();
                    return $e->render($request);
                } catch (\Exception $e) {
                    DB::rollBack();
                    return response()->json($e->getMessage(), 500);
                }
            }
    
            return new InvoiceResource($invoice->refresh()); // returns the invoice, but the id is still true
        }
    

    $this->service->export() 解析为此函数。在此之前,id仍然是模型的原始id。

        public function export($model)
        {
            return $this->call($model, __FUNCTION__);
        }
    
        protected function call($model, $function)
        {
            $class = $this->getClassName($model);
            $method = "{$function}{$class}";
            return $this->$method($model);
        }
    
        public function exportInvoice($invoice)
        {
            var_dump($invoice->id); // Returns the id
            $veniceInvoice = (new VeniceInvoiceResource($invoice))->toArray(request());
            var_dump($invoice->id); // Returns true...
    
            return $this->request('POST', 'venice/invoices/' . $this->bookSales, [
                RequestOptions::JSON => $veniceInvoice
            ]);
        }
    

    $veniceInvoice = (new VeniceInvoice($invoice))->toArray(request()); 在这一行之后,id被设置为true。这真的没有任何意义,因为它一直在工作,模型不会得到任何方式操纵。

    最后一段代码。但我不认为这与这个问题有任何关系。

        public function toArray($request)
        {
            $pdf = Printer::print($this->resource)->output();
    
            $lines = $this->customer->standard_base == 10 ? VeniceInvoiceLineIC::collection($this->lines) : VeniceInvoiceLine::collection($this->lines);
            $refs = $this->extension->referenceValues->map(function ($item) {
                return [
                    'index' => 0,
                    'quantity' => 0,
                    'unit_price' => 0,
                    'description' => $item->definition->name . ' ' . $item->value,
                    'vat_code' => 0,
                    'ic_code' => 0,
                ];
            })->toArray();
    
            $details = array_merge($refs, $lines->toArray($request));
    
            return [
                'cst_num' => $this->customer->cst_num,
                'book' => ($this->book === 'VKPCN') ? $this->book : config('venice.config.sales.book'),
                'amount' => $this->total,
                'vat_amount' => $this->total,
                'exp_date' => carbon(config('venice.config.sales.date'))->addDays($this->customer->exp_term)->format('d/m/Y'),
                'doc_date' => carbon(config('venice.config.sales.date'))->format('d/m/Y'),
                'vat_system' => $this->customer->vat_system,
                'bf_code' => $this->customer->bf_code,
                'doc_type' => ($this->doc_type === 'slsCreditnote') ? 1 : 0, 
                'pdf' => base64_encode($pdf),
                'pdfName' => $this->date->format('Ym') . '-' . $this->id . '.pdf',
                'remark' => 'Clockwork ' . $this->date->format('Y F') . ' ' . $this->user->name,
                'details' => $details,
            ];
        }
    

    ...
        $invoice_copy = clone $invoice;
    
        if ($invoice->to_export) {
            DB::beginTransaction();
            try {
                $data = $service->export($invoice);
    
                $invoice->book_date = Carbon::now();
                $invoice->doc_num = $data['doc_num'];
                $invoice->sys_num = $data['sys_num'];
                $invoice->tsm_num = $data['tsm_num'];
    
                $invoice->to_export = false;
                $invoice->is_ticked = false;
                $invoice->id = $invoice_copy->id;
                $invoice->save();
                DB::commit();
    ...
    

    经过大量调试,我已经确定了id设置为true的位置。我还是不知道为什么。

    $this->id 在生成PDF之前,id仍然是原始发票id。在打印机之后,id是 true .

    Illuminat\Http\Resources\JsonResource (Resource扩展了JsonResource)我明白了 $this->resource $invoice .

        /**
         * Create a new resource instance.
         *
         * @param  mixed  $resource
         * @return void
         */
        public function __construct($resource)
        {
            $this->resource = $resource;
        }
    

    在里面的时候 VeniceInvoiceResource $此->资源被传递到打印机实例。在资源中 $this 还有发票的值。

        /**
         * Load items to print.
         *
         * @param $items
         * @return $this
         * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
         */
        public function print($items, $toPrint = null)
        {
            $items = is_array($items) || $items instanceof Collection ? $items : func_get_args();
    
            foreach ($items as $item) {
                if ($item instanceof Printable) {
                    foreach ($item->printData($toPrint) as $key => $data) {
                        switch($key) {
                            case 'merge':
                                $this->mergeOutput($data);
                                break;
                            case 'mergeFile':
                                $this->mergeFile($data);
                                break;
                            default:
                                $this->toPrint[] = $this->view->make($key, $data)->render();
                        }
                    }
                } elseif ($item instanceof Renderable) {
                    $this->toPrint[] = $item->render();
                } elseif (is_string($item)) {
                    $this->toPrint[] = $item;
                } else {
                    throw new \InvalidArgumentException('Invalid argument');
                }
            }
    
            return $this;
        }
    

    在打印方法中, $this->toPrint[] = $this->view->make($key, $data)->render();

        /**
         * Get the output as string.
         *
         * @return string
         * @throws \iio\libmergepdf\Exception
         */
        public function output()
        {
            return $this->generate();
        }
    
        /**
         * Generate and merge.
         *
         * @return string
         * @throws \iio\libmergepdf\Exception
         */
        protected function generate()
        {
            $data = !empty($this->toPrint) ? $this->toPrint : [''];
            $result = $this->pdf->getOutputFromHtml($data); 
    
            if (!empty($this->toMerge)) {
                $this->merger->addRaw($result);
    
                foreach ($this->toMerge as $item) {
                    $this->merger->addRaw($item);
                }
                $result = $this->merger->merge();
            }
    
            $this->toPrint = null;
            $this->toMerge = null;
    
            return $result;
        } 
    

    在打印服务中,没有任何操作,它只是将集合和项目打印为PDF格式。

    最后一次编辑,因为我找到了导致这一切的那一行。但我不完全明白为什么它会把id设为真。

    在 Printer::print printData()

            if ($this->id = 4128 || $this->id === 4217) {
                $vat_amount = 0;
                $vat_label = '';
            }
    

    4128 & 4217 已经打印并存档了。它们不需要再处理了。

    1 回复  |  直到 8 年前
        1
  •  2
  •   patricus    8 年前

    看起来你在你的电脑里找到了问题 printData()

    id 最终成为 true ,这是因为 operator precedences .

    === || ),所以比较是在逻辑比较之前进行的。因此,如果比较运算符是正确的,则会运行以下操作(为清楚起见,添加了parens):

    ($this->id === 4128) || ($this->id === 4217)
    

    $this->id = (4128 || $this->id === 4217)
    

    分配给逻辑比较的结果。因为所有非零数的计算结果都是 是的 ,因此 身份证件 准备好了吗 .