2012-09-27 12 views
6

का उपयोग करते हुए INSERT IGNORE Laravel's Fluent द्वारा उत्पन्न SQL क्वेरी को संशोधित करने का एक त्वरित तरीका है सामान्य INSERT के बजाय INSERT IGNORE?लार्वेल के फ्लुएंट

मैं 50 तत्वों के साथ एक सरणी डालने की कोशिश कर रहा हूं और पूरी क्वेरी लिखकर मैन्युअल रूप से कोड को उड़ा दूंगा और इसे मानवीय त्रुटियों के लिए अधिक संवेदनशील बना दूंगा।

+0

सरणी है एक प्रमुख => मूल्य जोड़ी जो कॉलम => मान सेटअप के अनुरूप है? यदि ऐसा है, तो इसे उत्पन्न करने के लिए बस एक लूप लिखें। – wesside

+0

हां यह करता है! :) क्या आप SQL क्वेरी कथन उत्पन्न करने के लिए लूप लिखना चाहते हैं? – Nyxynyx

+0

धन्यवाद, मुझे नहीं पता था कि अन्य डेटाबेस पुस्तकालयों का उपयोग किया जा सकता है! मुझे इसे बदलने के बारे में कैसे जाना चाहिए? – Nyxynyx

उत्तर

0

काम आप एक नया व्याकरण वहाँ में सही स्ट्रिंग होगा बनाने की जरूरत के लिए:

grammar.php(1)

व्याकरण DB की एक सार्वजनिक संपत्ति है या इस मामले में Database संग्रहीत कनेक्शन। यह वास्तव में सीधे आगे नहीं है, लेकिन गुणों की दृश्यता से आप डेटाबेस परत में अपने विशेष व्याकरण को इंजेक्ट करने में सक्षम होना चाहिए।

मैं यह भी सुझाव देता हूं कि आप इस परियोजना को इस मुद्दे के साथ लाएं, शायद उन्हें बेहतर विचार मिलेगा कि इन मामलों के मामलों के लिए इसे और अधिक लचीला कैसे बनाया जाए।


(1) यह एक पूर्व, उत्तर संदर्भ तिथि करने के लिए किया गया था। यदि आप आज इसे देखते हैं, तो आपको अपने द्वारा उपयोग किए जाने वाले लार्वा संस्करण को अपनाने की आवश्यकता है, उदा। Grammar.php for 4.0, ये कक्षा laravel/framework में स्थानांतरित हो गई हैं।

+1

वह लिंक अब 404 देता है। – wiggles

+0

@ विगल्स: ठीक करने में आसान। हालांकि ओपी ने ऐसा रिपोर्ट करने के लिए समय नहीं लिया हो सकता है। – hakre

-13
$your_array = array('column' => 'value', 'second_column' => 'value'); 

DB::table('your_table')->insert($your_array); 

ध्यान रखें, मुझे नहीं पता कि आपका डेटा कहां से आ रहा है, लेकिन आपको हमेशा इसे स्वच्छ करना चाहिए। यदि आपके पास एक से अधिक रिकॉर्ड हैं, तो बस एक लूप में फिर से चालू करें।

जहाँ तक INSERT IGNORE के रूप में, धाराप्रवाह पुस्तकालय में INSERT विधि को खोजने के लिए एक नई विधि डालने के रूप में ठीक उसी तरह से insert_ignore कहा जाता है बनाने के लिए और सिर्फ IGNORE साथ संशोधित।

+0

क्या आपकी क्वेरी 'इंसर्ट इग्नोर' करती है? – Nyxynyx

+0

आपको इसकी आवश्यकता क्यों है, आपने कभी भी – wesside

+3

निर्दिष्ट नहीं किया है, मैंने निर्दिष्ट किया है कि प्रश्न में ... – Nyxynyx

9

अपने मॉडल में इस जादू का प्रयास करें,:

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)); 
} 

उपयोग इस तरह:

Shop::insertIgnore(array('name' => 'myshop')); 

इस बाधा उल्लंघन है कि एक बहु उपयोगकर्ता वातावरण में firstOrCreate साथ भी हो सकती को रोकने के लिए एक शानदार तरीका है , अगर वह 'नाम' संपत्ति एक अनूठी कुंजी थी।

+0

यह ध्यान दिया जाना चाहिए कि ऐसा करने का शायद यह सही तरीका है, लेकिन आपको यह सुनिश्चित करने की आवश्यकता होगी कि आप क्वेरी चलाने से पहले सभी उपयोगकर्ता जेनरेट किए गए चर साफ़ करें, क्योंकि यह कच्चा एसक्यूएल है! –

