Ответы пользователя по тегу PHP
  • Зачем нужен ООП?

    @m-haritonov
    В PHP ООП нужен, когда нескольким функциям требуется обращаться к общим переменным.

    Без ООП пришлось бы писать код вида:
    <?php
    namespace something1 {
        function set($value) {
            $GLOBALS['something1']['someVariable'] = $value;
        }
    
        function get() {
            return $GLOBALS['something1']['someVariable'];
        }
    }
    
    namespace something2 {
        function set($value) {
            $GLOBALS['something2']['someVariable'] = $value;
        }
    
        function get() {
            return $GLOBALS['something2']['someVariable'];
        }
    }
    
    namespace {
        \something1\set(1);
        \something2\set(2);
    
        print \something1\get();
        print \something2\get();
    }

    и:
    <?php
    namespace something {
        function set($instanceName, $value) {
            $GLOBALS[$instanceName]['someVariable'] = $value;
        }
    
        function get($instanceName) {
            return $GLOBALS[$instanceName]['someVariable'];
        }
    }
    
    namespace {
        \something\set('instance1', 1);
        \something\set('instance2', 2);
    
        print \something\get('instance1');
        print \something\get('instance2');
    }


    С ООП можно написать:
    <?php
    class Something1 {
        private $someVariable;
    
        function set($value) {
            $this->someVariable = $value;
        }
    
        function get() {
            return $this->someVariable;
        }
    }
    
    class Something2 {
        private $someVariable;
    
        function set($value) {
            $this->someVariable = $value;
        }
    
        function get() {
            return $this->someVariable;
        }
    }
    
    $something1 = new Something1();
    $something1->set(1);
    
    $something2 = new Something2();
    $something2->set(2);
    
    print $something1->get();
    print $something2->get();

    и:
    <?php
    class Something {
        private $someVariable;
    
        function set($value) {
            $this->someVariable = $value;
        }
    
        function get() {
            return $this->someVariable;
        }
    }
    
    $something1 = new Something();
    $something1->set(1);
    
    $something2 = new Something();
    $something2->set(2);
    
    print $something1->get();
    print $something2->get();


    Если брать web приложение на php, задача которого состоит в том, чтобы сгенерировать html код (который будет отправлен браузеру) и предоставить возможность разделения приложения на модули, то ООП в качестве основы такого приложения может быть излишен, т.к. все модули будут выполнять лишь одно действие (возвращать html код) и им не потребуется сохнанять состояние между вызовами, т.к. результат работы модуля не будет больше изменяться во время вызова web приложения (модуль сгенерирует html и отправит его браузеру, а в браузере, где в javascript применяется ООП, этот html код уже будет изменяться во время работы).

    Без ООП серверная часть web приложения может выглядеть так:
    <?php
    namespace modules {
        function layout($title, $contentHtml, $footerHtml) {
            return '<!doctype html>
                <html>
                <head>
                    <meta charset="utf-8">
                    <title>' . htmlspecialchars($title) .'</title>
                </head>
                <body>
                    <div class="content">
                        ' . $contentHtml . '
                    </div>
    
                    <div class="footer">
                        ' . $footerHtml . '
                    </div>
                </body>
                </html>
            ';
        }
    
        function contacts() {
            return 'Адрес: ..., телефон: ...';
        }
    
        function copyright() {
            return '© Моя фирма';
        }
    }
    
    namespace {
        if (strtok($_SERVER['REQUEST_URI'], '?') === '/contacts') {
            print \modules\layout('Контакты', \modules\contacts(), \modules\copyright());
        }
    }

    А с ООП так (как можно заметить, модули реализовалы в виде классов, которые содержат только 1 метод, т.е. класс здесь излишен):
    <?php
    namespace modules {
        class Layout {
            public $title;
            public $contentHtml;
            public $footerHtml;
    
            public function execute() {
                return '<!doctype html>
                    <html>
                    <head>
                        <meta charset="utf-8">
                        <title>' . htmlspecialchars($this->title) .'</title>
                    </head>
                    <body>
                        <div class="content">
                            ' . $this->contentHtml . '
                        </div>
    
                        <div class="footer">
                            ' . $this->footerHtml . '
                        </div>
                    </body>
                    </html>
                ';
            }
        }
    
        class Contacts {
            public function execute() {
                return 'Адрес: ..., телефон: ...';
            }
        }
    
        class Copyright {
            public function execute() {
                return '© Моя фирма';
            }
        }
    }
    
    namespace {
        if (strtok($_SERVER['REQUEST_URI'], '?') === '/contacts') {
            $layout = new \modules\Layout();
            $layout->title = 'Контакты';
            $layout->contentHtml = (new \modules\Contacts())->execute();
            $layout->footerHtml = (new \modules\Copyright())->execute();
    
            print $layout->execute();
        }
    }


    Но если бы PHP использовался для разработки не серверного, а клиентского приложения, где сгенерированная визуальная часть сохранялась бы в оперативной памяти долгое время и пользовательские действия изменяли бы её, то использование ООП может быть удобным. Но опять же, ООП - это просто способ организации кода, в основе которого лежат всё те же подпрограммы (методы) и этот способ организации не всем может понравиться.
    Ответ написан
    Комментировать
  • Как вывести таблицу по годам и месяцам?

    @m-haritonov
    <?php
    $array[2001][1] = array('wp' => 1, 's' => 2, 'c' => 3);
    $array[2001][2] = array('wp' => 4, 's' => 5, 'c' => 6);
    $array[2001][3] = array('wp' => 7, 's' => 8, 'c' => 9);
    $array[2002][1] = array('wp' => 10, 's' => 11, 'c' => 12);
    $array[2002][2] = array('wp' => 13, 's' => 14, 'c' => 15);
    $array[2002][4] = array('wp' => 16, 's' => 17, 'c' => 18);
    ?>
    <table border="1">
    	<tr>
    		<th></th>
    		<?php foreach ($array as $year => $months): ?>
    			<th><?=htmlspecialchars($year)?></th>
    		<?php endforeach; ?>
    	</tr>
    	
    	<?php for ($monthNumber = 1; $monthNumber <= 12; $monthNumber++): ?>
    		<tr>
    			<th><?=htmlspecialchars($monthNumber)?></th>
    			<?php foreach ($array as $months): ?>
    				<?php if (isset($months[$monthNumber])): ?>
    					<td>wp: <?=htmlspecialchars($months[$monthNumber]['wp'])?>, s: <?=htmlspecialchars($months[$monthNumber]['s'])?>, c: <?=htmlspecialchars($months[$monthNumber]['c'])?></td>
    				<?php else: ?>
    					<td></td>
    				<?php endif; ?>
    			<?php endforeach; ?>
    		</tr>
    	<?php endfor; ?>
    </table>
    Ответ написан
  • Как правильно выносить "важные" файлы за пределы корня сайта (PHP)?

    @m-haritonov
    Вынесение за пределы корня сайта это частный случай правила "запретить доступ к системным файлам из браузера".

    Например, в ядре находится скрипт "add-user.php", в котором не осуществляется проверка прав доступа (т.к. такая проверка осуществляется в файле index.php, через который должны вызываться все другие скрипты с помощью PHP инструкции "include").

    Соответственно, оставлять доступ к этому скрипту напрямую из браузера нельзя (т.к. в таком случае злоумышленник сможет воспользоваться уязвимостью; особенно, если скрипт открытый и файлы ядра всем известны).

    Поэтому в папке со скриптами ядра создают специальный файл, указывающий веб-серверу, что напрямую предоставлять доступ к файлам в папке нельзя (в случае веб-сервера apache, это файл ".htaccess" с содержимым "deny from all") или вообще выносят файлы ядра за пределы той папки, файлы из которой доступны браузеру напрямую. Второй способ (вынесение файлов за пределы) считается более надёжным.
    Ответ написан
    Комментировать
  • Вопрос по функциям php (аргументы по умолчанию)?

    @m-haritonov
    Для этого необходима поддержка языком синтаксиса вызова функции наподобие:
    myfunc(1, 2, , 4);
    PHP такого синтаксиса, к сожалению, не предоставляет.

    UPDATE 2022:
    В PHP 8 появились именованные аргументы - https://www.php.net/manual/ru/functions.arguments.....
    Теперь это возможно:
    function test($a = 1, $b = 2) {
        print "a: $a, b: $b";
    }
    test(b: 5); // Выведет "a: 1, b: 5"
    Ответ написан
    Комментировать
  • Почему хранение serialized конфига предпочтительнее нативного php?

    @m-haritonov
    1. По-поводу скорости.

    Без акселераторов unserialize(file_get_contents('...')) у меня выполняется быстрее, чем include '...' примерно в 2-3 раза. Можно объяснить это тем, что при include выполняется парсинг PHP кода и, в отличии от unserialize, необходимо распознавать намного больше языковых конструкций (в include версии можно, например, в качестве значения указать вызов функции; в unserialize — нет).

    С акселератором (я использовал opcache) ситуация прямо противоположная — include '...' быстрее, чем unserialize(file_get_contents('...')) примерно в 2-3 раза.

    Итог: поскольку акселератор можно настроить так, чтобы он не влиял на корректность работы PHP скрипта, побеждает include.

    2. Безопасность.

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

    Также unserialize подходит, если конфигурационный файл поступает из ненадёжного источника (например, получается с другого сервера по HTTP и по пути может быть изменён злоумышленником; или, например, квалификации администратора недостаточно для редактирования PHP кода и он может допустить в нём ошибку в случае варианта с include).

    Итог: в номинации "безопасность" побеждает unserialize.
    Ответ написан
    Комментировать
  • Нужна ли веб-программисту высшая математика?

    @m-haritonov
    Математика вторична. Зная соответствующие спецификации и программные средства, но не зная математики — Вы сможете сделать сайт. Зная математику, но не зная соответствующих спецификаций и программных средств — нет. Математика, думаю, конечно же будет полезна... как и знание дизайна, типографии, библиотековедения, лингвистики, психологии, физики, схемотехники, истории, социологии, политологии и т.п.

    Одни говорят, что веб-программмисту нужна высшая математика... Один мне говорит, после заданного вопроса: "Ну попробуй без математики в веб пойти..."

    Попросите их сделать сайт (или показать готовые работы). Если результат будет положительным, то узнайте у них какие области математики они использовали в своей работе (и с нами поделитесь).
    Ответ написан
  • Как сделать возможность отметки о месте загружаемой фотографии?

    @m-haritonov
    Используйте JavaScript и Geolocation API:
    if ('geolocation' in navigator)
    {
    	navigator.geolocation.getCurrentPosition(function(location){
    		console.log(location.coords.latitude);
    		console.log(location.coords.longitude);
    		console.log(location.coords.altitude);
    		console.log(location.coords.accuracy);
    		console.log(location.coords.altitudeAccuracy);
    		console.log(location.coords.heading);
    		console.log(location.coords.speed);
    		console.log(location.timestamp);
    	});
    }
    Ответ написан
    Комментировать
  • Как нарисовать дизайн страницы для товара с четырьмя вариациями?

    @m-haritonov
    высота 1
     — вес 1
     — вес 2
    высота 2
     — вес 1
     — вес 2

    высота 1    высота 2
     — вес 1     — вес 1
     — вес 2     — вес 2

    '           вес 1     вес 2
    высота 1      —         —
    высота 2      —         —

    высота   вес
       — 1   — 1
       — 1   — 2
    Ответ написан
    Комментировать
  • Как передать из MS Excel на удаленный сервер с PHP?

    @m-haritonov
    Получить тело POST запроса в чистом виде в PHP можно следующим образом:
    print file_get_contents('php://input');
    Если же Вы хотите отправлять параметры вида "имя=значение", то необходимо поступить так, как написал @OLS.

    P.S.: почему Вы шлёте в теле POST запроса значение переменной postr, а в content-length указываете длину переменной zapros?
    Ответ написан
  • Как решить проблему с ооп сеттер?

    @m-haritonov
    Необходимо исправить код либо на вариант, предложенный @victorvsk, либо на такой вариант:
    class sys{
      static public $log = "<br />";
    
        static function log($newval)
        {static::$log.=$newval."<br />";}
    
        static function getlog()
        { return static::$log . "<br />";}
    }
    
    sys::log("установка");
    sys::getlog();


    Статические переменные и методы — это методы и переменные класса, а не объекта, поэтому обращение к ним происходит либо через имя класса (sys::$log), либо через ключевое слово self (self::$log; если происходит обращение к члену класса из самого класса), либо через ключевое слово static (static::$log; отличается от "self" лишь тем, что преобразуется в имя класса на стадии исполнения скрипта и потому подходит для использования при вызове метода из дочернего класса). Можно обращаться из методов объекта к статическим членам класса, но не наоборот (т.к. у объекта один класс и он известен объекту, а у класса может быть либо много объектов либо вообще ни одного).
    Ответ написан
    Комментировать
  • Правильное сохранение объектов javascipt?

    @m-haritonov
    1. Порядок выполнения инструкций будет следующим:
    var myjsonarr=new Array(); // 1
           $.getJSON(url, function (data) {
                    myjsonarr=data; // 5
            }); // 2
            console.log("мой вывод"); // 3
            console.log(myjsonarr); // 4


    Поэтому выполнять "console.log(myjsonarr)" надо в другом событии (например, во время клика по ссылке, который выполняется уже после того, как была вызвана callback функция, переданная в getJSON).

    2. Приведённый Вами кусок кода должен выводить в консоль не "undefined", а "[]".
    3. Если Вы хотите сохранить переменную просто для дальнейшего использования, то Вы правильно сохраняете переменную, просто console.log слишком рано:
    <!DOCTYPE html>
    <html>
    <head>
    	<script src="http://code.jquery.com/jquery-2.1.1.min.js" type="text/javascript"></script>
    	<script type="text/javascript">
    	$(function(){
    		// Присваивать массив данной переменной нужно лишь в случае,
    		// если ниже будет код "myjsonarr.push(data)" а не "myjsonarr = data"
    		var myjsonarr;
    		
    		$.getJSON('getjson.php', function (data) {
    			myjsonarr = data;
    		});
    		
    		// На данный момент новое значение ещё не присвоено переменной myjsonarr
    		console.log(myjsonarr);
    		
    		$('a').click(function(){
    			// А когда пользователь, подождав немного, кликнет на ссылку,
    			// переменная уже будет содержать новое значение
    			console.log(myjsonarr);
    		});
    	});
    	</script>
    </head>
    <body>
    	<a href="#">Вывести объект</a>
    </body>
    </html>


    Если же Вы хотите вызывать код построения таблицы и в вызове getJSON и из другого места, то можно поступить примерно следующим образом:
    <!DOCTYPE html>
    <html>
    <head>
    	<script src="http://code.jquery.com/jquery-2.1.1.min.js" type="text/javascript"></script>
    	<script type="text/javascript">
    	$(function(){
    		function showRows(data)
    		{
    			$("#jsondata").html("");
    			$.each(data.planer, function(i, planer){
    				var newRow = "<tr>"
    				+ "<td class='td_id'>" + planer.idPlaner + "</td>"
    				+ "<td class='td_date'>" + planer.DatePlaner + "</td>"
    				+ "<td class='td_time'>" + planer.TimePlaner + "</td>"
    				+ "</tr>";
    					
    				$(newRow).appendTo("#jsondata");
    			});
    		}
    		
    		var myjsonarr;
    		$('a').click(function(){
    			if (myjsonarr)
    				showRows(myjsonarr);
    			else
    			{
    				$.getJSON('getjson.php', function(data){
    					myjsonarr = data;
    					showRows(myjsonarr);
    				});
    			}
    		});
    	});
    	</script>
    </head>
    <body>
    	<a href="#">Вывести объект</a>
    	<table id="jsondata"></table>
    </body>
    </html>
    Ответ написан
    2 комментария
  • Поясните по поводу простейшего PHP счётчика

    @m-haritonov
    И чем может быть вызвано резкое увеличение его показаний.

    У кого-то залипла клавиша F5. :)
    Ответ написан
    Комментировать
  • ВерблюжьяНотация vs нотация_через_подчеркивание

    @m-haritonov
    Ориентируйтесь исключительно на технические требования. Если используемые Вами программные продукты не предъявляют технических требований к именованию идентификаторов, то используйте тот стиль, который Вам нравится (если, конечно, не требуется вести совместную разработку с другими разработчиками; тогда надо учитывать и их мнение). Ваше желание унифицировать правила именования идентификаторов (и выкинуть таким образом из головы лишнюю информацию) более чем естественно и правильно.

    P.S.: в Вашем решении я вижу только плюсы, т.к. я сам перешёл на подобное унифицированное именование идентификаторов (variableName, fieldName, constantName, ClassName, ConstructorFunctionInJavaScript, simpleFunctionInJavaScript, cssClassName, someNamespace-elseNamespace-cssClassName, но some-domain.com/some-page/some-subpage?some-param, /images/some-image.png).
    Ответ написан
    Комментировать
  • Существует ли альтернатива Denwer для windows?

    @m-haritonov
    AMPPS (в комплекте несколько версий PHP и доступно переключение версий через графический интерфейс).
    Ответ написан
    Комментировать
  • Почему глючит php apc?

    @m-haritonov
    Насколько я знаю, разработка APC прекращена и версии APC под PHP 5.4 являются beta. В качестве решение, думаю, лучше использовать альтернативный акселератор. Например, opcache, который поставляется вместе с PHP начиная с версии 5.5.
    Ответ написан
    1 комментарий
  • Как реализовано?

    @m-haritonov
    При заходе на сайт браузер передаёт по сети серверу порцию текстовой информации (называемой HTTP запросом), в которой, помимо прочего, содержатся строки вида:
    GET /PAGE/ HTTP/1.0
    Host: www.website.net

    А программа-сервер, когда получает такую порцию информации, может либо попытаться сопоставить переданную строку ("/PAGE/") с существующими файлами на сервере (и вернуть браузеру содержимое найденного файла для отображения), либо передать эту порцию информации в другую программу (например, PHP) и вернуть браузеру то, что вернёт эта программа.
    Ответ написан
    Комментировать
  • Проблема с созданием rewiterule

    @m-haritonov
    RewriteEngine on
    
    RewriteCond %{QUERY_STRING} ^(do=.*)$
    RewriteRule .* /%1?
    
    RewriteRule ^(.*?)&tag[0-9]+=(.*)$ /$1-$2 [N]
    RewriteRule ^do=(.*?)-(.*)$ /$1/$2 [R=302,L]

    Обращение к URL адресу:
    /?do=servers&tag1=50_craft&tag2=active_admins&tag3=airdrop&tag4=no_sleepers&tag5=oxide&tag6=sethome&tag7=tpa

    Приведёт к перенаправлению на:
    /servers/50_craft-active_admins-airdrop-no_sleepers-oxide-sethome-tpa
    Ответ написан
    31 комментарий
  • Переадресация с домена на субдомен, как реализовать на .htaccess?

    @m-haritonov
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^domen.ru$
    RewriteRule ^(.*)$ http://subdomen.domen.ru/$1 [R=301,L]


    Строчку с RewriteCond можно убрать, если требуется проводить редирект для всех запросов, поступающих на обработку данному .htaccess файлу.
    Ответ написан
    Комментировать
  • В чем проблема при установке PHP APC (mac)?

    @m-haritonov
    Если версия PHP >= 5.5.0, то возможно он конфликтует с акселератором opcache, который поставляется вместе с PHP начиная с версии 5.5.0.

    UPDATE: похоже, что разработка APC прекращена и с версией php 5.5 он не совместим: stackoverflow.com/questions/9611676/is-apc-compati...
    Ответ написан
  • Как изменить вид url сайта php?

    @m-haritonov
    Вообще, эта задача из двух частей:
    1. Получение URL адреса.
    2. Вывод HTML страницы с правильными URL адресами.

    Пример.

    Код для mod-rewrite, перенаправляющий все запросы в файл content.php:
    RewriteEngine on
    RewriteRule .* content.php


    Файл content.php:
    <?php
    // Эту часть кода можно реализовать и через mod-rewrite
    $parts = explode('/', substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?')));
    $_GET['page'] = $parts[2];
    $_GET['id'] = $parts[3];
    ?>
    <html>
    <head>
    	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
    	<title></title>
    </head>
    <body>
    	<?php /*
    	А код, отвечающий за то, ссылки на какие URL адреса будут в сгенерированной HTML странице, нужно размещать именно в PHP скрипте.
    
    	Либо использовать какой-нибудь модуль apache (например, mod_ext_filter), который будет заменять ссылки в отдаваемой пользователю HTML странице на нужные (а в PHP скрипте выводить ссылки вида "?page=news&id=5").
    	*/ ?>
    	<ul>
    		<li><a href="/page/<?=htmlspecialchars($_GET['page'])?>/<?=htmlspecialchars($_GET['id'])?>">Ссылка на текущую страницу</a></li>
    		<li><a href="/page/news/10">Ссылка на новость номер 10</a></li>
    	</ul>
    </body>
    </html>
    Ответ написан
    Комментировать