title: Solidity: Students certification architecture
body: <p>I recently did a course on uDemy and get the first concepts. I'm starting to build a real-life app for a training center. I want to register in the blockchain that Jhon Doe, ID (document) xxxx, approved the course &quot;Master of blockchain&quot; at a specific date, and also register the &quot;expiration date&quot; for the certification/permission.</p>
  <p>In PHP I would create an array like this:</p>
  <pre><code>$certifications[123456] = [
      [
      &quot;name&quot; =&gt; &quot;Jhon&quot;,
      &quot;lastName&quot; =&gt; &quot;Doe&quot;,
      &quot;courseName&quot; =&gt; &quot;Blockchain master&quot;,
      &quot;Expiration date&quot; =&gt; &quot;2022-01-01&quot;
      ],
      [
      &quot;name&quot; =&gt; &quot;Jhon&quot;,
      &quot;lastName&quot; =&gt; &quot;Doe&quot;,
      &quot;courseName&quot; =&gt; &quot;Just another course&quot;,
      &quot;Expiration date&quot; =&gt; &quot;2021-01-01&quot;
      ]
  ];
  </code></pre>
  <p>With the output:</p>
  <pre><code>array (size=1)
    123456 =&gt; 
      array (size=2)
        0 =&gt; 
          array (size=4)
            'name' =&gt; string 'Jhon' (length=4)
            'lastName' =&gt; string 'Doe' (length=3)
            'courseName' =&gt; string 'Blockchain master' (length=17)
            'Expiration date' =&gt; string '2022-01-01' (length=10)
        1 =&gt; 
          array (size=4)
            'name' =&gt; string 'Jhon' (length=4)
            'lastName' =&gt; string 'Doe' (length=3)
            'courseName' =&gt; string 'Just another course' (length=19)
            'Expiration date' =&gt; string '2021-01-01' (length=10)
  </code></pre>
  <p>Furthermore, I want to create a function to find by document ID the certification he/she did.</p>
  <p>Needless to say that I want to keep it on memory on a persistent way, using gas if necesary.</p>
  <p>I thought in create a mix between mapping and array for this, maybe struct... But I've the feeling that I'm on the wrong way.</p>
  <p>So... Anybody can guide me or send me a similar example to check how to approach?</p>
  <p>Thanks in advance!</p>
  <p><strong>Edition 1:</strong></p>
  <p>I write this code following some tips and got it working except 2 thing:</p>
  <pre><code>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 =&gt; 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,
          uint dni,
          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, lastname, dni, certificationName, instructorName, dueDate, expirationDate);
      }
      
      function checkCertificateByDni(uint id) public view returns (Certificate memory) {
          return (certifications[dniToCertification[id]]);
          
      }
      
  }
  </code></pre>
  <ol>
  <li>Mapping is not iterable, so I have to return the entire Struct objects using <code>experimental ABIEncoderV2</code></li>
  <li>I got error at the second time I want to call <code>subscribeCertificate</code> with not detailed information...</li>
  </ol>