You can ask users not to enter shipping addresses with PO boxes (or,
more plausibly, only use street addresses for shipping addresses). And
you can attempt to verify that the addresses they enter do not include
PO boxes (or are street addresses).
But you cannot prevent them from entering addresses with PO boxes
unless you can determine exactly what USPS, or whatever shippers you
use, will treat as an address with a PO box. And since addresses are
interpreted by people, that will be difficult.
The country is the United States. My understanding of a PO Box is
that it is of the form PO Box #### where "#" is a number between 0 and
9. But the number of numbers could be unlimited, I suppose and there
could be variation in how "PO Box" is written, e.g. if punctuations
are included somewhere within.
This specification is decidedly incomplete.
In my experience, USPS, for example, will treat any of the following
as referring to a PO box:
PO Box 123
P.O. box 123
PO Box #123
Box 123
Box no. 123
#123 [if there's no street address]
Frankly, if you addressed a letter to:
Smith
123
01945
and mailed it in the US, and the Marblehead, Massachusetts post office
(zip code 01945) happened to have a box 123 owned by someone named
Smith, it would very likely be delivered there.
Shippers are typically fairly aggressive in deciphering addresses;
that's good for business.
So barring getting a strict specification from all of your shippers,
and implementing it (both unlikely), the best you can do is provide
some heuristics. My initial suggestion would be: if the first address
line with a series of digits does not have anything after the digits,
it's probably a box number.
That accepts (identifies as a box) any of the examples above, while
rejecting (identifying as a street address) cases like:
123 5th [an address on 5th Street]
123 Main #3 [an address with an apartment number]
and so forth. Assuming you've already identified the line of text that
might be a box number, the regex:
/^\D*\d+$/
would identify offending entries. (It says: start at the beginning of
the string and scan until you find a series of digits. Is there
anything after those digits? If not, then we have a match.)
My recommendation: if you implement this, and you get a match, alert
the user that it *appears* they have supplied a PO box, and that PO
boxes are not allowed, and let them change *or keep* their entry. If
you get a false positive, you don't want to prevent the user from
submitting valid data. Better to take invalid input and have a person
correct it later (by contacting the user or whatever).