You can query the
PersonContactId directly by using either the
AccountId you have (I'm assuming it's the PersonAccount Id) or the
Opportunity.AccountId if the AcountId is for the PersonAccount.
Either of those will allow you to create a method to directly obtain the PersonContactId. Its important to remember there should only be ONE
ContactID for a
PersonAccount, that will allow you to query that Contact using just the
AccountId in a query that would look something like this:
Id contactId = [SELECT Id FROM CONTACT WHERE AccountId = :accountId LImit 1].Id;
In response to comments...
The Opportunity will be a child of the Account. Opportunity has a field on it for
AccountId. If you do not have it at the time you need the
ContactId, you should be able to query Opportunity to get the Account Id. It will be much easier for you to do that separately than to try to do it in a single query.
Here is how to obtain it using the
opportunityId variable in your controller:
Opportunity opp = [SELECT AccountId FROM Opportunity WHERE Id = : opportunityid limit1];
// Id of personAccount = opp.AccountId;
Id contactId = [SELECT Id FROM CONTACT WHERE AccountId = :opp.AccountId LImit 1].Id;
If you have any issues with the above, either declare
Id personAccount = opp.AccountId or try using
opp.AccountId and if necessary, use
list<opportunity>opp in the query declaration. Sometimes these things do not compile as they should when limit 1 is used in the query.