Нужен совет по оптимизации функции

1.32K
.
ДоХтор

Доброго времени суток
Помогите мне асилить код. Не могу воткнуть внутрь одной функции другую ф-цию--инкрементатор. Вернее, воткнуть-то не проблема, а проблема в том, что в теле функции инкрементатор не даёт того результата, как если передавать его в гет-параметре в функцию. Код работает, но мне не нравится, что вместо одной функции надо описывать две, и потом их конкатенировать .

Есть ли смысл в попытках совмещения этих функций друг с другом? Или можно оставить как есть?

Описание (+/-)
session_id() ?: session_start();

/**
 * Устанавливает лимит на клики по временнОму интервалу
 * 
 * @param string $href    Ссылка для редиректа
 * @param string $lnkname Название ссылки
 * @param int    $days    Количество дней
 * @param int    $clicks  Количество кликов по ссылке
 * @param string $dir     Название папки для файлов
 * @param string $id      ID пользователя (или id сессии для гостей)
 * 
 * @return string Возвращает ссылку с лимитом кликов.
 *                Если лимит исчерпан - пустую строку
 */
function showLink($href, $lnkname, $days, $clicks, $dir, $id) {
    $id = (isset($_GET['id']) ? trim(strip_tags($_GET['id'])) : $id);
    $go = (isset($_GET['go']) ? trim(strip_tags($_GET['go'])) : '');
    
    is_dir($dir) ?: mkdir($dir);
    $fname = $dir .'/'. $id .'.txt';

    $time = time();
    $mTime = $time + 45; # <---Строка для теста
//  $mTime = $time + 3600 * 24 * $days;
    
    file_exists($fname) ?: file_put_contents($fname, serialize(['tm'=>$mTime, 'cnt'=>0]));
    $data = unserialize(file_get_contents($fname));
    
    if (!empty($go)) {
        $data['cnt']++;
        file_put_contents($fname, serialize($data));
        header('Location: '. $go);
        exit;
    }

    if ($data['tm'] < $time) { // Перезапись
        file_put_contents($fname, serialize(['tm'=>$mTime, 'cnt'=>0]));
        $data = unserialize(file_get_contents($fname));
    }
    
    return ($data['tm'] >= $time && $data['cnt'] < $clicks ? '<a href="?id='. $id .
        '&go='. $href .'">'. $lnkname .'</a> ('. ($clicks - $data['cnt']) .')<br/>' : '');
}

/**
* Функция-инкрементатор
*/
function i() {
    static $i = 0;
    return ++$i;
}
Использование (+/-)
echo showLink(
    basename(__FILE__),
    'Тест',
    1,
    10,
    'DIR',
    session_id() . i()
);

echo showLink(
    'http://johncms.com/',
    'JohnCMS',
    1,
    10,
    'DIR',
    session_id() . i()
);

/*
    Тест (10)
    JohnCMS (10)
*/
Собственно, меня смущает такой вариант передачи аргумента: session_id() . i()
Понятное дело, что можно было session_id() . i() сохранить в переменную, но тогда для каждого вызова showLink придётся писать блок переменных с параметрами, и код будет громоздкий (если прописать 10 ссылок, то добавится 60 строк кода). Как сделать правильнее, и практичнее?
Спасибо.
.

Ааа... мои глаза. Почему так много global в теле функции?

.
# Delphinum (25.08.2016 / 19:05)
Ааа... мои глаза. Почему так много global в теле функции?
Всего две ))
.

это тебе кажется что 2, на самом деле все вызовы рода file_put_contents, exit, mkdir, $_GET это global вызовы

.
# Delphinum (25.08.2016 / 19:09)
это тебе кажется что 2, на самом деле все вызовы рода file_put_contents, exit, mkdir, $_GET это global вызовы
А я считал только $_GET'ы. А как тогда можно обходиться без перечисленных тобой global вызовов ?
.

ДоХтор, ну от задачи зависит

.
# Delphinum (25.08.2016 / 21:14)
ДоХтор, ну от задачи зависит
Ну если взять конкретно код этой функции -- на мой взгляд, без того, что сейчас прописано в теле, не обойтись.

Но я ещё хочу напомнить суть вопроса - нужно ли как-то совмещать эти две функции? Или оставить из как есть?
.
# ДоХтор (25.08.2016 / 21:19)
=без того, что сейчас прописано в теле, не обойтись
Легко обойтись. Я бы выделил логику на:
* база, хранящая историю кликов
* стратегию ограничивающую клики
* контроллер
.
аkа ПьяНый Ангел

А зачем ты в 27 и 28 строке создаешь файл и потом его же считыватель? Объви просто массив, 32 и 38 - можно сделать 1 запист в файл, а в условиях просто собрать данные. 39 строка зачем? У тебя же есть массив с данными уже. Это если без заморочек, а просто подправить функцию

.
ДоХтор
А зачем ты в 27 и 28 строке создаешь файл и потом его же считыватель?
В 27-й строке я создаю файл, при условии, что его нет. Иначе(если его ещё нет) в 28-й строке я сразу же получу ошибку при попытке прочитать не существующий файл.
39 строка зачем?
На счёт блока кода со строки 37 и до 40 -- я в условии проверяю время, если время истекло, то перезаписываю файл. Ну а если файл перезаписан, то надо же и свежие данные из него получить. Для этого мне надо или прочитать его снова(что я и сделал в 39-й строке), или перезагрузить страницу заголовком location.

Для этого мне надо или прочитать его снова(что я и сделал в 39-й строке), или перезагрузить страницу заголовком location.
Я понял, о чём ты. 39-ю строку надо выпилить, а свежие данные итак уже есть в массиве. Спс )
Всего: 47