WordPress как на ладони
Недорогой хостинг для сайтов на WordPress: wordpress.jino.ru

Исполняемый php код в записях WordPress

Бывают ситуации, когда очень удобно использовать весь потенциал языка программирования PHP в тексте при написании статей. Речь идет о статьях для WordPress.

Все кто пробовал написать какой либо php код в посте, в надежде что он сработает, знают, что WordPress воспринимает такой код как простой текст. Однако иногда бывает удобно запустить, например, какой-нибудь цикл вывода прямо в тексте при написании статьи, ведь контент такой статьи будет обновляться динамически. Другим примером может служить возможность вызывать готовые функции в посте, в случае необходимости или, например, вставить какой-нибудь php файл в текст поста по средствам php функции require():

require 'my_script.php';

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

Итак, чтобы реализовать возможность вставлять исполняемые PHP скрипты в текст статьи / поста или статической страницы, нужно добавить в уже, наверное, до боли знакомый нам файл темы functions.php следующий код:

## Исполняемый PHP код в контенте записи WordPress.
## [exec]PHP_код[/exec]
##
## @version: 1.0
if( 'Исполняемый PHP код в контенте' ){

	add_filter( 'the_content', 'content_exec_php', 0 );

	function content_exec_php( $content ){
		return preg_replace_callback( '/\[exec( off)?\](.+?)\[\/exec\]/s', '_content_exec_php', $content );
	}

	function _content_exec_php( $matches ){

		if( ' off' === $matches[1] ){
			return "\n\n<".'pre>'. htmlspecialchars( $matches[2] ) .'</pre'.">\n\n";
		}
		else {
			eval( "ob_start(); {$matches[2]}; \$exec_php_out = ob_get_clean();" );
			return $exec_php_out;
		}

	}

}

После того, как код добавлен станет возможным использовать в статьях конструкцию такого вида:

[exec]php код[/exec]

Например:

[exec]
// Комментарий
global $wp_version;
echo "Текущая версия WP: $wp_version";
[/exec]

Чтобы отключить выполнение кода, можно использовать следующую конструкцию. Она выведет просто код, как если бы мы вставили php код как текст.

[exec off]php код[/exec]

Важно о защите

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

Чтобы обезопасить себя от возможных пагубных последствий этого хака, можно сделать следующую простую защиту (то что сразу пришло мне в голову): включать исполнение конструкции [exec]php код[/exec], только в том случае, если, например, у поста есть какое-либо произвольное поле или, скажем, пост написан в 00 минут. Естественно только вы будете знать эту хитрость при которой код будет исполняться и соответственно только вам будет доступна возможность вставить php код в статью.

Получите много друзей на страницу ВК для того, чтобы сделать ее максимально популярной в сети. Выводите свой аккаунт в топ поиска Контакта с недорогими услугами от представленного сайта. Здесь Вам будут доступны такие ресурсы, как: подписчики в группу, лайки, репосты, просмотры записей и т. д. Успейте сделать максимально выгодную покупку уже сейчас.

