Als Teil der Lernsolidität und Smart-Contract-Entwicklung entwickle ich ein einfaches Teileverwaltungs-/Verfolgungssystem. Ich habe eine Struktur und eine Zuordnung für eine Liste von Teilen als solche:
struct Part {
uint pNumber;
string pName;
string pDesc;
string pManuf;
string[] owners;
}
mapping(uint => Part) public part_store;
uint public partsCount;
Ich füge der Zuordnung neue Teile mit der folgenden Methode hinzu:
function createPart (string _pName, string _pDesc, string _pManuf) public {
partsCount++;
part_store[partsCount].pNumber = partsCount;
part_store[partsCount].pName = _pName;
part_store[partsCount].pDesc = _pDesc;
part_store[partsCount].pManuf = _pManuf;
part_store[partsCount].owners.push(_pManuf);
/* Trigger event */
emit partCreatedEvent(partsCount);
}
Alles wird fehlerfrei kompiliert und ich kann diese Transaktion über Truffle einreichen. Ich erhalte eine Transaktions-ID, wenn ich neue Teile erstelle.
Jetzt versuche ich, die Daten innerhalb des Teils zu lesen, aber ich sehe das Array nicht, in das ich die Daten verschoben habe. Es scheint, dass die letzten Daten im Objekt der Hersteller sind. Aber es zeigt nicht, dass ich den Originalhersteller als Besitzer dieses Teils gedrängt habe.
> contract.part_store(1)
Result:
[ BigNumber { s: 1, e: 0, c: [1] },
'part name',
'part desc',
'part Manuf' ]
>
Habe ich das Array nicht richtig definiert und Daten dorthin geschoben? Wie kann ich die Daten in diesem Array lesen? Ich brauche ein Array, weil dies eine einfache Möglichkeit ist, Eigentümer für die Teile zu speichern, da sich Eigentümer ändern können (dh einen neuen Eigentümer definieren, indem ein neuer Eigentümer für das bestimmte Teil in das Array verschoben wird).
Danke an alle.
BEARBEITEN : Es scheint, dass ich public
den Wert lesen kann, wenn ich ein Array außerhalb einer Struktur und definiere:
string[] public test1;
string[] test2;
function writeElem() public {
test1.push("t1");
test2.push("t2");
}
Ergebnisse:
> contract.writeElem()
...tx: 0x88...
...txHas: 0x88...
> contract.test1(0)
't1'
> contract.test2(0)
TypeError: app.test2 is not a function
> contract.test2
undefined
Ich glaube nicht, dass ich Variablen in struct public oder private definieren kann, also kann ich diese Daten vielleicht deshalb nicht lesen? Könnte es etwas mit Datenzugriff für Arrays in Solidity sein?
Was passiert ist, dass der "kostenlose" Getter, den Sie verwenden, den indizierten Wert nicht unterstützt, also lässt er ihn einfach weg. Der "kostenlose" Getter aus dem public
mapping
ist ungefähr
function part_store(uint index) public view returns(uint, string, string, string) {
Part storage p = part_store[index];
return (p.pNumber, p.pName, p.pDesc, p.pManu);
}
Sie müssen eine Funktion erstellen, um die fehlenden Informationen abzurufen. Sie haben Spielraum. Sie könnten einfach mit dem weitermachen, was ich begonnen habe, und das Array hinzufügen, aber ich bin kein großer Fan davon, aufgrund von Skalierungsproblemen und Benzinkosten.
Sie könnten stattdessen
function getProductOwnerCount(uint part) public view returns(uint) {
return prod_store[part].owners.length;
}
function getProductOwnerAtIndex(uint part, uint index) public view returns(address) {
return prod_store[part].owners[index];
}
Mit diesen beiden Funktionen kann jeder Beobachter die Array-Länge festlegen (damit er nicht am Ende vorbeiläuft) und die Zeile abrufen, an der er interessiert ist. Oder der Client kann alle Zeilen durchlaufen, um sie alle zu erhalten. Es ist erwähnenswert, dass Clients möglicherweise bereits über die meisten Eigentümer Bescheid wissen, wenn sie Ereignisprotokolle beobachtet haben und jedes Mal, wenn ein Eigentümer hinzugefügt wurde (sollte), Ereignisse ausgegeben wurden.
Ich hoffe es hilft.
Konnte eine Antwort auf meine Frage finden. Sie können Zeichenfolgen zurückgeben, solange Sie das memory
Schlüsselwort verwenden.
function getProductOwner() public view returns(string memory) {
return part_store[1].owners[0];
}
Machen Sie dasselbe für String-Arrays, aber Sie müssen auch eine neue Pragma-Definition oben auf der Quellseite hinzufügen, um dies tun zu können. Sie erhalten Warnungen, aber keine Fehler. Ich nehme an, dass dies daran liegt, dass es sich um eine neue Funktion handelt, die schließlich in Solidity voll funktionsfähig sein wird.
pragma experimental ABIEncoderV2;
function getProductOwners() public view returns(string[] memory) {
return part_store[1].owners;
}
MB41
getProductOwnerAtIndex
. Das Array speichert jedoch eine Zeichenfolgenliste mit Namen anstelle von Adressen. In diesem Fall wird es sagen...returns(string)
und nicht adressieren. Wenn ich das versuche, bekomme ichTypeError: Data location must be "memory" for return parameter in function, but none was given.
MB41
memory
Schlüsselwort als solches verwenden...returns(string memory) {
. Machen Sie dasselbe für String-Arrays, müssen aber auch definierenpragma experimental ABIEncoderV2;
, um dies tun zu können. Danke, dass du mich in die richtige Richtung weist.Rob Hitchens