Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 从traits内部的类访问属性_Php_Laravel_Phpunit_Traits_Mockery - Fatal编程技术网

Php 从traits内部的类访问属性

Php 从traits内部的类访问属性,php,laravel,phpunit,traits,mockery,Php,Laravel,Phpunit,Traits,Mockery,我试图使用mock为startedAt()方法编写一个单元测试,但是我面临的问题是,我认为我无法从startedAt()方法内部访问生成器实例 为了测试startedAt()方法,我创建了一个名为ExampleFilters的fixture类,并让它扩展Filters的父类。在ExampleFiltersclass I的内部,导入FiltersByStartDatetrait 有人对我如何从FiltersByStartDatetrait访问builder属性有什么建议吗 有什么想法吗 <?

我试图使用mock为
startedAt()
方法编写一个单元测试,但是我面临的问题是,我认为我无法从
startedAt()方法内部访问生成器实例

为了测试
startedAt()
方法,我创建了一个名为
ExampleFilters
的fixture类,并让它扩展
Filters
的父类。在
ExampleFilters
class I的内部,导入
FiltersByStartDate
trait

有人对我如何从
FiltersByStartDate
trait访问
builder
属性有什么建议吗

有什么想法吗

<?php

namespace App\Filters\Concerns;

trait FiltersByStartDate
{
    /**
     * Filter a query to include models of a specific date started.
     *
     * @param  array  $startedAt
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function startedAt($startedAt)
    {
        if (isset($startedAt[1])) {
            $this->builder->whereHas('currentEmployment', function ($query) use ($startedAt) {
                $query->whereBetween('started_at', [
                    $startedAt[0],
                    $startedAt[1]
                ]);
            });
        } else {
            $this->builder->whereHas('currentEmployment', function ($query) use ($startedAt) {
                $query->whereDate('started_at', $startedAt[0]);
            });
        }

        return $this->builder;
    }
}

我觉得你用错了特质<代码>特性旨在通过使开发人员能够在不同类层次结构中的几个独立类中自由重用方法集来减少单个继承的某些限制。
一般来说,特性不应使用仅存在于使用该特性的类中的属性。如果trait需要一个属性来工作,那么该属性应该是trait的属性,而不是使用trait的类的属性。创建依赖于using类的属性的trait会增加复杂性和对该类或扩展类的依赖性该trait的原因是我有6个XXXFilters类,它们都使用相同的startedAt方法,所以我想创建一个trait并将其包含在内。
如何从FiltersByStartDate访问builder属性特质?
,你不能。FiltersByStartDate没有
builder
属性。不过,您可以访问
ExampleFilters
的“builder”属性<代码>(新示例过滤器($request))->builder
问题就在这里。我不能硬编码ExampleFilters,因为如果这个特性被6个不同的类使用,那么这就是一个问题。也许你应该向我们展示你正在尝试编写的测试,它要求你从FiltersByStartDate特性访问生成器属性,也许有一种不同的方法,实际上并不需要它。或者,您可以将
builder
属性添加到trait本身,然后您可以在测试中自由地模拟该属性/getter,以设置您需要的任何内容
<?php

namespace Tests\Fixtures;

use App\Filters\Concerns\FiltersByStartDate;
use App\Filters\Filters;

class ExampleFilters extends Filters
{
    use FiltersByStartDate;
}
<?php

namespace App\Filters;

use Illuminate\Http\Request;

abstract class Filters
{
    /**
     * @var \Illuminate\Http\Request
     */
    protected $request;

    /**
     * The Eloquent builder.
     *
     * @var \Illuminate\Database\Eloquent\Builder
     */
    protected $builder;

    /**
     * Registered filters to operate upon
     *
     * @var array
     */
    protected $filters = [];

    /**
     * Create a new class instance.
     *
     * @param \Illuminate\Http\Request $request
     */
    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Apply the filters.
     *
     * @param  \Illuminate\Database\Eloquent\Builder $builder
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function apply($builder)
    {
        $this->builder = $builder;

        foreach ($this->getFilters() as $filter => $value) {
            if (method_exists($this, $filter)) {
                $this->$filter($value);
            }
        }

        return $this->builder;
    }

    /**
     * Fetch all relevant filters from the request.
     *
     * @return array
     */
    public function getFilters()
    {
        return array_filter($this->request->only($this->filters));
    }
}
<?php

namespace Tests\Unit\Filters\Concerns;

use Illuminate\Database\Query\Builder;
use Tests\Fixtures\ExampleFilters;
use Tests\TestCase;

/*
 * @group filters
 */
class FiltersByStartDateTest extends TestCase
{
    /* @var Tests\Fixtures\ExampleFilters */
    protected $subject;

    public function setUp(): void
    {
        $this->subject = app(ExampleFilters::class);
    }

    /** @test */
    public function models_can_be_filtered_by_their_start_date()
    {
        // $this->markTestIncomplete();

        $dateSet = ['2020-01-01 00:00:00'];

        $mock = \Mockery::mock(Builder::class)
            ->shouldReceive('whereHas', \Mockery::any())
            ->shouldReceive('whereDate')
            ->withArgs(['started_at', $dateSet])
            ->once()
            ->andReturn(true)
            ->getMock();

        dd($this->subject->startedAt($dateSet));

        $builderMockFromDate = $this->subject->startedAt($dateSet);

        $this->assertSame($builderMockFromDate, $mock);
    }
}