使用Laravel后端或任何PHP框架配合WordPress

dev-main 2024-04-26 03:58 UTC

This package is auto-updated.

Last update: 2024-09-26 04:48:59 UTC


README

一个Model类集合,允许您直接从WordPress数据库获取数据。

Actions Status Packagist Packagist Test Coverage Maintainability

Corcel是一个基于Laravel Eloquent ORM(来自Laravel框架)的PHP类集合,提供了一种流畅的接口来连接和直接从WordPress数据库获取数据。

您可以将WordPress用作后端(管理面板)或CMS,用于插入文章、自定义类型等,并在另一边查询这些数据(作为Model层)。与Laravel一起使用Corcel更容易,但您可以使用任何使用Composer的PHP项目。

买我一杯咖啡 | 关注Corcel在Twitter上

目录

安装Corcel

版本兼容性

安装Corcel

您需要使用Composer将Corcel安装到您的项目中

composer require jgrossi/corcel

配置(Laravel)

Laravel 5.5及更高版本

Corcel将使用Laravel的自动发现注册自身。

Laravel 5.4及更早版本

您必须在config/app.php中包含CorcelServiceProvider

'providers' => [
    /*
     * Package Service Providers...
     */
    Corcel\Laravel\CorcelServiceProvider::class,
]

发布配置文件

现在配置我们的配置文件,以确保您的数据库设置正确,并允许您以非常简单的方式注册自定义文章类型和短代码。

在终端中运行以下Artisan命令

php artisan vendor:publish --provider="Corcel\Laravel\CorcelServiceProvider"

现在您有一个config/corcel.php配置文件,其中您可以设置数据库连接以及WordPress表等。

数据库设置

Laravel设置

只需在config/corcel.php中设置Corcel要使用的数据库连接。

假设您在config/database.php文件中已经有了以下数据库连接

// File: /config/database.php

'connections' => [

    'mysql' => [ // for Laravel database
        'driver'    => 'mysql',
        'host'      => 'localhost',
        'database'  => 'mydatabase',
        'username'  => 'admin'
        'password'  => 'secret',
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => '',
        'strict'    => false,
        'engine'    => null,
    ],

    'wordpress' => [ // for WordPress database (used by Corcel)
        'driver'    => 'mysql',
        'host'      => 'localhost',
        'database'  => 'mydatabase',
        'username'  => 'admin',
        'password'  => 'secret',
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => 'wp_',
        'strict'    => false,
        'engine'    => null,
    ],
],

在这种情况下,您应该想为Corcel使用wordpress连接,因此只需将其设置为config/corcel.php配置文件中即可。

'connection' => 'wordpress',

其他PHP框架(非Laravel)设置

在这里,您必须配置数据库以满足Corcel的要求。首先,如果尚未加载,应包括Composer的autoload文件。

require __DIR__ . '/vendor/autoload.php';

现在您必须设置WordPress数据库参数

$params = [
    'database'  => 'database_name',
    'username'  => 'username',
    'password'  => 'pa$$word',
    'prefix'    => 'wp_' // default prefix is 'wp_', you can change to your own prefix
];
Corcel\Database::connect($params);

您可以指定所有Eloquent参数,但一些是默认的(但您可以覆盖它们)。

'driver'    => 'mysql',
'host'      => 'localhost',
'charset'   => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix'    => 'wp_', // Specify the prefix for WordPress tables, default prefix is 'wp_'

用法

文章

每次您看到 Post::method(),如果您正在使用自己的 Post 类(其中您设置了连接名称),如 App\Post,则应使用 App\Post::method(),而不是 Post::method()。所有示例都假设您已经知道这种区别。

在示例中,每次您看到 Post::method(),请假设为 Corcel\Model\Post::method()

// All published posts
$posts = Post::published()->get();
$posts = Post::status('publish')->get();

// A specific post
$post = Post::find(31);
echo $post->post_title;

创建自己的模型类

可选地,您可以创建自己的 Post 模型(或页面,或任何其他内容),它扩展了 Corcel\Post。然后设置您使用的连接名称(如果您想覆盖 Corcel 的默认连接名称),在这种情况下为 foo-bar

扩展 Corcel\Model\Post 类可以使您的项目更加灵活,一旦您可以添加自定义方法和逻辑,就可以根据您需要从 WordPress 数据库中使用的任何内容。

