使用Laravel的Fluent插入IGNORE

Nyx*_*nyx 10 php mysql laravel

是否有一个快速的方法来修改生成的SQL查询Laravel的流利有一个INSERT IGNORE,而不是通常的INSERT

我正在尝试插入一个包含50个元素的数组.手动写出整个查询会使代码膨胀并使其更容易受到人为错误的影响.

mal*_*hal 13

在你的模型中试试这个魔法:

public static function insertIgnore($array){
    $a = new static();
    if($a->timestamps){
        $now = \Carbon\Carbon::now();
        $array['created_at'] = $now;
        $array['updated_at'] = $now;
    }
    DB::insert('INSERT IGNORE INTO '.$a->table.' ('.implode(',',array_keys($array)).
        ') values (?'.str_repeat(',?',count($array) - 1).')',array_values($array));
}
Run Code Online (Sandbox Code Playgroud)

使用这样:

Shop::insertIgnore(array('name' => 'myshop'));
Run Code Online (Sandbox Code Playgroud)

如果'name'属性是唯一键,这是防止first-orCrate在多用户环境中可能发生的约束违规的好方法.

  • 应该注意的是,这样做可能是正确的方法,但是您需要确保在运行查询之前清除所有用户生成的变量,因为这是原始 SQL! (3认同)

J. *_*uni 5

我无法像拉斯蒂斯拉夫的回答中建议的那样修补猴子。

这对我有用:

  1. compileInsert自定义查询语法类中的重写方法,该类扩展了框架的MySqlGrammar类。

  2. 通过setQueryGrammar从数据库连接实例中调用方法来使用此自定义语法类的实例。

因此,类代码如下所示:

<?php

namespace My\Namespace;

use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\Grammars\MySqlGrammar;

/**
 * Changes "INSERT" to "INSERT IGNORE"
 */
class CustomMySqlGrammar extends MySqlGrammar
{
    /**
     * Compile an insert statement into SQL.
     *
     * @param  \Illuminate\Database\Query\Builder  $query
     * @param  array  $values
     * @return string
     */
    public function compileInsert(Builder $query, array $values)
    {
        // Essentially we will force every insert to be treated as a batch insert which
        // simply makes creating the SQL easier for us since we can utilize the same
        // basic routine regardless of an amount of records given to us to insert.
        $table = $this->wrapTable($query->from);

        if (! is_array(reset($values))) {
            $values = [$values];
        }

        $columns = $this->columnize(array_keys(reset($values)));

        // We need to build a list of parameter place-holders of values that are bound
        // to the query. Each insert should have the exact same amount of parameter
        // bindings so we will loop through the record and parameterize them all.
        $parameters = collect($values)->map(function ($record) {
            return '('.$this->parameterize($record).')';
        })->implode(', ');

        return "insert ignore into $table ($columns) values $parameters";
    }
}
Run Code Online (Sandbox Code Playgroud)

compileInsert从框架的类复制了方法,然后在方法内部,我仅更改insertinsert ignore。其他所有内容均保持不变。

然后,在特定的代码点中,在需要“插入忽略”的应用程序中(预定任务),我只需完成以下操作:

<?php

use DB;
use My\Namespace\CustomMySqlGrammar;

class SomeClass
{
    public function someMethod()
    {
        // Changes "INSERT" to "INSERT IGNORE"
        DB::connection()->setQueryGrammar(new CustomMySqlGrammar());

        // et cetera... for example:
        ModelClass::insert($data);
    }
}
Run Code Online (Sandbox Code Playgroud)


hak*_*kre 1

对于这项工作,您需要创建一个新的语法,其中包含正确的字符串:

语法.php (1)

语法是连接的公共属性,DB或者在本例中是Database存储连接的公共属性。这并不是很直接,但从属性的可见性来看,您应该能够将特殊语法注入到数据库层中。

我还建议您在项目中提出这个问题,他们可能有更好的想法,如何使此类案例更加灵活。


(1)这是以前的答案参考日期。如果你今天看到这个,你需要采用你使用的 Laravel 版本,例如Grammar.php for 4.0,这些类已移至laravel/framework.