BadMethodCallException:调用未定义的方法Illuminate \ Database \ Query \ Builder :: createTickets()

时间:2019-08-05 04:14:40

标签: laravel-5

我正在处理定单功能。理想情况下,应为单个订单生成许多票证。

以前,创建票证的职责是在Order模型内部编写的,那时它可以正常工作,但是现在我试图将这一职责转移到Ticket模型本身,所以它没有用。 / p>

我将从测试文件“ TicketTest.php”开始

<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\Concert;
use Carbon\Carbon;
use App\Order;

class TicketTest extends TestCase
{
    use DatabaseMigrations;

    /** @test */
    function can_create_multiple_tickets_for_order(){

        $numberOfTickets = 2;

        // Arrange - Create Concert and Order
        $concert = factory(Concert::class)->create(
            [
                'date' => Carbon::parse('December 1, 2016 8:00pm'),
            ]
        );

        $order = $concert->orders()->create([
            'email' => 'abc@gmail.com'
        ]);

        // Act - Create Tickets
        $order->tickets()->createTickets($numberOfTickets); // This line throws call to undefined method.

        // Assert
        $this->assertEquals($numberOfTickets, $order->tickets()->count());

    }
}

'Order.php'模型

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    protected $guarded = [];

    public function tickets()
    {
        return $this->hasMany(Ticket::class);
    }

}

'Ticket.php'模型

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Ticket extends Model
{
    public function createTickets($ticketQuantity){
        foreach(range(1, $ticketQuantity) as $i) {
            $this->create([]);
        }
    }

    public function order(){
        return $this->belongsTo(Order::class);
    }
}

1 个答案:

答案 0 :(得分:0)

在Laravel 5.4之前,我通过创建一个新的Relation并将该关系从Map Order映射到Ticket来解决了这个问题。创建了一个文件“ app / Relation / TicketOrderRelation.php”,并在其中添加了以下代码

<?php
namespace App\Relation;

use Illuminate\Database\Eloquent\Relations\HasMany;

class TicketOrderRelation extends HasMany {

    /**
     * Create a Collection of new tickets
     *
     * @param int $ticketQuantity Number of Tickets to be created 
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function createTickets($ticketQuantity){
        $instances = [];

        foreach(range(1, $ticketQuantity) as $i) {
            $instances[] = $this->create([]);
        }

        return collect($instances);
    }
}

新的“ Order.php”文件

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Relation\TicketOrderRelation;

class Order extends Model
{
    protected $guarded = [];

    /**
     * Define a one-to-many relationship. One Order can have many tickets.
     * 
     * This method is duplicate of hasMany method. The only difference is it
     * returns object of TicketOrderRelation class at the bottom instead of 
     * object of HasMany class.
     *
     * @param  string  $related
     * @param  string  $foreignKey
     * @param  string  $localKey
     * @return \App\Relation\TicketOrderRelation
     */
    public function ticketOrderRelation($related, $foreignKey = null, $localKey = null)
    {
        $foreignKey = $foreignKey ?: $this->getForeignKey();

        $instance = new $related;

        $localKey = $localKey ?: $this->getKeyName();

        return new TicketOrderRelation($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
    }

    public function tickets()
    {
        return $this->ticketOrderRelation(Ticket::class);
    }

}

新的“ Ticket.php”文件

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Ticket extends Model
{

    protected $guarded = [];

    public function order()
    {
        return $this->belongsTo(Order::class);
    }
}

在Laravel 5.4之后,雄辩的生成器开始支持create方法,这使创建变得容易。

This答案显示了如何创建自定义生成器。我尚未尝试过自定义生成器是否可以在Laravel 5.4上解决此问题,但是如果可以,那么我希望这样做。