【问题标题】:Laravel 4.1 Eloquent - use a custom connection with whereHasLaravel 4.1 Eloquent - 使用 whereHas 的自定义连接
【发布时间】:2014-06-20 20:59:29
【问题描述】:

我使用的 MSSQL 有 2 个名为 Seven_ora(用户模型表位于其中)和 sho(字符模型表位于其中)的连接。

一个用户有很多字符,一个字符属于用户。

当我尝试时:

Character::whereHas('User', function($q) { $q->where('gm', 1); });

它似乎使用与字符相同的连接。似乎 whereHas 中的闭包是一个 Query\Builder?我希望 whereHas 使用它所指的任何模型的相应设置连接。

有没有办法在我的 whereHas 闭包上使用不同的连接?

Characters.php(模型)

class Character extends Base {

    /**
     * Connection used by the model
     *
     * @var string
     */
    protected $connection = 'sho';

    /**
     * Table used by the model
     *
     * @var string
     */
    protected $table = 'tblgs_avatar';

    /**
     * Fields fillable by the model
     *
     * @var array
     */
    protected $guarded = array('*');

    /**
     * Checks whether the model uses timestamps
     *
     * @var boolean
     */
    public $timestamps = false;

    /**
     * Decode the job name of the given ID
     *
     * @return  string
     */
    public function getJobName()
    {
        switch( $this->job ) {
            case 0:
                $job = 'Visitor';
                break;
            case 111:
                $job = 'Solider';
                break;
            case 221:
                $job = 'Muse';
                break;
            case 311:
                $job = 'Hawker';
                break;
            case 411:
                $job = 'Dealer';
                break;
            case 121:
                $job =  'Knight';
                break;
            case 122:
                $job = 'Champ';
                break;
            case 221:
                $job = 'Mage';
                break;
            case 222:
                $job = 'Cleric';
                break;
            case 321:
                $job = 'Raider';
                break;
            case 322:
                $job = 'Scout';
                break;
            case 421:
                $job = 'Bourg';
                break;
            case 422:
                $job = 'Artisan';
                break;
            default:
                $job = 'Untitled';
                break;
        }

        return $job;
    }

    /**
     * Rank the characters according to provided details
     *
     * @param   integer     $offset
     * @param   string      $field
     * @return  Character
     */
    public static function byTop($offset = 10, $field = null)
    {
        $characters = new static();

        if ( !is_null($field) ) $characters->orderBy($field, 'desc');

        return $characters->take($offset);
    }

    /**
     * A shortcut to access the name of the character
     *
     * @return  string
     */
    public function getNameAttribute()
    {
        return $this->txtNAME;
    }

    /**
     * A shortcut to access the level of the character
     *
     * @return  int
     */
    public function getLevelAttribute()
    {
        return $this->btLEVEL;
    }

    /**
     * A shortcut to access the job of the character
     *
     * @return  integer
     */
    public function getJobAttribute()
    {
        return $this->intJOB;
    }

    /*
    |--------------------------------------------------------------------------
    | ORM
    |--------------------------------------------------------------------------
    */

    /**
     * ORM with the [User] table
     *
     * @return  User 
     */
    public function user()
    {
        return $this->belongsTo('User', 'Account', 'txtACCOUNT');
        //$user = User::where('Account', $this->txtACCOUNT)->first();

        //return $user;
    }
}

User.php(模型)

use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;

class User extends Base implements UserInterface, RemindableInterface {

    /**
     * Connection used by the model
     *
     * @var string
     */
    protected $connection = 'seven_ora';

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'userinfo';

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = array('MD5PassWord', 'password');

    /**
     * Fields guarded by the model
     *
     * @var array
     */
    protected $guarded = array();

    /**
     * Fields fillable by the model
     *
     * @var array
     */
    protected $fillable = array(
        'Account',
        'Email',
        'MD5PassWord',
        'FirstName',
        'LastName',
        'MotherLName'
    );

    /**
     * Checks whether the model uses timestamps
     *
     * @var boolean
     */
    public $timestamps = false;

    /**
     * Get the unique identifier for the user.
     *
     * @return mixed
     */
    public function getAuthIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Get the password for the user.
     *
     * @return string
     */
    public function getAuthPassword()
    {
        return $this->MD5PassWord;
    }

    /**
     * Get the token value for the "remember me" session.
     *
     * @return string
     */
    public function getRememberToken()
    {
        return $this->remember_token;
    }

    /**
     * Set the token value for the "remember me" session.
     *
     * @param  string  $value
     * @return void
     */
    public function setRememberToken($value)
    {
        $this->remember_token = $value;
    }

    /**
     * Get the column name for the "remember me" token.
     *
     * @return string
     */
    public function getRememberTokenName()
    {
        return 'remember_token';
    }

    /**
     * Get the e-mail address where password reminders are sent.
     *
     * @return string
     */
    public function getReminderEmail()
    {
        return $this->email;
    }

