Modern cryptography in PHP has meant either openssl with a lot of decisions to get wrong, or a PECL extension nobody had. 7.2 puts libsodium in core, with an API that removes most of the choices.
$key = sodium_crypto_secretbox_keygen();
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$cipher = sodium_crypto_secretbox($plaintext, $nonce, $key);
$plain = sodium_crypto_secretbox_open($cipher, $nonce, $key);
sodium_memzero($plaintext);
There is no cipher to choose, no mode, no padding decision — which is the whole design. The nonce must be unique per message and does not need to be secret, so storing it alongside the ciphertext is correct. sodium_memzero() is the one people skip: PHP strings are copied freely, so it only helps if the plaintext has not already been duplicated.