Бедный человек CMS

  • Автор темы Boris2014
  • 46
  • Обновлено
  • 15, May 2024
  • #1
Привет. Я пытаюсь собрать воедино несколько фрагментов кода, чтобы создать базовую CMS для бедняков. Я ищу эти функции:
  • Пагинация.
  • Полные дружественные URL-адреса.
  • Статьи.
  • Теги.
  • Плоские файлы вместо базы данных.


Некоторые сомнения Проблема со списком страниц:
  • Элемент 1 имеет URL-адрес /articles/0 вместо /articles.
  • Элемент 2 имеет URL-адрес /articles/1 вместо /articles/2.


Как лучше всего добавить систему тегов? статьи имеют идентификатор.

Я подумал о создании файла с именем tags.txt, в котором теги будут присваиваться каждому идентификатору статьи следующим образом:
 

<?php

function template_header(

$pageTitle = false,

$keywords = false,

$description = false

) {

echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

"[URL='https://lumtu.com/yti/dk55kdGRodHRwOi8vdzMub3JnL1RSL3hodG1sMS9EVEQveGh0bWwxLXN0cmljdCjlm']http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd[/URL]">

<html

xmlns="[URL='https://lumtu.com/yti/b0hh0bWxodHRwOi8vdzMub3JnLzE5OTkveGvkT']http://www.w3.org/1999/xhtml[/URL]"

lang="en"

xml:lang="en"

><head>

<meta

http-equiv="Content-Type"

content="текст/html; кодировка = utf-8"

/>

<meta

http-equiv="Content-Language"

contrut="en"

/>

<meta

name="viewport"

content="ширина = ширина устройства; начальный масштаб = 1,0"

/>';

if ($keywords) echo '

<meta

name="keywords"

content="', $ключевые слова, '"

/>';

if ($description) echo '

<meta

name="description"

content="', $описание, '"

/>';

echo '

<link

type="text/css"

rel="stylesheet"

href="', ROOT_HTTP, 'theme/screen.css"

media="screen,projection,tv"

/>

<title>

', ($pageTitle ? $pageTitle . ' - ' : ''), ' Site Title

</title>

</head><body>

<div id="top" class="widthWrapper">

<h1>

Site Title

<span><!-- image replacement --></span>

</h1>

<ul id="mainMenu">

<li><a href="', ROOT_HTTP, '">Home</a></li>

<li><a href="', ROOT_HTTP, 'articles">Articles</a></li>

<li><a href="', ROOT_HTTP, 'about">About</a></li>

<li><a href="', ROOT_HTTP, 'contact">Contact</a></li>

</ul>

<hr /><!-- remove if content starts with numbered heading -->

<div id="contentWrapper"><div id="content">';

// using double-wrapper for fluid content-first columns

} // template_header

function template_footer($extrasFile = false) {

echo '

<!-- #content, #contentWrapper --></div></div>

<div id="extras">';

// any static / common to all pages sidebar stuff here

if ($extrasFile) include($extrasFile . '.php');

echo '

<!-- #extras --></div>

<div id="footer">

Disclaimer / Other footer stuff here

<!-- #footer --></div>

<!-- #top.widthWrapper --></div>

';

} // template_footer

?>

Код (разметка): а затем обработка его с помощью PHP.

Это хорошая идея?

