В приведенном здесь коде я создал нового клиента с именем «mcycleowner» и сопоставил его с входным _address. Однако я также хочу сопоставить его с входной _license, чтобы информацию о клиенте можно было запрашивать либо с помощью Eth-адреса, либо с номерного знака.
Для этого я создал нового клиента «mcyclelicenses», и функция addLicense принимает те же входные данные, что и newMcycleOwner (кроме адреса), только этот клиент сопоставляется с _license. Эта функция запускается внутри функции «newMcycleOwner», так что и клиенты, и сопоставления создаются одновременно.
Однако такой способ означает наличие двух записей информации о каждом клиенте, что кажется пустой тратой места, а также всякий раз, когда необходимо изменить информацию о клиенте, ее придется изменить в двух местах. Есть лучший способ сделать это?
// < ---------------------- MOTORCYLCES ---------------------- >
mapping (address => Customer) mcycleowners;
address[] public mcycleownerAdds;
function newMcycleOwner(address _address, string _custname, string _color, string _make, uint32 _year, string _license) onlyMember public {
Customer storage mcycleowner = mcycleowners[_address];
mcycleowner.custname = _custname;
mcycleowner.color = _color;
mcycleowner.make = _make;
mcycleowner.year = _year;
mcycleowner.license = _license;
mcycleownerAdds.push(_address);
addLicense(_custname, _color, _make, _year, _license);
}
function getMcycleAdds() public view returns(address[]) {
return mcycleownerAdds;
}
function getMcycleByAdd(address _address) public view returns(string, string) {
return (mcycleowners[_address].custname, mcycleowners[_address].license);
}
function countMcycle() public view returns(uint) {
return mcycleownerAdds.length;
}
// <---------- CREATION OF NEW MAP SO WE CAN QUERY BY LICENSE ---------->
//This seems to create two instances of each customer. Replace with a better method.
mapping (string => Customer) mcyclelicenses;
function addLicense(string _custname, string _color, string _make, uint32 _year, string _license) onlyMember public {
Customer storage mcyclelicense = mcyclelicenses[_license];
mcyclelicense.custname = _custname;
mcyclelicense.color = _color;
mcyclelicense.make = _make;
mcyclelicense.year = _year;
}
function getMcycleByLic(string _license) public view returns(string, string, string, uint32) {
return (mcyclelicenses[_license].custname, mcyclelicenses[_license].color, mcyclelicenses[_license].make, mcyclelicenses[_license].year);
}
Простым способом сделать это может быть сохранение информации о клиентах внутри массива и использование сопоставления для хранения индексов массива, чтобы вы могли напрямую обращаться к индексу через сопоставление и использовать этот индекс для прямого доступа к массиву.
Вот пример
pragma solidity ^0.4.23;
contract ContractX {
struct Customer {
string name;
string license;
/* other infos */
}
mapping (address => uint) addressIndexes;
mapping (string => uint) licenseIndexes;
Customer[] customers;
uint customerCount;
function addNewItem(address _address, string _name, string _license) public {
customers.push(Customer(_name, _license));
addressIndexes[_address] = customerCount;
licenseIndexes[_license] = customerCount;
customerCount++;
}
function getByAddress(address _address) public view returns(string, string) {
return (
customers[addressIndexes[_address]].name,
customers[addressIndexes[_address]].license
);
}
function getByLicense(string _license) public view returns(string, string) {
return (
customers[licenseIndexes[_license]].name,
customers[licenseIndexes[_license]].license
);
}
}
Таким образом, информация о клиенте была сохранена только один раз, и вы отслеживаете только индекс массива в сопоставлении, чтобы впоследствии использовать его для прямого доступа к нужному вам клиенту.
Другим решением может быть использование Customer
в качестве субконтракта, затем создание контракта при добавлении информации о клиенте и сохранение адреса этого нового контракта в ваших сопоставлениях. Но это открывает другой сценарий, и вам может потребоваться внести несколько изменений.
Вы можете просто сопоставить лицензию с адресом, а затем выполнить два поиска, чтобы разыменовать лицензию.
mapping(string => address) mcyclelicences;
function getMcycleByLic(string _license) public view returns(string, string, string, uint32) {
return (
mcycleowners[mcyclelicenses[_license]].custname,
mcycleowners[mcyclelicenses[_license]].color,
mcycleowners[mcyclelicenses[_license]].make,
mcycleowners[mcyclelicenses[_license]].year
);
}
СозданоAMadman