1. Полный контроль над рендерингом. Создавайте страницы, используя полный контроль над HTML / CSS и без ограничений, связанных с базовой темой WordPress или настройкой файла темы.
  2. Рентабельность: вы можете делать почти все самостоятельно, вместо того, чтобы покупать премиальные темы или плагины (например, электронную почту, контактные формы, кеширование, сжатие и т. д.)
  3. Более безопасный: отключив интерфейс WordPress, вы в основном устраняете большинство уязвимостей, связанных со взломом и рассылкой спама.
  4. Надежный код: поскольку .NET предлагает IntelliSense и компиляцию времени разработки для всего, что вы пишете, будь то код C # или код Razor в представлениях HTML, вероятность возникновения ошибок времени выполнения снижается. Однако, когда вы работаете с файлом PHP (в редакторе тем WordPress или любой другой IDE), вы относительно более подвержены ошибкам.
  5. Повышение эффективности: это спорная тема, и у меня нет данных, подтверждающих ее. Однако, согласно этому сообщению SO, при использовании .NET по сравнению с PHP для той же задачи есть много преимуществ в производительности.

Давайте погрузимся в реализацию…

Подготовить базу данных MySQL

WordPress использует базу данных MySQL для хранения всего своего контента, такого как страницы и сообщения. Вы, наверное, уже это знаете, но на всякий случай :).

Нам нужно найти строку подключения для подключения к базе данных WordPress. Посмотрите на wp-config.php файл, хранящийся в корне вашей установки WordPress. Проверьте эти значения:

 /** MySQL database name */
define(‘DB_NAME’, ‘db_name’);
/** MySQL database username */
define(‘DB_USER’, ‘username’);
/** MySQL database password */
define(‘DB_PASSWORD’, ‘p@55word’);
/** MySQL hostname */
define(‘DB_HOST’, ‘localhost’);

Есть вероятность, что ваше DB_HOST значение не localhost, а какой-то IP-адрес, и это нормально. Запишите эти значения и продолжайте.

Удаленный доступ к серверу MySQL

Возможно, что доступ к серверу MySQL ограничен локальным сервером. Это означает, что к базе данных нельзя получить доступ извне сервера. Это нормально с точки зрения окончательной реализации, однако вам нужно будет взглянуть на some базу данных WordPress, чтобы понять структуру таблиц и столбцов.

Чтобы открыть доступ к MySQL извне, откройте порт 3306 на своем сервере и попробуйте подключиться к MySQL удаленно. Вам также может потребоваться предоставить права удаленного подключения соответствующей учетной записи пользователя. Если у вас нет доступа к серверу или недостаточно прав, попробуйте установить WordPress локально на свой компьютер. Это может быть длительный процесс и включает в себя довольно много шагов. Ознакомьтесь с этой статьей, чтобы узнать, как это сделать.

Проект .NET

Создайте новый проект .NET для разработки интерфейса веб-сайта. Вы можете использовать .NET Framework или .NET Core, это не имеет особого значения для данной статьи. Так что выберите тот, который вам удобен.

Установите пакеты nu-get (названия пакетов указаны для .NET Core)

Microsoft.EntityFrameworkCore;
MySql.EntityFrameworkCore

Теперь нам нужно добавить несколько моделей для представления таблиц базы данных WordPress. Используя эти модели, мы можем написать код C # для чтения содержимого публикации для создания наших интерфейсных страниц. Как минимум, вам потребуются следующие модели:

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

[Table("wp_terms")]
public class Term 
{
   [Key]
   [Column("term_id")]
   public int TermId {get; set;}
   
   [Column("name")]
   public string Name {get; set;}
   [Column("slug")]
   public string Slug {get; set;}
   [Column("term_group")]
   public int TermGroup {get; set;}
}

TermTaxonomy
Эта таблица определяет, является ли конкретное значение, хранящееся в wp_termstable, категорией, тегом или чем-то еще.

[Table("wp_term_taxonomy")]
public class TermTaxonomy
{
   [Key]
   [Column("term_id")]
   public int TermId { get; set; }
   [Column ("taxonomy")]
   public string Taxonomy { get; set; }
   [Column("description")]
   public string Description { get; set; }
   [Column("parent")]
   public int Parent { get; set; }
   [Column("count")]
   public int Count { get; set; }
}

Поиск списка категорий:
Запросите Term таблицу, соедините ее с TermTaxonomy на основе общего столбцаTermId и найдите Taxonomy значение 'category'.
Подробнее о запросах позже.

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

