-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Description
- Laravel Version: 6.9.0
- PHP Version: 7.3.9
- Database Driver & Version: PostgreSQL 12
Description:
I am fleshing out a multi level XML part that I am loading into a new model instance. This model consists of a double primary key: id and language.
The ->save() method works fine, but I need to update the data table which means that I could use the ->updateOrCreate() method, but I need to transform the object to an array first, as this is what the updateOrCreate() method eats. It does not take any model objects. I find that to be somewhat inconsistent.
When I reload the exact same data using this approach, it all works fine.
However, when I test my code by throwing away the first few records, the SQL server blows up, It gives a SQLSTATE[23502]: Not null violation error. The first record is not found, and it tries to create it, but for some vague reason the first primary key is returning "NULL"
Steps To Reproduce:
Here's my store method:
public function store(Request $request, EtimUpdate $etim_update, EtimUnit $etim_unit)
{
// DB::table('etim_units')->delete();
$units =$etim_update->harvest("Units");
// ddd($unit->Translations->Translation[0]->attributes()["language"]->__toString());
foreach($units->children() as $unit) {
foreach ($unit->Translations->children() as $translation) {
$etim_unit = new EtimUnit;
$etim_unit->id = $unit->Code->__toString();
$etim_unit->language = $translation->attributes()["language"];
$etim_unit->description = $translation->Description->__toString();
$etim_unit->abbreviation = $translation->Abbreviation->__toString();
$etim_unit->updateOrCreate($etim_unit->toArray());
// $etim_unit->save();
}
}
}
And the harvest() metthod asused above is coming from an inherited base class EtimUpdate.php, see code below:
public function harvest($element)
{
$reader = new XMLReader();
$reader->open($this->path . $this->filename) ;
$result = [];
while ($reader->read()) {
if ($reader->name == $element && $reader->nodeType == XMLReader::ELEMENT) {
// $result = new SimpleXMLElement($reader->readOuterXml());
$result = simplexml_load_string($reader->readOuterXml());
return $result;
}
}
$reader->close();
}
And here's a sample of a unit element which is loaded from a very large XML:
<Units>
<Unit>
<Code>EU000002</Code>
<Translations>
<Translation language="de-DE">
<Description>Hekto-Pascal</Description>
<Abbreviation>hPa</Abbreviation>
</Translation>
<Translation language="EN">
<Description>Hecto Pascal</Description>
<Abbreviation>hPa</Abbreviation>
</Translation>
<Translation language="fi-FI">
<Description>hehtopascal</Description>
<Abbreviation>hPa</Abbreviation>
</Translation>
<Translation language="fr-BE">
<Description>hectopascal</Description>
<Abbreviation>hPa</Abbreviation>
</Translation>
<Translation language="it-IT">
<Description>hPa</Description>
<Abbreviation>hPa</Abbreviation>
</Translation>
<Translation language="nb-NO">
<Description>Hekto-Pascal</Description>
<Abbreviation>hPa</Abbreviation>
</Translation>
<Translation language="nl-BE">
<Description>Hecto Pascal</Description>
<Abbreviation>hPa</Abbreviation>
</Translation>
<Translation language="nl-NL">
<Description>Hectopascal</Description>
<Abbreviation>hPa</Abbreviation>
</Translation>
</Translations>
</Unit>
</Units>
The temporary workaround is to empty the data table and reload everything, but that is not the truly right way to maintain this data table. I need the updateOrCreate() method to work with a bunch of other tables that need to keep historic data too.