问题描述
我最近在uDemy上做了一门课程,并获得了第一个概念。我开始为培训中心构建一个真实的应用程序。我要在区块链中注册ID(文档)xxxx的Jhon Doe,在特定日期批准课程“区块链大师”,并注册证书/许可的“到期日期”。
$certifications[123456] = [
[
"name" => "Jhon","lastName" => "Doe","courseName" => "Blockchain master","Expiration date" => "2022-01-01"
],[
"name" => "Jhon","courseName" => "Just another course","Expiration date" => "2021-01-01"
]
];
输出:
array (size=1)
123456 =>
array (size=2)
0 =>
array (size=4)
'name' => string 'Jhon' (length=4)
'lastName' => string 'Doe' (length=3)
'courseName' => string 'Blockchain master' (length=17)
'Expiration date' => string '2022-01-01' (length=10)
1 =>
array (size=4)
'name' => string 'Jhon' (length=4)
'lastName' => string 'Doe' (length=3)
'courseName' => string 'Just another course' (length=19)
'Expiration date' => string '2021-01-01' (length=10)
不用说,我想以持久的方式将其保存在内存中,必要时使用gas。
我曾考虑为此在映射和数组之间创建一个混合体,但也许是结构...但是我感觉自己走错了方向。
所以...任何人都可以指导我或给我发送类似的例子来检查方法吗?
谢谢!
版本1:
我按照一些技巧编写了这段代码,除了两件事外,它都可以正常工作:
pragma solidity 0.6.6;
pragma experimental ABIEncoderV2;
// SPDX-License-Identifier: MIT
import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol';
contract Certification {
using SafeMath for uint256;
address private owner;
struct Certificate {
string name;
string lastname;
string certificationName;
string instructorName;
uint256 dueDate;
uint256 expirationDate;
}
Certificate[] public certifications;
mapping(uint => uint) public dniToCertification;
event certificateSubscribed(string name,string lastname,uint dni,string certification,string instructor,uint256 date,uint256 untilDate);
constructor() public {
owner = msg.sender;
}
modifier isOwner() {
require(owner == msg.sender);
_;
}
function subscribeCertificate(
string memory name,string memory lastname,string memory certificationName,string memory instructorName,uint256 dueDate,uint256 expirationDate) public isOwner {
certifications.push(Certificate(
name,lastname,certificationName,instructorName,dueDate,expirationDate
));
Certificate storage certification; //certification will be an instance of Struct Certificate
certification.name = name;
certification.lastname = lastname;
certification.certificationName = certificationName;
certification.instructorName = instructorName;
certification.dueDate = dueDate;
certification.expirationDate = expirationDate;
uint id = certifications.length - 1;
dniToCertification[dni] = id;
emit certificateSubscribed(name,dni,expirationDate);
}
function checkCertificateByDni(uint id) public view returns (Certificate memory) {
return (certifications[dniToCertification[id]]);
}
}
- 映射是不可迭代的,因此我必须使用
experimental ABIEncoderV2
返回整个Struct对象。
- 我第二次想打电话给
subscribeCertificate
时出错,但没有详细信息...
解决方法
我建议将证书数组保存在Structs中,并为用户拥有的ID和文档ID的列表提供映射。
//certificate object
struct Certificate {
string name;
string lastName;
string courseName;
uint256 expirationDate;
}
// you can save all certifications on this array.
Certificate[] public certifications;
//save every address certifications and address
mapping(address => uint256[]) public userCertifications;
用法示例:
// get certificate by id
certifications[id]
// get user certifications-> return array of user certifications
userCertifications[msg.sender] or userCertifications[address]
第1版答案
我将您的代码更改为此,我认为它可以为您工作!
pragma solidity 0.6.6;
// SPDX-License-Identifier: MIT
import 'https://github.com/OpenZeppelin/openzeppelin-
solidity/contracts/math/SafeMath.sol';
contract Certification {
using SafeMath for uint256;
address private owner;
struct Certificate {
string name;
string lastName;
string certificationName;
string instructorName;
uint256 dueDate;
uint256 expirationDate;
}
Certificate[] public certifications;
mapping(uint => uint) public dniToCertification;
event certificateSubscribed(string name,string lastname,uint dni,string certification,string instructor,uint256 date,uint256 untilDate);
constructor() public {
owner = msg.sender;
}
modifier isOwner() {
require(owner == msg.sender);
_;
}
function subscribeCertificate(
string memory name,string memory lastname,string memory certificationName,string memory instructorName,uint256 dueDate,uint256 expirationDate) public isOwner {
certifications.push(Certificate(
name,lastname,certificationName,instructorName,dueDate,expirationDate));
uint id = certifications.length - 1;
dniToCertification[dni] = id;
emit certificateSubscribed(name,dni,expirationDate);
}
}
复制并粘贴remix,您会发现有两种方法 一个通过dni获得证书,另一个通过dni获得证书。 另外,您不能获得坚固的结构数组,而必须在客户端进行,并使用循环获取整个证书。