Проблемы с PHP при передаче кода из Windows в OS X

Недавно я купил новый MacBook Pro. До того, как я получил свой MacBook Pro, я работал над веб-сайтом на своем настольном компьютере. И теперь я хочу перенести этот код на свой новый MacBook Pro.

Проблема в том, что когда я передал код (я положил его на Dropbox и просто загрузил его на свой MacBook Pro), я начал видеть множество сообщений об ошибках в своем PHP-коде.

Сообщение об ошибке, которое я получаю:

Предупреждение. Невозможно изменить информацию заголовка – уже отправленные заголовки (вывод запущен в /some/file.php:1) в /some/file.php в строке 23

Я провел некоторое исследование по этому вопросу, и кажется, что эта ошибка чаще всего возникает из-за новой строки, простого пробела или любого вывода перед знаком <?php . Я просмотрел все места, где у меня есть файлы cookie, которые отправляются в HTTP-запросе, а также где я использую функцию header() . Я не обнаружил никаких выходных данных или пробелов, которые могли бы помешать и вызвать эту проблему.

Примечательно, что ошибка всегда говорит о том, что вывод запускается в строке 1. Что заставило меня задуматься, есть ли какие-то различия в кодировании в том, как операционные системы Mac OS X и Windows обрабатывают новые строки или пробелы? Или может ли передача Dropbox что-то испортить?

Код на одном из сайтов (login.php), который вызывает ошибку:

  <?php include "mysql_database.php"; login(); $id = $_SESSION['Loggedin']; setcookie("login", $id, (time()+60*60*24*30)); header('Location: ' . $_SERVER['HTTP_REFERER']); ?> 

функция входа:

 function login() { $connection = connecttodatabase(); $pass = ""; $user = ""; $query = ""; if (isset($_POST['user']) && $_POST['user'] != null) { $user = $_POST['user']; if (isset($_POST['pass']) && $_POST['pass'] != null) { $pass = md5($_POST['pass']); $query = "SELECT ID FROM Anvandare WHERE Nickname='$user' AND Password ='$pass'"; } } if ($query != "") { $id = $connection->query($query); $id = mysqli_fetch_assoc($id); $id = $id['ID']; $_SESSION['Loggedin'] = $id; } closeconnection($connection); } 

Полная ошибка:

 Warning: Cannot modify header information - headers already sent by (output started at /Users/name/GitHub/website/login.php:1) in /Users/namn/GitHub/website/login.php on line 9 

Related of "Проблемы с PHP при передаче кода из Windows в OS X"

Проверьте, есть ли перед вашим тегом открытия php пробелы. Также попробуйте сохранить файл из блокнота ++ с использованием оконных окон (crlr). (Edit> EOL Conversion> Формат Windows)

Примечательно, что ошибка всегда говорит о том, что вывод запускается в строке 1. Что заставило меня задуматься, есть ли какие-то различия в кодировании в том, как операционные системы Mac OS X и Windows обрабатывают новые строки или пробелы? Или может ли передача Dropbox что-то испортить?

Не переделывайте код или не беспокоитесь о вызовах header() или даже о файлах cookie. Это не проблема.

Проблема в том, что окончание строк Windows отличается от окончаний линии Mac. Подробнее здесь .

Различные операционные системы используют разные символы для обозначения конца строки:

  • Unix / Linux / OS X использует LF (строка, '\ n', 0x0A)
  • Маки до OS X используют CR (возврат каретки, '\ r', 0x0D)
  • Windows / DOS использует CR + LF (возврат каретки, за которым следует линия, '\ r \ n', 0x0D0A)

И то, что происходит в таких случаях, как форматирование страницы, заставляет парсер PHP в Apache задушить файлы. Возможно отправка контента в браузер до того, как вы намереваетесь при вызове header() или настройке файлов cookie. С технической точки зрения окончание завершенных строк заставляет «заголовок» отправляться, потому что сам файл выводит данные в браузер непреднамеренно.

Решение может заключаться в том, чтобы избежать использования Dropbox и просто скопировать файлы на флэш-накопитель и перенести его таким образом. Это идея, но я не уверен, что Dropbox был виновником этого. Это означает, что проблема может сохраниться даже при копировании файлов на флешку.

Или если это не сработает, сделайте так, как говорится в статье, и скачайте хороший инструмент для редактирования текста, например TextWrangler . Просто загрузите файлы в TextWrangler и затем вручную измените окончание строки, чтобы они были Mac (CR) и сохранили файлы.

