Copiar los datos de una fila a otra fila con Eloquent (o Fluent) de Laravel
Pregunta
Aquí está el trato.He configurado mi base de datos con dos tablas que son más o menos como sigue (en realidad, mi tabla es mucho más compleja, pero esto es lo esencial):
TABLA `elementos`
- identificación
- datos
TABLA `elemento_borradores`
- identificación
- id_elemento
- datos
Como podrá adivinar por los nombres, la segunda tabla contiene filas que son borradores de las filas de la primera tabla.(No te preocupes por recomendar mejores formas de hacer los borradores =) mis tablas son más complejas de lo que se muestran, y tener una mesa de borradores es la mejor solución).
He configurado una relación entre las dos tablas para poder hacer cosas como esta:
// Get all of the elements along with their draft rows
$elements_with_drafts = Element::with('drafts')->all();
También puedo seleccionar solo los elementos que TIENEN filas de borrador haciendo esto:
$elements_with_drafts = Element::with('drafts')
->whereIn('id', function($query)
{
$query->select('element_id')->from('element_drafts');
})
->get();
Pero hay una cosa que me gustaría hacer y que no puedo entender:copiando los valores borrador a su elemento padre.
Al final, mi objetivo es copiar todos los valores element_drafts['data'] a su campo element_drafts['data'] principal mediante una única consulta.
No estoy totalmente seguro de que esto sea posible.¿Lo es?
Supongo que de alguna manera podría hacerse así:
$elements_with_drafts = Element::with('drafts')
->whereIn('id', function($query)
{
$query->select('element_id')->from('element_drafts');
})
->update(array("data" => function($query)
{
// Somehow select the draft value?
});
Siento que estoy muy cerca, pero no estoy muy seguro de cómo hacer lo que quiero.¿Algunas ideas?
Nota:Obviamente, esto podría lograrse con relativa facilidad con un foreach
bucle, pero espero una solución que sea solo una consulta.
Solución
Como el de @Ben, solo que él cometió algunos errores:
DB::statement('UPDATE elements e
JOIN element_drafts d ON e.id = d.element_id
SET e.data = d.data');
De hecho puedes usar Query Builder
también:
DB::table('elements as e')
->join('element_drafts as d', 'd.element_id', '=', 'e.id')
->update(['e.data' => DB::raw('d.data')]);
Ambos funcionarán igual.
Tenga en cuenta que se establecerá e.data
a d.data
de la primera fila unida (en caso de que tenga más borradores de uno por elemento).
Otros consejos
DB::statement('UPDATE elements e
JOIN drafts d
SET e.data = d.data WHERE e.id = d.element_id');
Editar: Marque la respuesta de DecZO para una solución de consulta de consulta.