简体   繁体   中英

Translating Raw sql query to laravel eloquent query

I have a raw query which works fine, but I can't translate it to laravel eloquent...

Here are my tables :

users table

Schema::create('users', function(Blueprint $table)
    {
        $table->increments('id');
        $table->string('username', 30)->unique();
        $table->string('email')->unique();
        $table->string('password', 60);
        $table->integer('role_id')->unsigned();
        $table->boolean('seen')->default(false);
        $table->boolean('valid')->default(false);
        $table->boolean('confirmed')->default(false);
        $table->string('confirmation_code')->nullable();
        $table->timestamps();
        $table->rememberToken();
    });

clients table

Schema::create('clients', function(Blueprint $table)
    {
        $table->increments('id');
        $table->integer('id_marchand')->unsigned()->index();
        $table->foreign('id_marchand')->references('id')->on('users')->onDelete('cascade')->onUpdate('restrict');
        $table->integer('id_client')->unsigned()->index();
        $table->foreign('id_client')->references('id')->on('users')->onDelete('cascade')->onUpdate('restrict');
        $table->timestamps();

    });

employes table

Schema::create('employes', function(Blueprint $table)
    {
        $table->increments('id');
        $table->integer('id_marchand')->unsigned()->index();
        $table->foreign('id_marchand')->references('id')->on('users')->onDelete('cascade')->onUpdate('restrict');
        $table->integer('id_employe')->unsigned()->index();
        $table->foreign('id_employe')->references('id')->on('users')->onDelete('cascade')->onUpdate('restrict');
        $table->timestamps();

    });

User Model

<?php namespace App\Models;

/**
 * One to Many relation
 *
 * @return Illuminate\Database\Eloquent\Relations\hasMany
 */
public function employes()
{
    return $this->hasMany('App\Models\Employe', 'id_marchand');
}

/**
 * One to Many relation
 *
 * @return Illuminate\Database\Eloquent\Relations\hasMany
 */
public function clients()
{
    return $this->hasMany('App\Models\Client', 'id_marchand');
}

Client Model

<?php namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Client extends Model
{
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'clients';

    /**
     * One to Many relation
     *
     * @return Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user() 
    {
        return $this->belongsTo('App\Models\User');
    }
}

Employe Model

<?php namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Employe extends Model
{
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'employes';

    /**
     * One to Many relation
     *
     * @return Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user() 
    {
        return $this->belongsTo('App\Models\User');
    }
}

The raw query I'm trying to translate :

SELECT users.* 
FROM clients, users 
WHERE clients.id_marchand = 8 
AND users.id = clients.id_client 
UNION 
SELECT users.* 
FROM employes, users 
WHERE employes.id_marchand = 8 
AND users.id = employes.id_employe 
UNION 
SELECT users.*
FROM users
WHERE users.id = 8
ORDER BY `seen` ASC, `created_at` DESC 
LIMIT 25 OFFSET 0

My problems are:

  1. If I try to do it with a raw query, via DB::raw() , it returns an array, and I can't paginate or sort results then.
  2. I can't find a way to do a 'select' from several tables in Eloquent
  3. I don't know how to extract datas from the array and get a Collection
  4. I am still not sure if I'm doing it right or not.

So is there a way or an other to make that work ?


EDIT:

To be clear, what I'm trying to get is:

A Collection of Users , containing:

  • Users who are 'clients' of User 8
  • Users who are 'employes' of User 8
  • User 8.

on which I can apply ->oldest('seen')->latest()->paginate($n) or something equivalent.

It looks like your employee model is setup correctly which should make this fairly simple...

I think it's easier to think about what you are trying to do and how Eloquent can help you do that than simply trying to convert a query to use the query builder.

$id = 8;
$users = App\User::whereHas('clients', function($q) use ($id) {
    $q->where('id_marchand', $id);
})->orWhereHas('employes', function($q) use ($id) {
    $q->where('id_marchand', $id);
})->orWhere('id', $id)
->orderBy('seen')
->oldest()
->get();

This will return a collection of User models. If you'd like to paginate, simply swap out get() with paginate($numRecords) where $numRecords is the number of records you want per page.

Then with that collection of models, you can use a foreach loop to output each of the user's data....

foreach ($users as $user) {
    echo 'email: ' . $user->email;
}

Edit: I was wrong, I didn't look closely enough at the models. So in your queries, you are joining the clients and employes tables by the columns id_client and id_employe respectively. So if you modify your User model and change id_marchand to id_employe for the employes function and id_client for the clients function, this code should work (or at least it does for me).

Just for clarification, the code above generates the following query so you can see the results for yourself before making any changes...

SELECT 
    * 
FROM
    `users` 
WHERE EXISTS 
    (SELECT 
    * 
    FROM
    `clients` 
    WHERE `clients`.`id_client` = `users`.`id` 
    AND `id_marchand` = '8') 
    OR EXISTS 
    (SELECT 
    * 
    FROM
    `employes` 
    WHERE `employes`.`id_employe` = `users`.`id` 
    AND `id_marchand` = '8') 
    OR `id` = '8' 
ORDER BY `seen` ASC,
    `created_at` ASC 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM