You first need to distinguish between running grep through a shell and running grep directly (via the exec system call).
If you run grep directly (e.g. via exec syscall) there's no way to escape the parameter since grep does not expand arguments. You can use the PHP proc_open() function to do this. This would be my first choice.
If you run grep via a shell (sh, bash, csh, tcsh, etc), it's incredibly difficult to ensure the parameter cannot be escaped and introduce various security vulnerabilities. This is what the PHP exec() function does.
For example, if you enclose the parameter with double quotes ("something"), the shell will still expand $var, `cmd`, etc. That is before mentioning that a double quote will terminate the field and allow the attacker to run any command.
If you enclose the parameter with single quote ('something'), there aren't many special characters that can escape the parameter (except a single quote), but in csh/tcsh, for example, you can still access the history (with !) even inside single quotes.
If you can limit the grep to a limited character set (e.g. a-z,A-Z,0-9), you could sanitize the input to ensure it contains nothing else.
Another problem to consider is that if the input starts with a dash (-), grep will see it as a flag regardless of how you execute it.
Ideally you would both sanitize the input and use proc_open() to ensure there's no shell expansion. I think that would be reasonably safe.