Мои познания в программировании очень ограничены — лишь немного базового C. Любая помощь приветствуется. Фактический код Большая часть взята из материалов @deathshadow на нескольких форумах и кода его веб-сайта Скрытая информация :: Авторизуйтесь для просмотра »
Benson. Я внес некоторые изменения.
index.php
  <?php require_once('theme/index.template.php'); template_header( false, // don't show "pageTitle - Site title" 'seven,or,eight,words,that,exist,in,body', // keywords 'A short natural language description describing the site' ); require_once('libs/articles.lib.php'); require_once('libs/paginate.lib.php'); if (request::value(2)!='') { echo '<h1>Error 404</h1>'; http_response_code(404); template_footer(); die(); } echo ' <h2>Articles</h2> <p> This is where your page unique content would go! </p> '; //$page = isset($_GET['page']) && is_numeric($_GET['page']) ? $_GET['page'] : 0; $page = request::value(1); $paginator = new Paginate('', $page, newsNumber()); $paginator->show(); $limits = $paginator->getLimits(); news(false, $limits[':offset'], $limits[':limit']); template_footer(); ?> 
Код (разметка): библиотеки/articles.lib.php
  <?php /* gzip.lib.php Version 1.0 Jason M. Knight, August 2009 Uses a proper exit handler to provide automation of gzip compression of our PHP output with little if any headaches.


ASSUMES: CONTENT_ENCODING contains either 'x-gzip' or 'gzip' based on the value in HTTP_ACCEPT_ENCODING.

See "defines.php" to see how this is set.

If STRIP_WHITESPACE is defined whitespace between tags or at the start of lines will be stripped, as will comments.

Whitespace between a tag and CDATA or between attributes will be left alone.



*/ ob_start(); ob_implicit_flush(0); register_shutdown_function(function() { header('Content-Encoding: ' . CONTENT_ENCODING); $contents = ob_get_contents(); if (defined('STRIP_WHITESPACE')) $contents = preg_replace( ['#<!--.*?-->#s', '#>\s+<#', '#\n\s+<#'], ['', '><', '<'], $data ); ob_end_clean(); echo "\x1f\x8b\x08\x00\x00\x00\x00\x00", substr(gzcompress($contents, 6), 0, -4); }); [/B]
Код (разметка): библиотеки/paginate.lib.php
  <?php class Paginate { private $perPage, $maxShow, $middle, $href, $current, $lastPage; public function __construct( $href = '/', $current = 0, $total = 0, $perPage = 5, $maxShow = 5 //, //$field = 'page' ) { //$this->href = ' href="' . $href . ( // strpos($href, '?') === FALSE ? '?' : '&amp;' //) . $field . '='; $this->href = ' href="'; $this->current = $current; $this->total = $total; $this->perPage = $perPage; $this->maxShow = $maxShow; $this->middle = floor($maxShow / 2); $this->lastPage = floor(($total - 1) / $perPage); } // Paginate::__construct public function getLimits() { return [ ':offset' => $this->current * $this->perPage, ':limit' => $this->perPage ]; } private function anchorLine($page, $text, $title = false, $rel = false) { $tag = $page < 0 ? 'span' : 'a'; echo ' <li><', $tag, ( $page >= 0 ? $this->href . $page . '"' : '' ), ( $page == -2 ? ' class="disabled"' : '' ), ( $title ? ' title="' . $название.





'"' : '' ), ( $rel ? ' rel="' . $rel . '"' : '' ), '>', $text, '</', $tag, '></li>'; } public function show() { if ($this->total <= $this->perPage) return; echo ' <ul class="pagination">'; if (($this->lastPage > 0) && ($this->current > 0)) { $this->anchorLine(0, 'First'); $this->anchorLine($this->current - 1, '&#x25C0;', 'Previous Page', 'prev'); } else { $this->anchorLine(-2, 'First'); $this->anchorLine(-2, '&#x25C0;'); } if ($this->lastPage >= $this->maxShow) { $counter = ($this->current <= $this->middle) ? 0 : $this->current - $this->middle; $endPage = $counter + $this->maxShow; if ($endPage > $this->lastPage) { $counter = $this->lastPage - $this->maxShow; if ($counter < 0) $counter = 0; $endPage = $this->lastPage; } } else { $counter = 0; $endPage = $this->lastPage; } while ($counter <= $endPage) $this->anchorLine( $counter == $this->current ? -1 : $counter, ++$counter ); if (($this->lastPage > 0) && ($this->current < $this->lastPage)) { $this->anchorLine($this->current + 1, '&#x25B6;', 'Next Page', 'next'); $this->anchorLine($this->lastPage, 'Last'); } else { $this->anchorLine(-2, '&#x25B6;'); $this->anchorLine(-2, 'Last'); } echo ' </ul>'; } // Paginate::show } // Paginate
Код (разметка): библиотеки/gzip.lib.php
  <?php function newsNumber() { global $article_dir,$users,$txt_convert; $articles=scandir($article_dir,1); return (count($articles)-2); // Number of files except . and .. } function news($mode,$start,$count) { global $article_dir,$users,$txt_convert; $articles=scandir($article_dir,1); $t=$start; $end=$t+$count; if ($end>count($articles)) { $end=count($articles); } while ($t<$end) { switch ($articles[$t]) { case '.': case '..': break; default: list($id, $date,$subject,$author)=explode('_',$articles[$t]); //$author=$users[str_replace('.article.txt','',$author)]; $author = str_replace('.article.txt','',$author); $date=date("d F Y", mktime(0,0,0, substr($date,4,2), substr($date,6,2), substr($date,0,4) ) ); $contents=str_ireplace($txt_convert['in'],$txt_convert['out'], trim(file_get_contents($article_dir.'/'.$articles[$t])) ); echo ' <div class="article"> <h3> '; echo ' ',$subject,' <span>',$date,'</span>'; echo ' </h3> '; echo '<div class="article_body">'; echo ' <p>',$contents,'</p> <div class="author">Author: ',$author,'</div> <div class="id">ID: ',$id,'</div> '; echo '</div>'; echo ' </div> '; break; } $t++; } } ?> 
Код (разметка): статика/articles.php
  <?php // start compression first since it does a heading and starts buffering define('CONTENT_ENCODING', (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'x-gzip') !== false) ? 'x-gzip' : (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) ? 'gzip' : false ); if (CONTENT_ENCODING) include('libs/gzip.lib.php'); function cleanPath($path) { return trim(str_replace(['\\','%5C'],'/',$path),'/'); } function bomb($title, $message) { template_header('ERROR - ' . $title); echo ' <div id="fatalError"> <h2> ',$title,' </h2> <p>',$message,'</p> <p><strong>EXECUTION HALTED</strong></p> <!-- #fatalError --></div>'; template_footer(); die; } final class request { private static $data = []; public static function value($index = 0, $clean = false) { if ($index === true) { $index = 0; $clean = true; } if (count(self::$data) == 0) { $path = cleanPath(parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH)); if (strpos($path,'..')) bomb('hackingDetected', 'uptreeFail'); $path = substr($path, strlen(HTTP_ROOT) - 1); self::$data = empty($path) ? ['default'] : explode('/',$path); foreach (self::$data as &$p) $p = urldecode($p); } return isset(self::$data[$index]) ? ( $clean ? cleanName(self::$data[$index]) : self::$data[$index] ) : false; } } // class request.



request::value(0) return first parameter.



/* define('SCRIPT_PATH', cleanPath(pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_DIRNAME))); define('ROOT_HTTP', '/' . SCRIPT_PATH . (SCRIPT_PATH == '' ? '' : '/')); define('ROOT_LOCAL', pathinfo($_SERVER['SCRIPT_FILENAME'], PATHINFO_DIRNAME) . '/'); define('HOST_PROTOCOL', 'http' . ( isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] != 'off') ? 's' : '' ) . '://'); define('HOST_HTTP', HOST_PROTOCOL . $_SERVER['HTTP_HOST']); define('BASE_HTTP', HOST_HTTP . ROOT_HTTP); define('PATH_HTTP', '/' . parse_url(cleanPath($_SERVER['REQUEST_URI']), PHP_URL_PATH) ); define('FULL_HTTP', HOST_HTTP . PATH_HTTP); define('CANONICAL_PATH', request::getPath()); define('CANONICAL_URI', HOST_PROTOCOL . WORKING_DOMAIN . '/' . CANONICAL_PATH); define('CANONICAL_URIe', urlencode(CANONICAL_URI)); */ define('SCRIPT_PATH', cleanPath(pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_DIRNAME))); define('ROOT_HTTP', '/' . SCRIPT_PATH . (SCRIPT_PATH == '' ? '' : '/')); define('SCRIPT_FILENAME',cleanPath($_SERVER['SCRIPT_FILENAME'])); define('HTTP_ROOT',str_ireplace('index.php','',$_SERVER['PHP_SELF'])); define('LOCAL_ROOT',str_ireplace('index.php','',SCRIPT_FILENAME)); define('HTTP_THEME', HTTP_ROOT . 'theme/'); require_once('setup.php'); switch(request::value()) { case 'article': require_once('theme/article.template.php'); break; default: // then it must be the index, a static or Not Found require_once( is_file($targetFile = 'statics/' . request::value() . '.php') ? $targetFile : 'statics/404.php' ); } ?>
Код (разметка): тема/index.template.php
  1 tag1,tag2,tag3 2 tag2 3 tag4,tag5 
Код (разметка): Ссылки на код, который я использую

Boris2014


Рег
10 Mar, 2014

Тем
1

Постов
3

Баллов
13
  • 18, May 2024
  • #2
Если у вас есть доступ к Apache, вы можете включить mod_spelling

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

ahmadeev


Рег
13 Mar, 2016

Тем
0

Постов
1

Баллов
1
  • 01, Jun 2024
  • #3
Я очень рад изучать PHP, это гораздо мощнее и приятнее, чем возиться с фреймворками или генераторами статических сайтов.

Я немного почистил код, а также исправил ошибку в static/article.php.

Теперь он адаптирован к utf-8. Хотя мне все еще нужно доработать код, базовые функции пока работают нормально.
статика/article.php
 

<?php

function friendize_url($url) {

$unwanted_array = array('Š'=>'S', 'š'=>'s', 'Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',

'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U',

'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c',

'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', '?'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o',

'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y',' '=>'_' );

return(strtr($url, $unwanted_array));

}

?>

Код (разметка): библиотеки/url.lib.php
  <?php require_once('libs/articles.lib.php'); require_once('libs/paginate.lib.php'); $number_of_articles = newsNumber(); $number_of_pages = ceil($number_of_articles / 5); // 5 articles per page $articles=scandir($article_dir,1); $t=0; $found=0; while (!$found && $t < $number_of_articles ) { list($date,$subject,$author)=explode('_',$articles[$t]); $slug = str_replace(' ', '_', strtolower($subject)); if (friendize_url(utf8_encode($slug)) == request::value(1)) $found++; $t++; } if (!$found) { require_once('theme/index.template.php'); not_found(); // 404 error.





} else { $slug = str_replace(' ', '_', strtolower($subject)); $contents = explode('<!-- | -->',str_ireplace($txt_convert['in'],$txt_convert['out'], trim(file_get_contents($article_dir.'/'.$articles[$t-1]))) ); $author = str_replace('.article.txt','',$author); isset($contents[2]) ? $keywords=$contents[2] : $keywords=false; isset($contents[3]) ? $description=$contents[3] : $description=false; require_once('theme/index.template.php'); template_header( utf8_encode($subject), // if isset show "pageTitle - Site title" $keywords, // if isset show keywords $description ); echo ' <div class="article"> <h2> ',utf8_encode($subject),' <br> <small> por ',utf8_encode($author),' </small> </h2> <div class="article_body"> ',$contents[0].$contents[1],' </div> </div> '; } template_footer(); ?>
Код (разметка): мне по-прежнему приходится генерировать ошибки 404 для каждой несуществующей страницы сайта, чтобы избежать проблем с дублированием контента.
 

joni-jo


Рег
21 May, 2013

Тем
1

Постов
4

Баллов
14
  • 04, Jun 2024
  • #4
Да... это моя точка зрения.

Все ссылки всегда должны быть в нижнем регистре.

Особенно на своем сайте.

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



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



Однако тогда вы потеряете возможность иметь разные файлы с разными типами в именах - в файловых системах, где вы можете проводить такие различия - то есть, что существует разница между ThisIsAFile.txt и thisisafile.txt. Следовательно, я считаю, что вам не нужна замена массива.

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

Вот почему вместо этого вам следует использовать одну из встроенных функций PHP, если цель состоит в том, чтобы создать нормализованные URL-адреса.
 

Алиса2


Рег
26 Jul, 2013

Тем
1

Постов
3

Баллов
13
  • 04, Jun 2024
  • #5
Этот код находит запрошенную статью, сканируя каталог и сравнивая заголовок. Есть ли лучший способ сделать это без SQL? Я боюсь плохой работы при большом количестве статей. Пожалуйста, извините за неправильный отступ: при копировании содержимого в этот редактор строки кажутся неуместными.
статика/article.php
 

<?php require_once('theme/index.template.php'); template_header(

false, // don't show "pageTitle - Site title"

'seven,or,eight,words,that,exist,in,body', // keywords

'A short natural language description describing the site'

); require_once('libs/articles.lib.php');

require_once('libs/paginate.lib.php');

$number_of_articles = newsNumber();

$number_of_pages = ceil($number_of_articles / 5);

$articles=scandir($article_dir,1);

$t=0;

$found=0;

while (!$found &&

$t < $number_of_articles

) {

list($id,$date,$subject,$author)=explode('_',$articles[$t]);

$slug = str_replace(' ', '_', strtolower($subject));

if ($slug == request::value(1))

$found++;

$t++;

}

if (!$found) {

echo '<h1>Error 404</h1>';

http_response_code(404);

template_footer();

die();

} else {

if ($t == $number_of_articles) // Sucky solution but it fixes a bug displaying the last article.

$t--;

$slug = str_replace(' ', '_', strtolower($subject));

$contents=str_ireplace($txt_convert['in'],$txt_convert['out'],

trim(file_get_contents($article_dir.'/'.$articles[$t]))

);

echo '

<div class="article">

<h3>

',$subject,'

</h3>

<div class="article_body">

',$contents,'

<div class="author">Author: ',$author,'</div>

</div>

</div>

';

}

template_footer(); ?>

Код (разметка): мне нужно исправить такие детали, как уникальные ключевые слова и описание для каждой статьи, а также очистить код. Кроме того, я доволен результатами, я использовал статический генератор wok и теперь чувствую себя более свободно с PHP.
 

qwe123qwe1231


Рег
29 Jan, 2012

Тем
1

Постов
2

Баллов
12
  • 09, Jun 2024
  • #6
Спасибо за совет. У меня есть эта модификация в моем списке TODO с низким приоритетом... Я параллельно изучаю много вещей: письмо, основы HTML, CSS и PHP. Оба http://cutcodedown.com/

и /blogSummary/0 (также /blogSummary) имеют одинаковое содержимое, это проблема? особенно с учетом того, что оба URL-адреса связаны внутри сайта.

Следующее, что я хочу попробовать, это создать базовую корзину покупок, поскольку все существующие решения раздуты, поэтому я собираюсь начать изучение PDO с сеансов sqlite и php.

Иногда люди просят меня открыть интернет-магазин, но я отказываюсь использовать такие вещи, как prestashop или magento, поэтому изучение этого помимо полезного — отличная возможность улучшить свои навыки программирования.
 

megallodon


Рег
10 Dec, 2012

Тем
2

Постов
6

Баллов
26
  • 09, Jun 2024
  • #7
Как правило, это незначительно, поскольку это указатель статей, а не сами статьи, причем обе статьи имеют переменное содержание, поэтому мне было бы плевать, если рейтинг этой страницы понизится по сравнению с РЕАЛЬНЫМИ страницами статей.

Поэтому я использую rel="bookmark" в заголовке и ссылки "Читать дальше". Если бы это была реальная проблема, я бы использовал в заголовке версии "/".
 

billadoid


Рег
11 May, 2015

Тем
1

Постов
3

Баллов
13
  • 12, Jun 2024
  • #8
Спасибо вам всем за ответы. Я использую nginx, но в любом случае предпочитаю URL-адреса в нижнем регистре.

Эта функция является исправлением некоторых специальных символов в заголовках статей.

Я уже использую strtolower в другой части кода.

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

Кроме того, / и /0 дают одинаковое содержимое.

Мой опыт программирования очень ограничен, и я теряюсь в этом алгоритме.
 

MaxFrost


Рег
01 Sep, 2013

Тем
1

Постов
2

Баллов
12
Тем
49554
Комментарии
57426
Опыт
552966

Интересно