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

Tallanvor

НЕ ПИШУ я плагины!!! И не правлю! И ваще...
Сообщения
1,352
Реакции
554
Нужна консультция.

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

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

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

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

Кто-нибудь может что-то посоветовать?
 

The Night Fury

Участник
Сообщения
1,300
Реакции
1,395
Покажи скрипт, попробую что-нибудь придумать.
 

Tallanvor

НЕ ПИШУ я плагины!!! И не правлю! И ваще...
Сообщения
1,352
Реакции
554
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 / 1073741824, 2) . ' ГБ';
        }
        elseif ($bytes >= 1048576)
        {
            $bytes = number_format($bytes / 1048576, 2) . ' МБ';
        }
        elseif ($bytes >= 1024)
        {
            $bytes = number_format($bytes / 1024, 2) . ' КБ';
        }
        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);?>

И всё остальное в таком же ключе.
 

The Night Fury

Участник
Сообщения
1,300
Реакции
1,395
Держи. Переписал с ООП.
Результат:
vHPc625.png

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

	private function formatFileSize($bytes) {
		switch($bytes) {
			case $bytes >= 1073741824: $formatted_bytes = number_format($bytes / 1073741824, 2).' Гб'; break;
			case $bytes >= 1048576: $formatted_bytes = number_format($bytes / 1048576, 2).' Мб'; break;
			case $bytes >= 1024: $formatted_bytes = number_format($bytes / 1024, 2).' Кб'; 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)!

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

Tallanvor

НЕ ПИШУ я плагины!!! И не правлю! И ваще...
Сообщения
1,352
Реакции
554
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 'Демка ещё пишется'; }
 
Последнее редактирование:

The Night Fury

Участник
Сообщения
1,300
Реакции
1,395
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.
 

Tallanvor

НЕ ПИШУ я плагины!!! И не правлю! И ваще...
Сообщения
1,352
Реакции
554
The Night Fury, ну, меня больше структура интересовала, синтаксис пропишу, как надо :)

Спасибо :)

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

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

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

The Night Fury

Участник
Сообщения
1,300
Реакции
1,395
И да, заново назначать класс не требуется. Достаточно один раз назначить, а потом уже менять значение переменной.

Увы, я не знаю, как можно (и можно ли вообще) средствами одного только PHP проверить, изменяется ли на данный момент файл, или уже можно с ним работать дальше.
В теории — http://php.net/manual/ru/function.is-writable.php
Тут-то не особо принципиально, но я попросту не рекомендую использовать команды shell в скриптах PHP.
 

Tallanvor

НЕ ПИШУ я плагины!!! И не правлю! И ваще...
Сообщения
1,352
Реакции
554
Тут-то не особо принципиально, но я попросту не рекомендую использовать команды shell в скриптах PHP.
Сам админю...
Знаю, каюсь.....


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

Vaio

Участник
Сообщения
625
Реакции
215
Оффтоп
 

Tallanvor

НЕ ПИШУ я плагины!!! И не правлю! И ваще...
Сообщения
1,352
Реакции
554
Оффтоп
 

The Night Fury

Участник
Сообщения
1,300
Реакции
1,395
Vaio, понятное дело, только ему не требуется отделение одного от другого. А правильно — слишком много ненужного ему обвеса получается. А так — и быстро, и просто, и относительно красиво.
 

Tallanvor

НЕ ПИШУ я плагины!!! И не правлю! И ваще...
Сообщения
1,352
Реакции
554
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 / 1073741824, 2).' Гб'; break;
            case $bytes >= 1048576: $formatted_bytes = number_format($bytes / 1048576, 2).' Мб'; break;
            case $bytes >= 1024: $formatted_bytes = number_format($bytes / 1024, 2).' Кб'; 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++;
        }
    }
}
?>
 
Сверху Снизу