zenstark/corcel

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


README

一组模型类,允许您直接从WordPress数据库中获取数据。

Actions Status Packagist Packagist Test Coverage Maintainability

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

您可以将 WordPress 用作后端(管理面板)或 CMS,用于插入帖子、自定义类型等,而另一侧的任何其他 PHP 应用都可以查询这些数据(作为模型层)。与 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 连接,因此只需将其设置在 Corcel 配置文件 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)之前,请考虑以下指南:

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

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

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

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

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

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

  • 等待批准:-)

许可证

MIT许可证 © Junior Grossi