[PHP] Как избавиться от повторяющихся кусков кода?

Тема в разделе "Веб-технологии", создана пользователем Tallanvor, 12 дек 2015.

  1. Tallanvor

    Tallanvor Красноглазый

    Сообщения:
    1.072
    Симпатии:
    299
    Нужна консультция.

    Есть страница html + php
    Есть два куска пышного кода - один находится в теле страницы, другой - в инклюде.

    Суть проблемы:

    Этот кусок кода повторяется N количество раз по всей странице только из-за того, что Переменные в нём должны нести разные значения.
    Точно так же и инклюды - вся разница в названиях переменных и значений в них.

    В общем я то понимаю, что нужно переделать в функцию или процедуру (в пыхе не силён)
    Но не гуглится что-то...

    Кто-нибудь может что-то посоветовать?
     
  2. The Night Fury

    The Night Fury Администратор

    Сообщения:
    1.221
    Симпатии:
    914
    Покажи скрипт, попробую что-нибудь придумать.
     
  3. Tallanvor

    Tallanvor Красноглазый

    Сообщения:
    1.072
    Симпатии:
    299
    The Night Fury,

    PHP:
    <?php include 'functions.php'?>

    .....
    <?php echo demo_count($demo_storage_css);?>

    .....
        <?php
            $file_count 
    1;
            
    $f glob($demo_storage_css.'*.dem');
            
    krsort($f);
            foreach (
    $f as $file_dem)
            {
                echo 
    '<tr class="data"><td>';
                
    //Count
                
    echo $file_count;
                echo 
    '</td><td>';
                
    //File Name
                
    echo basename($file_dem);
                echo 
    '</td><td>';
                
    //File Size + Size Convert Function
                
    echo size_convert(filesize($file_dem));
                echo 
    '</td><td>';
                
    //Date
                
    echo date("d.m.Y, H:i:s"filemtime($file_dem));
                echo 
    '</td><td>';
                
    //File Link
                
    if(shell_exec('lsof '.escapeshellarg($file_dem)) == null)
                {   echo 
    '<a href="'.$demo_storage_css.basename($file_dem).'">Скачать</a>';  }
                else
                {   echo 
    'Демка ещё пишется'; }
                echo 
    '</td>';
                echo 
    '</tr>';
                
    $file_count++;
            }
        
    ?>

    PHP:
    <?php
        $demo_storage_css 
    "css/public/";
            function 
    size_convert($bytes)
            {
                    if (
    $bytes >= 1073741824)
            {
                
    $bytes number_format($bytes 10737418242) . ' ГБ';
            }
            elseif (
    $bytes >= 1048576)
            {
                
    $bytes number_format($bytes 10485762) . ' МБ';
            }
            elseif (
    $bytes >= 1024)
            {
                
    $bytes number_format($bytes 10242) . ' КБ';
            }
            elseif (
    $bytes 1)
            {
                
    $bytes $bytes ' Б';
            }
            else
            {
                
    $bytes '0 Б';
            }
            return 
    $bytes;
            }
            function 
    demo_count($directory)
            {
                    
    $items glob($directory.'/*.dem');
                    
    $count 0;
                    foreach (
    $items as $item)
                    {
                    if(
    $item != "." && $item != "..")
                    {
                            
    $count++;
                            }
                    }
                    return 
    $count;
            }
    ?>

    Меняется только значение переменной $demo_storage_css в инклюде.

    Но мне приходится пока что плодить кучу инклюдов и менять названия переменных в повторяющихся кусках, чтобы на одной странице получать данные с нескольких папок.

    Т.е. дальше в коде у меня получается

    PHP:
    <?php echo demo_count($demo_storage_css2);?>
    ...
    <?php echo demo_count($demo_storage_css3);?>
    ...
    <?php echo demo_count($demo_storage_css4);?>
    ...
    <?php echo demo_count($demo_storage_css5);?>
    И всё остальное в таком же ключе.
     
  4. The Night Fury

    The Night Fury Администратор

    Сообщения:
    1.221
    Симпатии:
    914
    Держи. Переписал с ООП.
    Результат:
    [​IMG]
    PHP:
    <?php
    class DemoManager {
        public 
    $demo_storage_css;

        private function 
    formatFileSize($bytes) {
            switch(
    $bytes) {
                case 
    $bytes >= 1073741824$formatted_bytes number_format($bytes 10737418242).' Гб'; break;
                case 
    $bytes >= 1048576$formatted_bytes number_format($bytes 10485762).' Мб'; break;
                case 
    $bytes >= 1024$formatted_bytes number_format($bytes 10242).' Кб'; break;
                default: 
    $formatted_bytes $bytes.' Байт';
            }
            
            return 
    $formatted_bytes;
        }

        public function 
    countDemoFiles($dir) {
            
    $items glob($dir.'/*.dem');
            return 
    count($items);
        }

        public function 
    buildDemosList() {
            
    $entry_number 1;
            
    $f glob($this->demo_storage_css.'*.dem'); ksort($f);
            foreach(
    $f as $demofile) {

                
    $file_name basename($demofile);
                
    $file_size $this->formatFileSize(filesize($demofile));
                
    $file_date date("d.m.Y @ H:i:s"filemtime($demofile));

                echo 
    "<tr class='data'>";
                    echo 
    "<td>$entry_number</td>";
                    echo 
    "<td>$file_name</td>";
                    echo 
    "<td>$file_size</td>";
                    echo 
    "<td>$file_date</td>";
                    echo 
    "<td><a href='"$this->demo_storage_css.$file_name ."'>Скачать</a></td>";
                echo 
    "</tr>";
                
    $entry_number++;
            }
        }
    }
    ?>

    PHP:
    <table>
    <?php
    require 'functions.demos.php';
    $dm = new DemoManager();

    $dm->demo_storage_css './testfolder/';
    echo 
    "Количество файлов: ".$dm->countDemoFiles($dm->demo_storage_css);
    $dm->buildDemosList();
    ?>
    </table>

    <hr>

    <table>
    <?php
    $dm
    ->demo_storage_css './testfolder2/';
    echo 
    "Количество файлов: ".$dm->countDemoFiles($dm->demo_storage_css);
    $dm->buildDemosList();
    ?>
    </table>

    Используется так:
    1. Создать зависимость от functions.demos.php
    2. Создать класс DemoManager:
      PHP:
      $myvar = new DemoManager();
    3. Установить папку под переменную:
      PHP:
      $myvar->demo_storage_css 'somefolder/';
      И да, здесь trailing slash обязателен. Для задания папки относительно данной можно использовать "./".
    4. Вызвать нужные методы:
      PHP:
      $myvar->countDemoFiles("./subfolder");
      $myvar->buildDemosList();
      Метод countDemoFiles требует ручного вывода (echo/print)!

    Вот, как-то так.
     
  5. Tallanvor

    Tallanvor Красноглазый

    Сообщения:
    1.072
    Симпатии:
    299
    The Night Fury, если я правильно понял, то должно получиться примерно следующее:

    PHP:
    require 'functions.demos.php';

    <
    div1>
        
    $block1 = new DemoManager();
        
    $block1->demo_storage_css 'mydir/maybe/enother/subdir/';
        
    $block1->countDemoFiles("./current_demos_dir");
        
    $block1->buildDemosList();
    </
    div1>
    ......
    <
    div2>
        
    $block2 = new DemoManager();
        
    $block2->demo_storage_css 'mydir/custom/dir/';
        
    $block2->countDemoFiles("./current_demos_dir");
        
    $block2->buildDemosList();
    </
    div2>

    И да, эта конструкция тоже должна работать, если не ошибаюсь?

    PHP:
    if(shell_exec('lsof '.escapeshellarg($file_name)) == null)
                                                {   echo 
    "<td><a href='"$this->demo_storage_css.$file_name ."'>Скачать</a></td>";  }
                                                else
                                                {   echo 
    'Демка ещё пишется'; }
     
    Последнее редактирование: 12 дек 2015
  6. The Night Fury

    The Night Fury Администратор

    Сообщения:
    1.221
    Симпатии:
    914
    Tallanvor, немного иначе, но суть верна.
    Либо так:
    PHP:
    require 'functions.demos.php'

    echo 
    "<div1>";
        
    $block1 = new DemoManager(); 
        
    $block1->demo_storage_css 'mydir/maybe/enother/subdir/'
        
    $block1->countDemoFiles("./current_demos_dir"); 
        
    $block1->buildDemosList(); 
    echo 
    "<div1>";
    /* */
    echo "<div2>";
        
    $block2 = new DemoManager(); 
        
    $block2->demo_storage_css 'mydir/custom/dir/'
        
    $block2->countDemoFiles("./current_demos_dir"); 
        
    $block2->buildDemosList(); 
    echo 
    "<div2>";
    Либо так:
    PHP:
    <? require 'functions.demos.php'?>

    <div1>
    <?php
        $block1 
    = new DemoManager(); 
        
    $block1->demo_storage_css 'mydir/maybe/enother/subdir/'
        
    $block1->countDemoFiles("./current_demos_dir"); 
        
    $block1->buildDemosList();
    ?>
    <div1>
    ...
    <div2>
    <?php
        $block2 
    = new DemoManager(); 
        
    $block2->demo_storage_css 'mydir/custom/dir/'
        
    $block2->countDemoFiles("./current_demos_dir"); 
        
    $block2->buildDemosList(); 
    ?>
    <div2>
    И да, учти, что countDemoFiles() не зависит от demo_storage_css, а вот buildDemosList() будет формировать список именно из указанной в переменной папки.

    В классе это:
    PHP:
    echo "<td><a href='"$this->demo_storage_css.$file_name ."'>Скачать</a></td>";
    Заменить на это:
    PHP:
    if(shell_exec('lsof '.escapeshellarg($file_name)) == NULL) {echo "<td><a href='"$this->demo_storage_css.$file_name ."'>Скачать</a></td>";} else {echo 'Демка ещё пишется';}
    Но я бы не стал использовать shell в связке с PHP.
     
  7. Tallanvor

    Tallanvor Красноглазый

    Сообщения:
    1.072
    Симпатии:
    299
    The Night Fury, ну, меня больше структура интересовала, синтаксис пропишу, как надо :)

    Спасибо :)

    Увы, я не знаю, как можно (и можно ли вообще) средствами одного только PHP проверить, изменяется ли на данный момент файл, или уже можно с ним работать дальше.

    Без этого юзеру будет отдаваться битый файл.

    ( демки беру напрямую из папки сервера, nginx отдаёт только файлы *.dem, копировать готовые куда-то на сторону - не вариант )
     
  8. The Night Fury

    The Night Fury Администратор

    Сообщения:
    1.221
    Симпатии:
    914
    И да, заново назначать класс не требуется. Достаточно один раз назначить, а потом уже менять значение переменной.

    В теории — http://php.net/manual/ru/function.is-writable.php
    Тут-то не особо принципиально, но я попросту не рекомендую использовать команды shell в скриптах PHP.
     
  9. Tallanvor

    Tallanvor Красноглазый

    Сообщения:
    1.072
    Симпатии:
    299
    Сам админю...
    Знаю, каюсь.....

    Кажись, тут идёт только проверка прав на запись...
    Файл демки, при записи в него, не лочится ничем, если мне память не изменяет.
     
  10. Vaio

    Vaio

    Сообщения:
    628
    Симпатии:
    218
    Оффтоп
     
  11. Tallanvor

    Tallanvor Красноглазый

    Сообщения:
    1.072
    Симпатии:
    299
    Оффтоп
     
  12. The Night Fury

    The Night Fury Администратор

    Сообщения:
    1.221
    Симпатии:
    914
    Vaio, понятное дело, только ему не требуется отделение одного от другого. А правильно — слишком много ненужного ему обвеса получается. А так — и быстро, и просто, и относительно красиво.
     
  13. Tallanvor

    Tallanvor Красноглазый

    Сообщения:
    1.072
    Симпатии:
    299
    The Night Fury, всё-таки сообразил, как это оформить на чистом пыхе, без шелла :)
    Возможно, не очень элегантно, но работает.

    PHP:
    <?php
    class DemoManager {
        public 
    $demo_storage_css;

        private function 
    formatFileSize($bytes) {
            switch(
    $bytes) {
                case 
    $bytes >= 1073741824$formatted_bytes number_format($bytes 10737418242).' Гб'; break;
                case 
    $bytes >= 1048576$formatted_bytes number_format($bytes 10485762).' Мб'; break;
                case 
    $bytes >= 1024$formatted_bytes number_format($bytes 10242).' Кб'; break;
                default: 
    $formatted_bytes $bytes.' Байт';
            }

            return 
    $formatted_bytes;
        }

        public function 
    countDemoFiles($dir) {
            
    $items glob($dir.'/*.dem');
            return 
    count($items);
        }

        public function 
    buildDemosList() {
            
    $entry_number 1;
            
    $f glob($this->demo_storage_css.'*.dem'); krsort($f);
            foreach(
    $f as $demofile) {

                
    $file_name basename($demofile);
                
    $file_size $this->formatFileSize(filesize($demofile));
                
    $file_date date("d.m.Y @ H:i:s"filemtime($demofile));

                
    //Cheking file modification time
                
    $date_cur date("Y-m-d H:i:s");
                
    $uni_date_cur strtotime($date_cur);
                
    $date_file date("Y-m-d H:i:s"filemtime($demofile));
                
    $uni_date_file strtotime($date_file);


                echo 
    "<tr class='data'>";
                    echo 
    "<td>$entry_number</td>";
                    echo 
    "<td>$file_name</td>";
                    echo 
    "<td>$file_size</td>";
                    echo 
    "<td>$file_date</td>";
                if (
    abs($uni_date_file $uni_date_cur) < 70)
                {   echo 
    "<td>Демка ещё пишется!!!</td>"; }
                else
                {   echo 
    "<td><a href='"$this->demo_storage_css.$file_name ."'>Скачать</a></td>"; }
                echo 
    "</tr>";
                
    $entry_number++;
            }
        }
    }
    ?>