<?php // File: app/Post.php

namespace App;

use Corcel\Model\Post as Corcel;

class Post extends Corcel
{
    protected $connection = 'foo-bar';

    public function customMethod() {
        //
    }
}

因此,现在您可以使用自己的类获取 WP 数据库数据

$posts = App\Post::all(); // using the 'foo-bar' connection

请记住,您不必扩展我们的 Post 类,您可以使用 Corcel\Model\Post 和其他所有模型而没有任何问题。

元数据(自定义字段)

注意:在 Corcel v1 中,您可以使用 Post::save() 方法保存元数据。现在不再允许这样做。使用 saveMeta()createMeta()(见下文)方法来保存文章元数据。

您也可以从文章中检索元数据。

// Get a custom meta value (like 'link' or whatever) from a post (any type)
$post = Post::find(31);
echo $post->meta->link; // OR
echo $post->fields->link;
echo $post->link; // OR

要创建或更新用户元数据,只需使用 saveMeta()saveField() 方法。它们返回与 Eloquent save() 方法相同的 bool

$post = Post::find(1);
$post->saveMeta('username', 'jgrossi');

您也可以同时保存多个元数据。

$post = Post::find(1);
$post->saveMeta([
    'username' => 'jgrossi',
    'url' => 'http://jgrossi.com',
]);

您还有 createMeta()createField() 方法,它们的工作方式类似于 saveX() 方法,但它们仅用于创建,并返回创建的 PostMeta 实例,而不是 bool

$post = Post::find(1);
$postMeta = $post->createMeta('foo', 'bar'); // instance of PostMeta class
$trueOrFalse = $post->saveMeta('foo', 'baz'); // boolean

通过自定义字段(元数据)查询文章

通过在 Post(或使用 HasMetaFields 特性的其他模型)类上使用作用域,有多种方法可以查询通过自定义字段(元数据)的文章。

要检查元键是否存在,请使用 hasMeta() 作用域

// Finds a published post with a meta flag.
$post = Post::published()->hasMeta('featured_article')->first();

如果您想精确匹配元字段,可以使用带有值的 hasMeta() 作用域。

// Find a published post which matches both meta_key and meta_value.
$post = Post::published()->hasMeta('username', 'jgrossi')->first();

如果您需要匹配多个元字段,也可以使用带参数的 hasMeta() 作用域

$post = Post::hasMeta(['username' => 'jgrossi'])->first();
$post = Post::hasMeta(['username' => 'jgrossi', 'url' => 'jgrossi.com'])->first();
// Or just passing the keys
$post = Post::hasMeta(['username', 'url'])->first();

如果您需要匹配不区分大小写的字符串或使用通配符进行匹配,请使用带值的 hasMetaLike() 作用域。这使用 SQL LIKE 操作符,因此请使用 '%' 作为通配符操作符。

// Will match: 'J Grossi', 'J GROSSI', and 'j grossi'.
$post = Post::published()->hasMetaLike('author', 'J GROSSI')->first();

// Using % as a wildcard will match: 'J Grossi', 'J GROSSI', 'j grossi', 'Junior Grossi' etc.
$post = Post::published()->hasMetaLike('author', 'J%GROSSI')->first();

字段别名

Post 类支持“别名”,因此如果您检查 Post 类,您应该注意静态 $aliases 数组中定义的一些别名,例如 titlepost_titlecontentpost_content

$post = Post::find(1);
$post->title === $post->post_title; // true

如果您正在扩展 Post 类以创建自己的类,您也可以使用 $aliases。只需在您的类中添加新别名到该静态属性,它将自动继承父 Post 类的所有别名。

class A extends \Corcel\Post
{
    protected static $aliases = [
        'foo' => 'post_foo',
    ];
}

$a = A::find(1);
echo $a->foo;
echo $a->title; // from Post class

自定义作用域

要排序文章,可以使用 newest()oldest() 作用域,适用于 PostUser 类。

$newest = Post::newest()->first();
$oldest = Post::oldest()->first();

分页

要排序文章,只需使用 Eloquent paginate() 方法。

$posts = Post::published()->paginate(5);
foreach ($posts as $post) {
    // ...
}

要显示分页链接,只需调用 links() 方法。

{{ $posts->links() }}

高级自定义字段 (ACF)