1

सुनिश्चित नहीं हैं कि अगर किसी के लिए भी उपयोगी है, लेकिन हाल ही में मैं Laravel से 5 hakre का दृष्टिकोण अपनाया है:

  1. Builder.php में:

    आप 3 फ़ाइलें निम्न काम करने पर ध्यान न दें अपने सम्मिलित करने के लिए बदलना होगा (विक्रेता/laravel/रूपरेखा/src/उजागर/डेटाबेस/जानकारी/Builder.php) आप, समारोह डालने clon करने के लिए व्याकरण कॉल समारोह में insertIgnore के नाम में परिवर्तन और बदलाव के साथ: $sql = $this->grammar->compileInsertIgnore($this, $values);)

  2. में ग्राम mar.php (विक्रेता/लार्वेल/ढांचे/src/रोशनी/डेटाबेस/क्वेरी/व्याकरण/व्याकरण।php) आप compileInsert समारोह क्लोन और compileInsertIgnore, जहाँ आप के लिए वापसी को बदलने के लिए इसका नाम बदलना करने के लिए है: return "insert ignore into $table ($columns) values $parameters";

  3. Connection.php (में विक्रेता/laravel/रूपरेखा/src/उजागर/डेटाबेस/Connection.php) आपके पास बस समारोह डालने क्लोन और insertIgnore

अब आप से किया जाना चाहिए करने के लिए यह नाम बदलने के लिए, कनेक्शन समारोह insertIgnore पहचान करने में सक्षम है, बिल्डर को दूर करने के व्याकरण और व्याकरण में 'उपेक्षा' भी शामिल है यह इंगित करने के लिए सक्षम है बयान। कृपया यह MySQL के लिए अच्छी तरह से काम नहीं करता है, हो सकता है कि यह अन्य डेटाबेस के लिए आसान न हो।

0

अपने मॉडल

<?php 

namespace App; 

use Illuminate\Auth\Authenticatable; 
use Illuminate\Database\Eloquent\Model; 
use Illuminate\Auth\Passwords\CanResetPassword; 
use Illuminate\Foundation\Auth\Access\Authorizable; 
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 

class User extends Model implements AuthenticatableContract, 
            AuthorizableContract, 
            CanResetPasswordContract 
{ 
    use Authenticatable, Authorizable, CanResetPassword; 

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

    /** 
    * The attributes that are mass assignable. 
    * 
    * @var array 
    */ 
    protected $fillable = ['name', 'email', 'password']; 

    /** 
    * The attributes excluded from the model's JSON form. 
    * 
    * @var array 
    */ 
    protected $hidden = ['password', 'remember_token']; 


    public static function insertIgnore(array $attributes = []) 
    { 
     $model = new static($attributes); 

     if ($model->usesTimestamps()) { 
      $model->updateTimestamps(); 
     } 

     $attributes = $model->getAttributes(); 

     $query = $model->newBaseQueryBuilder(); 
     $processor = $query->getProcessor(); 
     $grammar = $query->getGrammar(); 

     $table = $grammar->wrapTable($model->getTable()); 
     $keyName = $model->getKeyName(); 
     $columns = $grammar->columnize(array_keys($attributes)); 
     $values = $grammar->parameterize($attributes); 

     $sql = "insert ignore into {$table} ({$columns}) values ({$values})"; 

     $id = $processor->processInsertGetId($query, $sql, array_values($attributes)); 

     $model->setAttribute($keyName, $id); 

     return $model; 
    } 
} 

के अनुसरण की विधि insertIgnore जोड़ें आप उपयोग कर सकते हैं:

App\User::insertIgnore([ 
    'name' => 'Marco Pedraza', 
    'email' => '[email protected]' 
]); 

अगले क्वेरी यह निष्पादित किया जाएगा:

insert ignore into `users` (`name`, `email`, `updated_at`, `created_at`) values (?, ?, ?, ?) 

इस विधि स्वचालित रूप से जोड़/यदि आपने सक्षम या अक्षम किया है तो वाष्पकालीन टाइमस्टैम्प को हटा दें।

1

मैं रास्तस्लाव के उत्तर में सुझाए गए बंदर पैच नहीं कर सका।

यह वही मेरे लिए काम किया है:

  1. अवहेलना एक कस्टम क्वेरी व्याकरण वर्ग है, जो ढांचे के MySqlGrammar वर्ग फैली में compileInsert विधि।

  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"; 
    } 
} 

मैं ढांचे की क्लास से 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); 
    } 
} 
संबंधित मुद्दे