PHP surround search text with words
You say you want to search a text string from a database, but are not showing the database part.  This is key to think about, as I am guessing you could cut out all this work if you made appropriate search requests against an appropriately designed data store.  Most any modern relational database supports some level of natural language search, which would allow you to actually do this across more than a single string at a time.

This is not to mention the existence of data stores both open source and commercial geared specifically towards search cases, even allowing the ability to return search matches with context as you are trying to do.

Consider doing this sort of work with a tool that is optimized for this purpose.

Thoughts on code:


You are clearly working with multibyte strings yet are not using the multibyte versions of the the standards string manipulation functions.  This could lead to unexpected behavior. If you need to have string functions overloaded with mb counterparts, you might consider a comment in the code noting that this PHP setting needs to be turned on for this code to operate properly.
you should add vertical white space to you code around logical sections to help ease of reading. Think of empty lines like you would paragraphs in writing. They help break up your thoughts.
you are casting to lowercase only on haystack and not on needle.  Why is this? Typically if you are doing case insensitive search, you would cast both in same manner.
you may consider using regex with appropriate substring pattern capture and compare from a performance standpoint. I am not sure if it will perform as well, but it could certainly simplify your code, which can sometimes holds more value if performance is not too big of a trade off.
your code isn't designed to handle multiple matches. This may be OK with regards to the design, but figured I would point this out.  You could take your example haystack and search for "the", and never get the second occurrence found.
what happens if space is passed as search string?
what happens if single character is passed or other similar trivial or ambiguous search term? Do you have something up the call stack which weeds out these potentially undesirable use cases?