Другим долгосрочным решением этой проблемы может быть использование системы управления версиями, такой как git сочетании с учетной записью GitHub для управления вашим кодом. Преимущество заключается в том, что нажатие кода на GitHub и извлечение кода из GitHub, сам процесс будет иметь дело с кросс-платформенными линиями, заканчивающими головные боли. И вам не нужно беспокоиться о непреднамеренных странностях, вызванных прямой копией файлов для службы, такой как DropBox.

Но опять же, довольно убедительно, это не имеет никакого отношения к Dropbox. Все о концах строк Windows отличается от окончаний строк в Mac OS X.

EDIT: Есть несколько интересных идей о том, как обрабатывать массовое преобразование окончаний строк Windows в конец строки Mac OS X в Mac OS X Hints . Наиболее интересным является использование zip и unzip для облегчения процесса. Я не пробовал это, так остерегаюсь! Но это похоже на то, что стоит тестировать, поскольку последние строки указывают, BTW, это флаг «-a» для распаковки, что приводит к тому, что файлы ascii преобразуют свои строки. :

Я всегда использовал следующее (в файле с именем fixascii ):

 #!/bin/sh zip -qr foo.zip "$@" && unzip -aqo foo.zip && rm foo.zip 

И затем выполните его как:

 fixascii [files or directories to convert] 

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

Я видел слишком много раз, когда кто-то искажал тонну изображений и других двоичных файлов, пытаясь исправить линейные окончания в текстовых файлах с помощью dos2unix или tr в сочетании с find, но не смог убедиться, что обрабатывались только текстовые файлы. Разархивируйте, какие файлы являются ascii, преобразуют их и оставляют только двоичные файлы.

BTW, это флаг «-a» для распаковки, что приводит к тому, что файлы ascii преобразуются в окончание строк.

А затем посмотрите официальную страницу man для unzip в опции -a (конвертировать текстовые файлы); акцент мой:

Обычно все файлы извлекаются точно так, как они хранятся (как «двоичные» файлы). Параметр -a вызывает файлы, идентифицированные zip, в виде текстовых файлов (те, у которых метка «t» в списках zipinfo, а не «b»), автоматически извлекаются как таковые, конвертирование окончаний строк, символов конца файла и символа при необходимости. (Например, файлы Unix используют линейные каналы (LF) для конца строки (EOL) и не имеют маркера конца файла (EOF), Macintoshes использует возврат каретки (CR) для EOL, а большинство операционных систем для ПК используют CR + LF для EOL и control-Z для EOF. Кроме того, в мэйнфреймах IBM и в Мичиганской терминальной системе используется EBCDIC, а не в более общем наборе символов ASCII, а NT поддерживает Unicode.) Обратите внимание, что zip-идентификация текстовых файлов отнюдь не является идеально; некоторые «текстовые» файлы могут быть двоичными и наоборот. unzip поэтому печатает '' [текст] '' или '' [binary] '' как визуальную проверку для каждого файла, который извлекает при использовании опции -a. Параметр -aa заставляет все файлы извлекаться как текст независимо от предполагаемого типа файла.

EDIT: Кроме того, если у вас есть доступ к машине Linux, вам может dos2unix проверка dos2unix . Подробнее здесь . И нашел еще один вопрос о переполнении стека.

Наконец нашел простой способ исправить это! Я просматривал файл php.ini, когда сталкивался с опцией, которая называется: auto_detect_line_endings, и имеет значение по умолчанию: Off.

Описание этой опции:

 ; If your scripts have to deal with files from Macintosh systems, ; or you are running on a Mac and need to deal with files from ; unix or win32 systems, setting this flag will cause PHP to ; automatically detect the EOL character in those files so that ; fgets() and file() will work regardless of the source of the file. ; http://php.net/auto-detect-line-endings 

Это именно то, что я искал!

Я просто использовал функцию ini_set () в начале моего файла базы данных (который я загружаю на каждую php-страницу) и, похоже, решил проблему для меня! Функция ini_set () также возвращает параметр, измененный в файле php.ini, в нормальный режим, когда скрипт завершен.

Полная строка функции ini_set (), которую я использовал:

 ini_set("auto_detect_line_endings", true); 

Спасибо всем за помощь!

Дополнительная информация о функции ini_set () здесь: функция ini_set ()

Дополнительная информация об опции auto_detect_line_endings здесь: Опция автоматического определения конца строки