    /**
     * Validate input
     *
     * @param   array       $input
     * @param   integer     $id
     * @return  Validator
     */
    public function validate(array $input = array(), $id = null)
    {
        // Rules
        $username   = 'required|alpha_num|between:4,32|unique:userinfo,Account';
        $password   = 'required|between:4,48';
        $email      = 'required|email|unique:userinfo,Email';
        $mname      = 'required';

        // Unique rules
        if(!is_null($id)) {
            $unique      = ',' . $id;
            $username   .= $unique;
            $email      .= $unique;
        }

        $rules = array(
            'username'  =>  $username,
            'password'  =>  $password,
            'email'     =>  $email,
            'mname'     =>  $mname
        );

        $messages = array('mname.required' => "The security question field is required");

        Config::set('database.default', 'seven_ora'); // Set config
        return Validator::make($input, $rules, $messages);
    }

    /**
     * Change password of the user
     *
     * @param   string  $old
     * @param   string  $new
     * @return  boolean
     */
    public function changePassword($old, $new)
    {
        if(Hash::check($old, $this->MD5PassWord)) {
            $this->MD5PassWord = Hash::make($new);

            if($this->save()) return true;
        }

        return false;
    }

    /**
     * Checks if the user is a GM
     *
     * @return  boolean
     */
    public function isGM()
    {
        return ( $this->Right > 1 )
            ? true
            : false;
    }

    public function addVP($points)
    {
        $vp = $this->votePoint;
        $count = $vp->count;
        $vp->count = $count + $points;
        $vp->save();
    }

    /**
     * Since our server files does not use the typical
     * field names, this sets our username to whatever is being used
     *
     * @return  void
     */
    public function getUsernameAttribute()
    {
        return $this->Account;
    }

    /**
     * Since our server files does not use the typical
     * field names, this sets our password to whatever is being used
     *
     * @return  void
     */
    public function getPasswordAttribute()
    {
        return $this->MD5PassWord;
    }

    /**
     * A shortcut to the user's vote point count
     *
     * @return  void
     */
    public function getVpAttribute()
    {
        return $this->votePoint->count;
    }

    public function getDpAttribute()
    {
        return $this->donationPoint->count;
    }


    /*
    |--------------------------------------------------------------------------
    | ORM
    |--------------------------------------------------------------------------
    */

    /**
     * ORM with the Character model
     *
     * @return  Character
     */
    public function characters()
    {
        return $this->hasMany('Character', 'txtACCOUNT', 'Account');
        //$characters = Character::where('txtACCOUNT', $this->username)->get();

        //return $characters;
    }

    /**
     * ORM with the VotePoint model
     *
     * @return  VotePoint
     */
    public function votePoint()
    {
        return $this->hasOne('VotePoint');
    }

    /**
     * ROWM with the DonationPointmodel
     *
     * @return  DonationPoint
     */
    public function donationPoint()
    {
        return $this->hasOne('DonationPoint');
    }

    /**
     * ORM with the News model
     *
     * @return  News
     */
    public function news()
    {
        return $this->hasMany('News');
    }

    /**
     * ORM with the Slide model
     *
     * @return  Slide
     */
    public function slides()
    {
        return $this->hasMany('Slide');
    }

    /**
     * ORM with the VoteLog model
     *
     * @return  VoteLog
     */
    public function logs()
    {
        return $this->hasMany('VoteLog');
    }

}

【问题讨论】:

    标签: laravel eloquent


    【解决方案1】:

    将数据库名称添加到 User 类中的 $table 值中。所以假设seven_ora也是DB的名字:

    protected $table = 'seven_ora.userinfo';
    

    【讨论】:

    • 这确实是一种解决方案,但很可能它应该可以工作而不必这样做......
    • ^这个解决方案有缺点吗?
    【解决方案2】:

    您也可以通过构造函数中的配置变量添加它以适应不同的环境

      public function __construct($attributes = array())  {
            parent::__construct($attributes); 
    
            $this->table = Config::get('database.connections.connection.database').'.model_table_name';
      }
    

    【讨论】:

      【解决方案3】:

      这可能会有所帮助:

      1. 当您使用 Character::whereHas('User',...) 时,查询生成器会创建单个数据库查询,因此只能使用 一个连接(及其凭据)。查询类似于:
        • SELECT * FROM characters WHERE (SELECT COUNT(*) FROM users WHERE characters.user_id = user.id AND gm = 1) >= 1; [使用 Character 模型上定义的连接(如您所见)]
      2. 当您单独引用关系或使用像 Character::with('user') 这样的急切加载时,会执行两个单独的数据库查询,每个都使用其各自的连接(和连接凭据):
        • SELECT * FROM characters; [使用在 Character 模型上定义的连接]
        • SELECT * FROM users WHERE id IN (1, 2, 3, …); [使用在用户模型上定义的连接]

      按照解决方案的建议,将数据库名称添加到表名称之前,仅当字符模型连接具有访问其他数据库的权限时才有效,因为您仍在使用字符模型连接。

      【讨论】:

        猜你喜欢
        • 2014-01-11
        • 2021-08-23
        • 1970-01-01
        • 2019-12-28
        • 2017-06-09
        • 2020-09-16
        • 2020-12-23
        • 2018-06-19
        • 2014-09-30
        相关资源
        最近更新 更多