如果您想检索由 高级自定义字段 (ACF) 插件创建的自定义字段,您必须安装 corcel/acf 插件 - 点击此处获取更多信息 - 并按如下方式调用自定义字段

$post = Post::find(123);
echo $post->acf->some_radio_field;
$repeaterFields = $post->acf->my_repeater_name;

为了避免不必要的SQL查询,只需设置您请求的字段类型。通常需要两次SQL查询才能获取字段类型,因此如果您想指定它,您将跳过这些额外的查询

$post = Post::find(123);
echo $post->acf->text('text_field_name');
echo $post->acf->boolean('boolean_field_name');

自定义帖子类型

您也可以使用自定义帖子类型。您可以使用type(string)方法或创建自己的类。

// using type() method
$videos = Post::type('video')->status('publish')->get();

// using your own class
class Video extends Corcel\Post
{
    protected $postType = 'video';
}
$videos = Video::status('publish')->get();

使用type()方法将使Corcel返回所有对象为Corcel\Post。使用您自己的自定义类,您有自定义类、包括自定义方法和属性的优势,例如,将所有对象作为Video返回。

自定义帖子类型和元数据

// Get 3 posts with custom post type (store) and show its address
$stores = Post::type('store')->status('publish')->take(3)->get();
foreach ($stores as $store) {
    $storeAddress = $store->address; // option 1
    $storeAddress = $store->meta->address; // option 2
    $storeAddress = $store->fields->address; // option 3
}

配置返回的实例

每次您调用类似Post::type('video')->first()Video::first()的操作时,您都会收到一个Corcel\Model\Post实例。

如果您选择为自定义帖子类型创建一个新类,您可以返回该类的所有该帖子类型的实例。

注册帖子类型(简单方法)

而不是为要注册的所有自定义帖子类型调用Post::registerPostType()方法,只需使用Corcel的配置文件并将所有自定义帖子及其类映射即可。它们将自动为您注册。

'post_types' => [
    'video' => App\Video::class,
    'foo' => App\Foo::class,
]

因此,每次您查询自定义帖子类型时,都会返回映射的实例。

当您打算获取不同类型的帖子集合时(例如,在获取在菜单中定义的帖子时),这特别有用。

注册帖子类型(困难方法)

//all objects in the $videos Collection will be instances of Post
$videos = Post::type('video')->status('publish')->get();

// register the video custom post type and its particular class
Post::registerPostType('video', '\App\Video')


//now all objects in the $videos Collection will be instances of Video
$videos = Post::type('video')->status('publish')->get();

您还可以为此使用内置类,例如页面或帖子。只需将页面或帖子类与相关的帖子类型字符串关联起来,然后返回该对象而不是默认对象。

短代码

从配置(Laravel)

您可以在config/corcel.php文件中映射您想要的全部短代码,在'shortcodes'键下。在这种情况下,您应该创建一个自己的类,该类实现Corcel\Shortcode接口,该接口需要一个render()方法。

'shortcodes' => [
    'foo' => App\Shortcodes\FooShortcode::class,
    'bar' => App\Shortcodes\BarShortcode::class,
],

这是一个短代码类的示例

class FakeShortcode implements \Corcel\Shortcode
{
    /**
     * @param ShortcodeInterface $shortcode
     * @return string
     */
    public function render(ShortcodeInterface $shortcode)
    {
        return sprintf(
            'html-for-shortcode-%s-%s',
            $shortcode->getName(),
            $shortcode->getParameter('one')
        );
    }
}

在运行时

您可以通过在Post模型上调用addShortcode方法来添加短代码

// [gallery id="1"]
Post::addShortcode('gallery', function ($shortcode) {
    return $shortcode->getName() . '.' . $shortcode->getParameter('id');
});
$post = Post::find(1);
echo $post->content;

Laravel 5.5使用包自动发现,因此不需要手动添加ServiceProvider。

如果您使用Laravel,我们建议在App\Providers\AppServiceProvider中的boot方法中添加您的短代码处理器。

短代码解析

短代码使用thunderer/shortcode库进行解析。

提供了多种不同的解析器。RegularParser在技术上是最正确的,默认提供。这适用于大多数情况。然而,如果您在短代码解析中遇到一些不规则性,您可能需要配置Corcel使用WordpressParser,它更忠实于WordPress的短代码正则表达式。为此,如果您使用Laravel,请编辑config/corcel.php文件,取消注释您首选的解析器。或者,您可以替换为您自己的解析器。

