2013-07-03 10 views
29

Ich versuche Einheiten Massen Zuordnung Eloquent-Funktion zu erstellen ...Leere Zeichenfolge statt NULL-Werte Eloquent

$new = new Contact(Input::all()); 
$new->save(); 

Das Problem ist, dass diese Art und Weise, die jedes Feld mit einem leeren String ausgefüllt statt null Werte wie ich es erwartet habe.

Ich entwickle zur Zeit das System und noch einige Tabelle columns're nicht definiert, deshalb diese Methode verwenden, um zu verhindern jedes neues Feld $fillable Array hinzufügen und zu einem new Contact(array(...)); ...

Auch ich ve rund 20 Felder in dieser Tabelle, so Es wäre ein bisschen hässlich sein, einen Array zu haben wie

$new = new Contact(array(
    'salutation' => Input::get('salutation'), 
    'first_name' => Input::get('first_name'), 
    'last_name' => Input::get('last_name'), 
    'company_id' => Input::get('company_id'), 
    'city' => ... 
    ... 
)); 

Irgendwelche Tipps, wie diese oder beheben zu tun?

Update Inzwischen habe ich dies aussortiert die Array_filter im App::before() Filter tun.

Update Im Filter war ein bisschen Durcheinander. Ich am Ende mache:

public static function allEmptyIdsToNull() 
{ 
    $input = Input::all(); 

    $result = preg_grep_keys ('/_id$/' , $input); 

    $nulledResults = array_map(function($item) { 
     if (empty($item)) 
      return null; 

     return $item; 
    }, $result); 

    return array_merge($input, $nulledResults); 
} 

Und in meiner functions.php.

Jetzt nur noch mit Feldern arbeiten, die mit "_id" enden. Dies ist mein größtes Problem, als ob eine Beziehung nicht NULL ist, die Datenbank wird einen Fehler werfen, da der Fremdschlüssel "" nicht gefunden werden kann.

Funktioniert perfekt. Jeglicher Kommentar?

+0

Setzen Sie das in eine Zeile ... 'Kontakt :: create (Input :: all())' ftw. –

+0

Erhalte ich auf diese Weise nicht die leeren Werte? Ich denke, es macht das selbe Zeug wie '$ new = new Contact (Input :: all());' –

Antwort

10

Verwenden Sie das Ereignis 'Speichern' des Modells, um nach leeren Modellen zu suchen, und setzen Sie sie explizit auf null. "Projekt" ist der Name meines Modells in diesem Beispiel. Setzen Sie diese Funktion in eine Hilfsfunktion und verbinden Sie sie mit allen Ihren Modellen.

Project::saving(function($model) { 
    foreach ($model->toArray() as $name => $value) { 
     if (empty($value)) { 
      $model->{$name} = null; 
     } 
    } 

    return true; 
}); 

Update für Laravel 5 (April 11 2016)

I auch eine Http-Middleware zur Reinigung der Eingangsdaten von der HTTP-Anforderung am Ende der Erstellung zusätzlich zu den Daten, Reinigung, bevor es gesendet wird, die Datenbank.

class InputCleanup 
{ 
    /** 
    * Handle an incoming request. 
    * 
    * @param \Illuminate\Http\Request $request 
    * @param \Closure $next 
    * @return mixed 
    */ 
    public function handle($request, Closure $next) 
    { 
     $input = $request->input(); 

     array_walk_recursive($input, function(&$value) { 

      if (is_string($value)) { 
       $value = StringHelper::trimNull($value); 
      } 
     }); 

     $request->replace($input); 

     return $next($request); 
    } 
} 
+3

Nach der Verwendung dieses Codes für eine Weile .. sei vorsichtig damit. Es hat einen interessanten Nebeneffekt. Dadurch werden die Werte bei jedem Update auf null gesetzt. Dies könnte unbeabsichtigte Konsequenzen haben. Es wäre wahrscheinlich gut zu überprüfen, ob sich der Wert von seinem ursprünglichen Zustand geändert hat. – craigtadlock

+0

Ich erweiterte auf Ihre Methode hier http://www.laravel-tricks.com/tricks/setting-null-values-only-on-certain-fields – Mei

+0

@craigtadlock jetzt, dass wir Laravel 5.1 haben, habe ich nicht gesehen Nebeneffekt, den Sie erwähnt haben. Wenn Sie diesen Kommentar hinzufügen, um andere darüber zu informieren, besteht kein Problem mehr. – karmendra

-1

Stellen Sie in Ihrem Eloquent-Modell sicher, dass $guarded leer ist. Sie müssen $fillable nicht festlegen.

Die Massenzuweisung ist normalerweise keine gute Idee, aber in einigen Szenarien ist es in Ordnung, zu bestimmen, wann.

Siehe: http://laravel.com/docs/eloquent#mass-assignment

+0

Ich habe keine Probleme bei der Massenzuweisung, ich habe nur Probleme, da jedes leere Formularfeld seinen Wert als '' " "' anstelle von 'NULL' –

+0

Existieren diese Felder beim POST? Wenn ja, sind sie leer? Wie sehen Ihre Migrations- und/oder Standardwerte für die Tabellenspalten aus? –

+0

Die Felder existieren, wenn ich POST, deshalb bekomme ich leere Werte anstelle von 'NULL'. Das Hauptproblem ist unter –

1

Für eine Formulareingabe, es ist normal, und logisches leere Werte zu haben, anstatt Nullwerte.

Wenn Sie wirklich denken, der beste Weg, dies zu tun, ist, um die Eingabe direkt in Ihre Datenbank zu setzen, als die Lösung, um leere Werte null zu machen wäre so etwas.

