A common approach to match all text to the last occurrence of the subsequent pattern(s) is using a greedy dot, .*. So, you may match and capture the text before the last text and replace with a backreference + the new value:
$str = 'text abcd text text efgh';
echo preg_replace('~(.*)text~su', '${1}bar', $str);
// => text abcd text bar efgh
If text is some value inside a variable that must be treated as plain text, use preg_quote to ensure all special chars are escaped correctly:
preg_replace('~(.*)' . preg_quote($text, '~') . '~su', '${1}bar', $str)
See the online PHP demo and a regex demo.
Here, (.*) matches and captures into Group 1 any zero or more chars (note that the s modifier makes the dot match line break chars, too), as many as possible, up to the rightmost (last) occurrence of text. If text is a Unicode substring, the u modifier comes handy in PHP (it enables (*UTF) PCRE verb allowing parsing the incoming string as a sequence of Unicode code points rather than bytes and the (*UCP) verb that makes all shorthand character classes Unicode aware - if any). 
The ${1} is a replacement backreference, a placeholder holding the value captured into Group 1 that lets restore that substring inside the resulting string. You can use $1, but a problem might arise if the $text starts with a digit.