'shortcode_parser' => Thunder\Shortcode\Parser\RegularParser::class,
// 'shortcode_parser' => Thunder\Shortcode\Parser\WordpressParser::class,

如果您不使用Laravel,您可以在运行时执行此操作,从任何使用Shortcodes特质的类(例如,Post)中调用setShortcodeParser()方法。

$post->setShortcodeParser(new WordpressParser());
echo $post->content; // content parsed with "WordpressParser" class

有关短代码包的更多信息,请点击此处

分类

您可以通过以下方式获取特定帖子的分类

$post = Post::find(1);
$taxonomy = $post->taxonomies()->first();
echo $taxonomy->taxonomy;

或者,您可以使用其分类来搜索帖子

$post = Post::taxonomy('category', 'php')->first();

文章格式

您也可以获取文章格式,例如WordPress函数get_post_format()

echo $post->getFormat(); // should return something like 'video', etc

页面

页面类似于自定义文章类型。您可以使用Post::type('page')Corcel\Model\Page类。

use Corcel\Model\Page;

// Find a page by slug
$page = Page::slug('about')->first(); // OR
$page = Post::type('page')->slug('about')->first();
echo $page->post_title;

分类和分类法

获取一个分类或分类法或从某个分类中加载文章。有多种方法可以实现。

// all categories
$cat = Taxonomy::category()->slug('uncategorized')->posts->first();
echo "<pre>"; print_r($cat->name); echo "</pre>";

// only all categories and posts connected with it
$cat = Taxonomy::where('taxonomy', 'category')->with('posts')->get();
$cat->each(function($category) {
    echo $category->name;
});

// clean and simple all posts from a category
$cat = Category::slug('uncategorized')->posts->first();
$cat->posts->each(function($post) {
    echo $post->post_title;
});

附件和修订版

PostPage获取附件和/或修订版。

$page = Page::slug('about')->with('attachment')->first();
// get feature image from page or post
print_r($page->attachment);

$post = Post::slug('test')->with('revision')->first();
// get all revisions from a post or page
print_r($post->revision);

缩略图

获取PostPage的缩略图。

$post = Post::find(1);

// Retrieve an instance of Corcel\Model\Meta\ThumbnailMeta.
print_r($post->thumbnail);

// For convenience you may also echo the thumbnail instance to get the URL of the original image.
echo $post->thumbnail;

要检索特定缩略图大小,您可以在缩略图对象上调用->size()方法并传递缩略图大小字符串参数(例如thumbnailmedium)。如果缩略图已生成,则此方法返回图像元数据数组,否则将返回作为回退的原始图像URL。

if ($post->thumbnail !== null) {
    /**
     * [
     *     'file' => 'filename-300x300.jpg',
     *     'width' => 300,
     *     'height' => 300,
     *     'mime-type' => 'image/jpeg',
     *     'url' => 'https:///wp-content/uploads/filename-300x300.jpg',
     * ]
     */
    print_r($post->thumbnail->size(Corcel\Model\Meta\ThumbnailMeta::SIZE_THUMBNAIL));

    // https:///wp-content/uploads/filename.jpg
    print_r($post->thumbnail->size('invalid_size'));
}

选项

在Corcel的早期版本中,此类被称为Options而不是Option(单数)。因此,从v2.0.0开始,请始终使用该类单数形式。

Corcel 2+中删除了Option::getAll()方法,改为使用Option::asArray($keys [])

您可以使用Option类从wp_options表获取数据

$siteUrl = Option::get('siteurl');

您还可以添加新选项

Option::add('foo', 'bar'); // stored as string
Option::add('baz', ['one' => 'two']); // this will be serialized and saved

您可以以简单的数组形式获取所有选项

$options = Option::asArray();
echo $options['siteurl'];

或者,您也可以指定要获取的键

$options = Option::asArray(['siteurl', 'home', 'blogname']);
echo $options['home'];

菜单

要按其别名获取菜单,请使用以下语法。菜单项将加载到items变量中(它是一个包含Corcel\Model\MenuItem对象的集合)。

当前支持的菜单项包括:页面、文章、自定义链接和分类。