[Table("wp_posts")
public class Post
{
   [Key]
   [Column("ID")
   public int Id {get; set;}
   [Column("post_author")]
   public int AuthorId {get; set;}
   [Column("post_date")]
   public DateTime Date {get; set;}
... replicate all columns from table
}

TermRelationship
Это небольшая таблица (всего 3 столбца), но ее немного сложно использовать. Давайте сначала посмотрим на структуру таблицы:

[Table("wp_term_relationships")]
public class TermRelationship
{
   [Key]
   [Column("object_id")]
   public int ObjectId { get; set; }
   [Column("term_taxonomy_id")]
   public int TaxonomyId { get; set; }
   [Column("term_order")]
   public int Order { get; set; }
}

Сначала это может быть немного сложно понять, но потерпите меня:
Когда вы получаете сообщение из таблицы Сообщение, вам также необходимо знать категория, к которой принадлежит публикация. Здесь используется таблица TermRelationship. В таблице Сообщение есть столбец с именем ID. Это уникальный идентификатор каждого сообщения. Соедините таблицу Post с таблицей TermRelationship, используя столбец ID столбца Post и ObjectId столбец TermRelationship. Результат TaxonomyId в TermRelationship - это TermId соответствующей категории в таблице Term. Вы также можете присоединиться к запросу с таблицей Term, чтобы получить название категории, если это необходимо. Фух! Поверьте мне, это как никогда сложно, остальное просто ваниль.

Примечание.
Показанные выше классы моделей отмечены знаком [Table(“wp_name”)] для указания имени таблицы в базе данных. Возможно, имена ваших таблиц начинаются с чего-то другого, кроме wp. В этом случае просто используйте точное имя из базы данных для украшения классов вашей модели.

DbContext
После создания моделей добавить DbSet в класс DbContext довольно просто. Вот образец класса DbContext:

public class WordPressDbContext: DbContext
{
   public WordPressDbContext() : base() { }
   public virtual DbSet<Term> Terms { get; set; }
   public virtual DbSet<TermTaxonomy> TermTaxonomies { get; set; }
   public virtual DbSet<Post> Posts { get; set; }
   public virtual DbSet<TermRelationship> TermRelationships { get; set; }
}

Строка подключения
Вот строка подключения, которую нужно поместить в web.config файл (при использовании .NET Framework) или appsettings.json (при использовании .NET Core). Используйте значения из файла wp-config, как описано выше.

"server=localhost;port=3306;database=db_name;uid=username;password=p@55word"

Получение данных для интерфейсных страниц

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

Вот несколько примеров запросов для получения данных:

Список категорий

var data = (from t in db.Terms
            from tt in db.TermTaxonomies.Where(a => 
                  a.TermId == t.TermId && 
                  a.Taxonomy == "category")
            select new
            {
                Id = t.TermId,
                Name = t.Name,
                Description = tt.Description,
                Slug = t.Slug,
             }).ToList();

Список сообщений в определенной категории

var posts = (from p in db.Posts.Where(a => 
                     a.Type == "post" && 
                     a.Status == "publish")
             from tr in db.TermRelationships.Where(a => 
                     a.ObjectId == p.Id && 
                     a.TaxonomyId == categoryId)
             select new 
             {
                 Title = p.Title,
                 Slug = p.Slug, 
                 Excerpt = p.Excerpt,
                 PublishedOn = p.Date,
                 Comments = p.CommentCount
              }).ToList();

Вы также можете использовать OrderBy для упорядочивания результатов и Take(n) для извлечения только фиксированного количества сообщений из категории, например, для создания страничной навигации.

Поиск в сообщениях

var data  = (from p in db.Posts.Where(a => 
                    a.Type == "post" && 
                    a.Status == "publish" &&
                    a.Content.Contains(query))
             from tr in db.TermRelationships.Where(a => 
                    a.ObjectId == p.Id)
             from t in db.Terms.Where(a => 
                    a.TermId == tr.TaxonomyId)
             select new
             {
                 CategoryName = t.Name,
                 CategorySlug = t.Slug,
                 Title = p.Title, 
                 Slug = p.Slug,
                 Excerpt = p.Excerpt,
                 PublishedOn = p.Date,
                 Comments = p.CommentCount
              }).ToList();

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

Некоторые образцы

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

Указатель категорий с лучшими сообщениями

Архив категорий со всеми сообщениями

Одно сообщение (с правой панелью навигации)

Если вы разработчик PHP, все это может показаться вам бесполезным. Однако, как разработчик .NET C #, он сочетает в себе лучшее из обоих миров - мощь WordPress и .NET. Поскольку я являюсь специалистом по .NET, я всегда думаю об использовании .NET новыми, неизведанными способами. Поделитесь своими мыслями.