One option is to pass the post ID as a url parameter when the edit link is clicked.
For example, in some template user can see a list of one’s posts. Each post has an edit link and the post id appended to the link as a url parameter.
<ul>
<?php foreach( $users_posts as $users_post ) : ?>
<li>
<span><?php echo esc_html( $users_post->post_title ); ?></span>
<a class="button" href="/edit?id=<?php echo esc_attr( $users_post->ID ); ?>">Edit</a>
</li>
<?php endforeach; ?>
</ul>
When the user clicks on one of the edit links s/he is directed to the editing template, where the id parameter is identified and used to determine, if the user can edit the corresponding post.
<?php
$post_id = ( ! empty( $_GET['id'] ) && is_numeric( $_GET['id'] ) ) ? absint( $_GET['id'] ) : 0;
$post_to_edit = $post_id ? get_post( $post_id ) : false;
if ( current_user_can( 'edit_post', $post_id ) && $post_to_edit ) : ?>
<form id="edit_form" method="post">
<label>
<span>Post title</span><br>
<input type="text" name="post_title" value="<?php echo esc_attr( $post_to_edit->post_title ); ?>">
</label>
<!-- more form fields -->
<input type="hidden" name="id" value="<?php echo esc_attr( $post_id ); ?>">
<!-- nonce field -->
<!-- submit -->
</form>
<?php else : ?>
<p>Nothing to see here</p>
<?php endif; ?>
You could also do the editing view access checking earlier, for example on template_redirect
action.
add_action( 'template_redirect', function(){
$post_id = ( ! empty( $_GET['id'] ) && is_numeric( $_GET['id'] ) ) ? absint( $_GET['id'] ) : 0;
$post_to_edit = $post_id ? get_post( $post_id ) : false;
if ( ! current_user_can( 'edit_post', $post_id ) || ! $post_to_edit ) {
nocache_headers();
wp_safe_redirect( home_url( "https://wordpress.stackexchange.com/" ) );
exit;
}
});