在Laravel模型上确定特征内的查询

时间:2016-12-09 14:18:50

标签: php laravel oop model traits

一点背景......

我的应用程序中有两个可以定位的模型'。我可以很容易地在存储库中编写一个查询以返回我需要的内容,但是,我确信在Laravel Scopes和Traits等的帮助下可以做得更好(我可能错了)。

所以,我提出了以下解决方案:

示例摘要模型

abstract class AbstractModel extends Model implements SomeOtherStuff
    
{
    public function scopeNearby(Builder $query)
    
    {
        return $query->selectRaw('
                (
                    6373000 * acos(
                        cos( radians( ' . $this->location->latitude . ' ) )
    
                        * cos( radians( X(' . $this->location->table . '.location) ) )
    
                        * cos( radians( Y(' . $this->location->table . '.location) ) - radians( ' . $this->location->longitude . ' ) )
    
                        + sin( radians( ' . $this->location->latitude . ' ) )
                        * sin( radians( X(' . $this->location->table . '.location) ) )
                    )
                ) AS distance
           ')
            // I wanted to use ->with('location') below instead of ->join() but it didn’t work
            ->join($this->location->table, $this->location->primaryKey, '=', $this->primaryKey);
    }

    // All other Abstract stuff here
}

示例用户模型

class User extends AbstractModel implements SomeOtherStuff
{
    
    /**
     * Get the location of the user.
    
     */
    public function location()
    {
    
        return $this->hasOne(‘App\Models\User\Location', 'user_id');
    
    }

    // All other model stuff here
}

示例用户控制器

class UserController extends AbstractController
    
{
    /**
     * Return the nearby users.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    
    public function nearby()
    {
        $users = $this->shield->user()->nearby()->toSql();

        // Print out the query to ensure it is structured correctly
        echo $users;
    
    }
}

我的问题

上述解决方案有效,但是,这是非常错误的(在我看来)! nearby()范围仅适用于“可定位”的模型。当然,我认为最好的解决方案是实现这样的Trait:

trait Locatable
{
    /**
        
     * Scope a query to include the distance from the current model.
        
     *
     * @param   \Illuminate\Database\Eloquent\Builder $query
     * @return  \Illuminate\Database\Eloquent\Builder
        
     */
        
    public function scopeNearby(Builder $query)
        
    {
        // Same as above implementation
    
    }
    
}

这个问题是我需要的模型的属性是protected因此无法通过Trait访问...

我的问题

假设上述内容有意义,请参阅下面的问题:

  1. 是否有更好的方法来实现所需的功能?如果有,请有人指出我正确的方向吗?
  2. 这是较低的优先级,但为什么->with('location')不起作用?我用错了吗?我希望它为查询添加一个内连接,但它没有......

1 个答案:

答案 0 :(得分:1)

这是实际应该如何做的

int clientWidth = ...
int clientHeight = table.getItemHeight * numberOfItems;
if( table.getLinesVisible() && numberOfItems > 0 ) {
  clientHeight += table.getGridLineWidth() * ( numberOfItems - 1 );
}
Rectangle bounds = table.computeTrim( 0, 0, clientWidth, clientHeight );

GridData gridData = new GridData( SWT.DEFAULT, clientHeight );

回答你的问题。

  1. 以上是更好的方法。您应该使用trait Locatable { /** * Scope a query to include the distance from the current model. * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopeNearby($query) { if(!$this->location) { return $query; } return $query->whereHas('location', function($query) { $query->selectRaw(' //Your query for distance (Use the getTable() function wherever required...) ) AS distance ') ->having('distance', '<', 25); } ); } } 进行关系查询。

  2. 由于没有连接表,查询将无法工作,它只执行WHERE EXISTS()查询,然后将其作为与返回模型的关系添加。要了解更多......你能做的就是....

  3. (在控制器中的任何地方写下这个......只是为了测试目的)

    whereHas()

    如果您遇到任何问题,请告诉我...... :)