Перебор массива?
Если набор городов фиксированный, то можно так:function extractCity($str) {
    $cities = ["киев"=>["kyiv", "київ"], "одесса", "днепр"];
    foreach ($cities as $city=>$aliases) {
        $city = is_numeric($city) ? $aliases : $city;
        if (mb_strpos(mb_strtolower($str), $city) !== false) {
            return $city;
        }
        if (is_array($aliases)) {
            foreach ($aliases as $alias) {
                if (mb_strpos(mb_strtolower($str), $alias) !== false) {
                    return $city;
                }
            }
        }
    }
    return "не определен";
}

var_dump(extractCity("Продам что-то Киев")); // string(8) "киев"
var_dump(extractCity("Обменяю что-то, в Киеве")); // string(8) "киев"
var_dump(extractCity("Куплю що то :: Київ можна")); // string(8) "киев"
var_dump(extractCity("Продам что-то Москве")); // string(23) "не определен"
Если набор городов не фиксированный, то тогда необходмио подключать более умный пасрсер текста типа Наташи
Ваша задача называется "стемминг" решений у неё много, причём преимущественно плохих, но для русского языка есть например яндексовский mystem, имеющий отличную точность и скорость, при всём этом ещё и почти не требовательный к ресурсам. Но я, признаться честно, не помню как у него с лицензией на коммерческое использование. Как бы то не было, узнав правильное название вашей задачи, я надеюсь, вы быстро выгуглите решение.