85 комментов
Полезные 6 Вопросы 4 Все
  • Алексей blogocar.net

    Привет! Попробовал вставить вот такое:

    <?php if ($_SERVER["REQUEST_URI"] == '/2010/03') { ?>
    <a href="http://site.ru/">site</a>
    <?php } else {?> site<?php } ?>

    Это чтобы ссылка была только на .../2010/03 а при других вариантах просмотра не было.
    Для этого использовал такую констуркцию:

    [exec] if ($_SERVER["REQUEST_URI"] == '/2010/03') { ?>
    <a href="http://site.ru/">site</a>
    <?php } else {?> <?php } [/exec]

    В результате ругается

    Parse error: syntax error, unexpected $end in путь/functions.php : eval()'d code on line 1

    Подскажи, пожалуйста, может как-то можно по-другому это реализовать?

    Ответить8.9 лет назад #
    • Kama7770

      Не знаю точно в чем причина, но конструкция else {?> <?php } очень подозрительная.

      Я бы написал как-то так:

      [exec] 
      if ($_SERVER["REQUEST_URI"] == '/2010/03')
      	echo '<a href="http://site.ru/">site</a>';
      else 
      	echo 'site';
      [/exec]
      Ответить8.9 лет назад #
  • Артем www.krasnoyarsk-fire.ru

    Попробую ваш код! А напишите, как изменить функцию, чтобы этот вставленный php исполнялся только после добавления произвольного поля? Спасибо!

    Ответить8.9 лет назад #
    • Kama7770

      Для этого сделаем проверку на наличие произвольного поля, скажем, exec у статьи, в функции inline_php() — добавим в начало функции строки:

      function inline_php($content){
      	global $post;
      	if( !isset(get_post_meta($post->ID, 'exec', true)) )
      		return $content;
      	...

      Теперь, создадим произвольное поле exec и укажем в нем что угодно, для того чтобы код выполнялся в посте. Если такого поля не будет у поста, код выполнятся не будет.

      Ответить8.9 лет назад #
  • Артем www.krasnoyarsk-fire.ru

    А у меня такая проблема:

    Вот код. Кэширует страницу, и если срок жизни истек, включает файл, который генерирует новый html:

    //Начало кэширования
    $start = microtime();
    $filename = 'http://site.ru/sait/Trinity/cache/'.md5($_SERVER['REQUEST_URI']).'.html';
    $cached = false;
    $time = 21600; // Время кеша в секундах (6*60*60 = 6 часов)
    $stat = 0; // Установите 1 для вывода времени загрузки страницы (по умолчанию 0)
    
    if (file_exists($filename)) {
    	if ((time()-filemtime($filename))<$time) {
    		$cached = true;
    	} else {
    		unlink($filename);
    		$cached = false;
    	}
    }
    
    if ($cached) {
    	readfile($filename);
    } else {
    	ob_start();
    
    	include "http://www.*********.ru/********.php";
    
    	// Конец кэширования
    	$text = ob_get_clean();
    	$fh = fopen($filename, 'w+');
    	fwrite($fh, $text);
    	fclose($fh);
    	echo $text;
    }
    $finish = microtime();
    if ($stat==1) echo $finish-$start;

    Само по себе все работает, а вот на странице ничего не появляется! Только текст, который выше и ниже кода

    (файл, который в include,идет на страницу в Инете (статистика), находит там данные, записывает в виде массива, потом через For..as записывает элементы массива в ячейки таблицы).

    -(

    Ответить8.9 лет назад #
    • Kama7770

      Судя по всему глюк в строке

      include "http://www.*********.ru/********.php";

      . Она должна полностью сгенерировать страницу и по идее должна быть как в index.php в корне WordPress:

      define('WP_USE_THEMES', true);
      
      /** Loads the WordPress Environment and Template */
      require('./wp-blog-header.php');

      Как минимум файл который там указан, должен сам по себе что-то выводить на экран. То что он выводит и будет записано в файл кэша.

      Еще, возможно причина в указании пути до файла, там нужен вроде абсолютный пусть, а не через http:// что-то вроде: /home/k/site.ru/public_html/file.txt. Имею ввиду в include() и readfile().

      Ответить8.9 лет назад #
  • Александр roscredit.msk.su

    Доброго вечера, Kama
    Подскажите, пожалуйста.
    В общем, я всё пробую реализовать кольцевую перелинковку у себя на сайте.

    Я вставил код функции "Предыдущие записи" в functions.php, а затем добавил туда же код, указанный в текущей статье.

    Размышлял и делал так:

    1. Есть функция перелинковки, она работает. Но почему-то у меня в единичной записи - аж до 4-х блоков ссылок.
    2. Хорошо, подумалось мне, и решил вызывать этот блок ссылок прямо из записей
    3. Залез в гугл, и по запросу вышел на этот же сайт smile . Скопировал код и вставил в функшнз.пхп
    4. Открыл запись на редактирование, вставил туда

      [exec]<ul>
      <?php kama_previous_posts (6, '{date:j.M.Y} - {a}{title}{/a} (Комментариев: {comments})'); ?>
      </ul>[/exec]
    5. Получил ошибку
      Parse error: syntax error, unexpected '<' in /home/aldex/roscredit.msk.su/wp-content/themes/roscredit/functions.php(983) : eval()'d code on line 1
    6. Стал экспериментировать с тем, что у меня между
      [exec][/exec]

      находится. Всё равно получаю эту же ошибку. Последней попыткой было

      [exec]echo 'Просмотров: ';[/exec]

    Всё равно ошибка. В последнем случае мне просто было любопытно - отобразится ли само это слово...

    Что я делаю не так?

    Ответить8.8 лет назад #
    • Kama7770

      Все вроде очень даже так! В первом случае логично что была эта ошибка: html теги то зачем юзать там их за [exec][/exec] нужно...

      Не может быть такая же ошибка в случае

      [exec]echo 'Просмотров: ';[/exec]

      . Может у вас там какой-то кэш хитро-мудрый работает, хотя тоже вряд ли. unknw

      Ответить8.8 лет назад #
      • Александр roscredit.msk.su

        Насчёт кэша вы оказались правы. Ошибка при попытке вывести

        [exec]echo 'Просмотров: ';[/exec]

        исчезла, после того как я отключил Quick Cache Версия 110720 | Автор: PriMoThemes.com / WebSharks, Inc.

        И теперь у меня новая ошибка с выводом этой функции :))

        Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING in /home/aldex/roscredit.msk.su/wp-content/themes/roscredit/functions.php(983) : eval()'d code on line 1

        Поэкспериментирую дальше...

        Ответить8.8 лет назад #
  • Александр roscredit.msk.su

    Уважаемый Kama, покажите, пожалуйста, пример корректного кода между [exec][/exec]. Думаю, что у меня проблема не в вордпрессе, а в недостатке серого вещества.

    Я хочу вывести в теле статьи ссылки на последние 4 статьи блога, если несложно, подскажите, что должно быть в [exec]вот тут[/exec], чтобы эти 4 ссылочки появились?

    Спасибо за внимание smile

    Ответить8.7 лет назад #
  • Артем www.krasnoyarsk-fire.ru

    Александр, я использовал на страницу 404 вот этот код:

    get_archives ('postbypost', 5);

    соответственно, 5 - количество постов
    только я использовал его непосредственно в файле, но наверное должен сработать и так?

    Ответить8.7 лет назад #
    • Александр roscredit.msk.su

      Вау. Классно smile Спасибо. :))

      Ответить8.7 лет назад #
  • Артем www.krasnoyarsk-fire.ru

    и кстати, я вообще в вордпрессе сделал свою страницу 404.php . Взял код с index.php в редакторе темы, и вставил туда свои дополнения - кнопку возврата на прошлую страницу, форму поиска и пять последних постов...

    на странице был следующий код:

    include 'http:/www.tolko-delo.ru/подкаталог/файл.php';

    Он перестал работать. Как я выяснил, это из-за настроек PHP на сервере (читал что-то о переходе с PHP4 на PHP5)... Удалось запустить вот таким кодом:

    include $_SERVER['DOCUMENT_ROOT'] . '/подкаталоги/файл.php';
    Ответить8.7 лет назад #
  • @ shin

    спасибо, пригодилось. хотелось сделать это без громоздкого плагина.

    Ответить8.5 лет назад #
  • Александр

    Уважаемый Kama!
    Огромное спасибо Вам за пост, сделано грамотно и красиво! good
    Только проверку на наличие произвольного поля сделать по Вашему не получилось, php выдавал Errors parsing в этой строке:

    if( !isset(get_post_meta($post->ID, 'exec', true)) ) return $content;

    Я переписал немного Вашу функцию, и все заработало на ура! Может кому-то пригодится:

    function inline_php($content){
    	global $post;
    	if( get_post_meta($post->ID, 'exec', true)<>"" ) {
    	$content = preg_replace_callback('/\[exec\]((.|\n)*?)\[\/exec\]/', 'exec_php', $content);
    	$content = preg_replace('/\[exec off\]((.|\n)*?)\[\/exec\]/', '$1', $content);
    	return $content;
    	}
    	else {return $content;}
    }
    Ответить8.1 лет назад #
  • Дмитрий agehack.pro

    Спасибо! Очень ценно, особенно советы по безопасности

    Ответить8 лет назад #