$input = Input::all(); 
foreach ($input as &$value) { 
    if (empty($value) { $value = null; } 
} 
$new = new Contact(Input::all()); 
$new->save(); 

Persönlich stimme ich nicht mit dieser Art von Lösungen, aber es für einige Leute zu arbeiten.

+0

Was würdest du tun? –

+0

Speichern Sie leere Zeichenfolge direkt in Ihrer Datenbank. Schließlich glaube ich nicht, dass Sie Nullwerte rendern werden ... –

+1

Ich akzeptiere auch keine leeren Werte, da ich an ImnoDB, Beziehungen und Einschränkungen arbeite, also wenn ein FK nicht 'NULL' ist, ist es tris zu finden die fremde ID, selbst wenn es "" "ist, die offensichtlich nicht in der Fremdtabelle existiert und einen MySQL-Fehler wie" Kann eine untergeordnete Zeile hinzufügen oder aktualisieren: eine Fremdschlüsseleinschränkung fehlschlägt " –

19

Laravel 4

Wenn es notwendig ist, dass Sie einen leeren String in einem Array entfernen könnte durch Filterung.

$input = array_filter(Input::all(), 'strlen'); 

Dann, wenn Sie so etwas wie array('a' => 'a', 'b' => '') Sie erhalten: array('a' => 'a').

Soweit ich weiß, wird Laravel Eloquent ORM es wie NULL behandelt, wenn ein Feld nicht im Array für die Massenbelegung angegeben ist.


Laravel 5

$input = array_filter(Request::all(), 'strlen'); 

oder

// If you inject the request. 
$input = array_filter($request->all(), 'strlen'); 
+0

Gute Idee ... Ich habe überlegt, die Eingabe zu wiederholen und wollte eine sauberere Lösung. –

+0

'Array_filter' an sich sollte gut genug sein. Keine Notwendigkeit, "strlen" als Callback-Funktion zu liefern. –

+0

Ich mag diesen Weg ... Und jetzt ... Was den "richtigen" Weg angeht, sehe ich überall ... Gibt es keinen anderen Weg, als die Felder einzeln zuzuordnen? Wie gesagt ... Es kann mühsam sein, mehr als 20 Felder im create Array zu setzen –

57

Ich habe für die Antwort auf diese Frage mich sah, und das nächste, was ich mit oben kommen kann verwendet Mutatoren (http://laravel.com/docs/eloquent#accessors-and-mutators). (! Magie)

Das gleiche Problem eine durch Zugabe von Mutator-Methode für das Fremdschlüsselfeld in dem Modell gelöst wurde:

public function setHeaderImageIdAttribute($value) 
{ 
    $this->attributes['header_image_id'] = $value ?: null; 
} 

Für eine Tabelle mit viel Fremdschlüssel kann diese Art von sperrig , aber es ist die "eingebaute" Methode, die ich für den Umgang damit gefunden habe. Der Vorteil ist, dass es Magie ist, also musst du nur die Methode erstellen und du bist gut zu gehen.

+10

Dies ist die richtige Laravel-Lösung. Dies ist der Grund, warum Accessors und Mutators in Eloquent existieren. Es gibt auch mehr Kontrolle darüber, was genau auf "null" eingestellt ist, anstatt auf eine Decke, die alles auf null setzt, wie es die akzeptierte Antwort tut. –

+5

+1 für diese Antwort. Dies ist definitiv der richtige Weg, um Null-Schlüssel zu vergeben. Gibt Ihnen viel mehr Kontrolle über einzelne Spalten. Dies wäre auch vorteilhaft, wenn Sie den Standardwert einer Spalte oder etwas Ähnliches ändern müssten. –

+1

Große Antwort auf etwas, das mich für immer brauchte, um herauszufinden. Eine Anmerkung, die helfen könnte: Denken Sie daran, den Mutator mit der ID zu benennen - dh er mutiert nicht die Beziehungsfunktion, sondern das db-Feld. Ich habe den Fehler gemacht, die Funktion 'setHeaderImageAttribute' nach der Funktion anstatt 'setHeaderImageIdAttribute' im obigen Beispiel aufzurufen. Laravel vermisste den Mutator. Offensichtlich im Nachhinein .. aber es dauerte ewig, bis man es fand. – Watercayman

11

Wahrscheinlich mehr generische Lösung:

class EloquentBaseModel extends Eloquent { 

    public static function boot() 
    { 
     parent::boot(); 

     static::saving(function($model) 
     { 
      if (count($model->forcedNullFields) > 0) { 
       foreach ($model->toArray() as $fieldName => $fieldValue) { 
        if (empty($fieldValue) && in_array($fieldName,$model->forcedNullFields)) { 
         $model->attributes[$fieldName] = null; 
        } 
       } 
      } 

      return true; 
     }); 

    } 

} 

Das Modell, wo Sie leere Formularfelder sanieren muss sollte diese Klasse erweitert, dann sollten Sie $ forcedNullFields Array mit Feldnamen füllen, die NULL sein erforderlich Fall von leeren Formularfeldern:

class SomeModel extends EloquentBaseModel { 
    protected $forcedNullFields = ['BirthDate','AnotherNullableField']; 
} 

Und das ist alles, Sie sollten nicht denselben Code in Mutatoren wiederholen.

+0

Das ist meiner Meinung nach die beste Antwort.Es gibt die perfekt granulare Kontrolle, die Mutatoren tun, ohne den Code immer und immer wieder zu wiederholen. Und es ist noch mehr Laravel-artig, was schön ist. – jlbang

+0

nicht in dem Fall, dass Sie Null als gültigen Wert haben –

Verwandte Themen