一旦您有MenuItem类的实例,如果您想使用原始实例(例如原始页面或术语,例如),只需调用MenuItem::instance()方法。MenuItem对象只是一个具有post_type等于nav_menu_item的帖子。

$menu = Menu::slug('primary')->first();

foreach ($menu->items as $item) {
    echo $item->instance()->title; // if it's a Post
    echo $item->instance()->name; // if it's a Term
    echo $item->instance()->link_text; // if it's a custom link
}

instance()方法将返回匹配的对象

  • Post实例用于post菜单项;
  • Page实例用于page菜单项;
  • CustomLink实例用于custom菜单项;
  • Term实例用于category菜单项。

多级菜单

要处理多级菜单,遍历所有菜单项并将它们放置在正确的级别上,例如。

您可以使用MenuItem::parent()方法检索该菜单项的父实例

$items = Menu::slug('foo')->first()->items;
$parent = $items->first()->parent(); // Post, Page, CustomLink or Term (category)

要按父项分组菜单项,您可以在$menu->items集合中使用->groupBy()方法,按其$item->parent()->ID对菜单项进行分组。

有关groupBy()方法的更多信息,请参阅Laravel文档

用户

您可以像处理文章一样操作用户

// All users
$users = User::get();

// A specific user
$user = User::find(1);
echo $user->user_login;

身份验证

使用Laravel

如果您正在使用Laravel 5.4或更早版本,请确保您已注册了CorcelServiceProvider提供程序

然后,在config/auth.php中定义用户提供程序,以允许Laravel使用WordPress用户进行登录

'providers' => [
    'users' => [
        'driver' => 'corcel',
        'model'  => Corcel\Model\User::class,
    ],
],

现在您可以使用Auth外观来验证用户

Auth::validate([
    'email' => 'admin@example.com', // or using 'username' too
    'password' => 'secret',
]);

为了使 Laravel 的密码重置功能与 Corcel 兼容,我们必须覆盖数据库中密码的存储方式。为此,您必须更改 Auth/PasswordController.php,从

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;

class PasswordController extends Controller
{
    use ResetsPasswords;

改为

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Corcel\Laravel\Auth\ResetsPasswords as CorcelResetsPasswords;

class PasswordController extends Controller
{
    use ResetsPasswords, CorcelResetsPasswords {
        CorcelResetsPasswords::resetPassword insteadof ResetsPasswords;
    }

不使用 Laravel

您可以使用 AuthUserProvider 类手动验证用户。

$userProvider = new Corcel\Laravel\Auth\AuthUserProvider;
$user = $userProvider->retrieveByCredentials(['username' => 'admin']);
if(!is_null($user) && $userProvider->validateCredentials($user, ['password' => 'admin'])) {
    // successfully login
}

请记住,您可以使用 usernameemail 作为用户的凭证。

运行测试

要运行 phpunit 测试,请执行以下命令

./vendor/bin/phpunit

如果您已安装全局 phpunit 命令,您可以直接输入

phpunit

所有测试都使用 Sqlite 和 :memory 数据库编写,因此它们在您的内存中运行。所有测试都使用 factoriesmigrations。请查看 tests/database/factoriestests/database/migrations 目录以获取更多信息。

贡献

欢迎所有贡献来帮助改进 Corcel。

在您提交拉取请求(PR)之前,请考虑以下指南

  • Fork https://github.com/corcel/corcel 在 Github 上;

  • 在本地克隆您的分叉仓库(不是 Corcel 的)并创建基于您要修复的版本(2.12.22.32.42.5)的分支:git checkout -b my-fix-branch 2.5

  • 进行所有代码更改。请记住,在添加任何功能或修复任何错误(如果尚未测试)时,至少编写一个测试用例。我们的目标是让 100% 的代码通过测试,所以请帮助我们编写更好的代码 ;-) 如果您没有测试经验,这是一个学习的好机会。只需查看我们的测试用例,您就会看到它们是多么简单。

  • 在本地运行单元测试以确保您的更改没有破坏其他代码片段;

  • 将您的分支推送到您的分叉仓库,通常 git push origin HEAD 应该可以工作;

  • 在 GitHub 上,从您的自定义 my-fix-branch 分支(从您的分叉仓库)创建一个拉取请求(PR)到相关的分支(例如,corcel:2.5,而不是 corcel:master,请);

  • 等待批准 :-)

许可证

MIT 许可证 © Junior Grossi