xtodx/corcel


README

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

Travis 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 配置文件,您可以在其中设置数据库连接以及更多内容。

数据库设置

Laravel 设置

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

假设您在 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 = array(
    '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()方法。它们返回bool,类似于Eloquent的save()方法。

$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数组中定义的一些别名,例如title对应于post_title,而content对应于post_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'];

菜单

要按slug获取菜单,请使用以下语法。菜单项将加载到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。

在您提交Pull Request(PR)之前,请考虑以下指南

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

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

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

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

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

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

  • 等待批准 :-)

许可证

MIT许可证 © Junior Grossi