首页 > 技术文章 > 在Laravel外独立使用Eloquent

caibaotimes 2021-01-06 16:09 原文

laravel8.x

Eloquent是独立的模块,我们也可以在自己的项目里通过composer来使用Eloquent。

Illuminate Database

The Illuminate Database component is a full database toolkit for PHP, providing an expressive query builder, ActiveRecord style ORM, and schema builder. It currently supports MySQL, Postgres, SQL Server, and SQLite. It also serves as the database layer of the Laravel PHP framework.

Usage Instructions

First, create a new "Capsule" manager instance. Capsule aims to make configuring the library for usage outside of the Laravel framework as easy as possible.

use Illuminate\Database\Capsule\Manager as Capsule;

$capsule = new Capsule;

$capsule->addConnection([
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => 'password',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
]);

// Set the event dispatcher used by Eloquent models... (optional)
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
$capsule->setEventDispatcher(new Dispatcher(new Container));

// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();

// Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
$capsule->bootEloquent();

composer require "illuminate/events" required when you need to use observers with Eloquent.

Once the Capsule instance has been registered. You may use it like so:

Using The Query Builder

$users = Capsule::table('users')->where('votes', '>', 100)->get();

Other core methods may be accessed directly from the Capsule in the same manner as from the DB facade:

$results = Capsule::select('select * from users where id = ?', [1]);

Using The Schema Builder

Capsule::schema()->create('users', function ($table) {
    $table->increments('id');
    $table->string('email')->unique();
    $table->timestamps();
});

Using The Eloquent ORM

class User extends Illuminate\Database\Eloquent\Model {}

$users = User::where('votes', '>', 1)->get();

For further documentation on using the various database facilities this library provides, consult the Laravel framework documentation.

安装

在项目目录下执行:

composer require illuminate/database

这样就表示Eloquent已经安装好了。

配置

下面我们来配置Eloquent。

  1. 首先我们创建一个入口文件,如果你的项目已经有内容,那么同理在你的项目入口文件加入即可:

demo/start.php:

<?php

// 载入composer的autoload文件
include __DIR__ . '/vendor/autoload.php';

然后我们加入数据库配置:

$database = [
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'demo',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
];

上面我们的数据库配置,库名demo,用户名root,密码为空,这个demo是我在mysql里建立好的空数据库。

然后我们加入Eloquent初始化代码:

use Illuminate\Container\Container;
use Illuminate\Database\Capsule\Manager as Capsule;

$capsule = new Capsule;

// 创建链接
$capsule->addConnection($database);

// 设置全局静态可访问
$capsule->setAsGlobal();

// 启动Eloquent
$capsule->bootEloquent();

那么Eloquent就配置完成了。

最终的文件demo/start.php应该是这样:

demo/start.php:

<?php

// 载入composer的autoload文件
include __DIR__ . '/vendor/autoload.php';

$database = [
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'demo',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
];

use Illuminate\Container\Container;
use Illuminate\Database\Capsule\Manager as Capsule;//如果你不喜欢这个名称,as DB;就好 

$capsule = new Capsule;

// 创建链接
$capsule->addConnection($database);

// 设置全局静态可访问
$capsule->setAsGlobal();

// 启动Eloquent
$capsule->bootEloquent();

那么现在只要你需要使用到Eloquent的地方载入这个文件即可, 下面我们来简单介绍一下使用。

建表

配置完成了,我们再来使用Eloquent的结构生成器创建数据库的表:

demo/table.php

<?php

//包含Eloquent的初始化文件
include __DIR__ . '/start.php';

use Illuminate\Database\Capsule\Manager as Capsule;

Capsule::schema()->create('users', function($table)
{
    $table->increments('id');
    $table->string('username', 40);
    $table->string('email')->unique();
    $table->timestamps();
});

然后我们运行table.php,两种方式:浏览器打开,或者命令行运行:

php table.php

然后我们的查看MySQL数据库domo里就会有一个users表了

写入数据

表建立好了,然后我们插入数据,我们同样创建一个文件 demo/insert.php来做实验:

<?php

//包含Eloquent的初始化文件
include __DIR__ . '/start.php';

use Illuminate\Database\Capsule\Manager as Capsule;

Capsule::table('users')->insert(array(
        array('username' => 'Hello',  'email' => 'hello@world.com'),
        array('username' => 'Carlos',  'email' => 'anzhengchao@gmail.com'),
        array('username' => 'Overtrue',  'email' => 'i@overtrue.me'),
    ));

使用模型

只要你的模型继承Eloquent的Model类,就没问题了:

use  Illuminate\Database\Eloquent\Model  as Eloquent; 

class User extends  Eloquent 
{
    protected $table = 'users';
}

那么你就可以很方便的像在Laravel框架里一样使用Eloquent了:

// 查询id为2的
$users = User::find(2);

// 查询全部
$users = User::all();

// 创建数据
$user = new User;
$user->username = 'someone';
$user->email = 'some@overtrue.me';
$user->save();

// ... 更多

OK,这基本上就搞定了,当然,你用分页的时候会出问题,因为我们没有依赖laravel的pagination模块。但是引入那个模块同时它内部依赖了symfony的http-foundation模块,意味着为了一个分页功能我们要装好多东西。于是我就实现了一个比较简单的分页类:

<?php
 
namespace Rester;
 
/**
 * Paginator.php
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @author overtrue <anzhengchao@gmail.com>
 * @github https://github.com/overtrue
 * @url    http://overtrue.me
 */
 
use Closure;
use Countable;
use ArrayAccess;
use Serializable;
use ArrayIterator;
use JsonSerializable;
use IteratorAggregate;
 
class Paginator implements
    ArrayAccess,
    Countable,
    IteratorAggregate,
    Serializable,
    JsonSerializable
{
    protected $pager;
    protected $pageSize;
    protected $total;
    protected $items;
 
    /**
     * Constructor
     *
     * @param string             $pager
     */
    public function __construct($pager = 'page')
    {
        $this->pager = $pager;
    }
 
    /**
     * Make a pagination
     *
     * @param array   $items
     * @param integer $total
     * @param integer $pageSize
     *
     * @return array
     */
    public function make($items, $total, $pageSize = 10)
    {
        $this->total    = abs($total);
        $this->pageSize = $pageSize;
        $this->items = $items;
 
        return $this;
    }
 
    /**
     * Return current page
     *
     * @return integer
     */
    public function getCurrentPage($total = null)
    {
        $page = abs(app()->request->get('page', 1));
 
        if ($total) {
            $this->total = $total;
        }
 
        $page >= 1 || $page = 1;
 
        if ($this->items) {
            $totalPage = $this->getTotalPage();
            $page <= $totalPage || $page = $totalPage;
        }
 
        return $page;
    }
 
    /**
     * Return total pages
     *
     * @return integer
     */
    public function getTotalPage()
    {
        $this->pageSize > 0 || $this->pageSize = 10;
 
        $totalPage = ceil($this->total / $this->pageSize);
 
        $totalPage >= 1 || $totalPage = 1;
 
        return $totalPage;
    }
 
    public function links()
    {
        $html = '<ul class="pagination">';
 
        $totalPage   = $this->getTotalPage();
        $currentPage = $this->getCurrentPage();
 
        if ($totalPage < 10) {
            for ($i = 1; $i <= $totalPage; $i++) {
                $active = $i == $currentPage ? 'class="active"':'';
                $html .= "<li $active><a href=".$this->getLink($i).">$i</a></li>";
            }
        } else {
 
            if ($currentPage > 3) {
                $html .= "<li><a href=".$this->getLink(1).">&laquo;</a></li>";
                $start = $currentPage - 2;
            } else {
                $start = 1;
            }
 
            for ($i = $start; $i <= $currentPage; $i++) {
                $active = $i == $currentPage ? 'class="active"':'';
                $html .= "<li $active><a href=".$this->getLink($i).">$i</a></li>";
            }
 
            for ($i = $currentPage + 1; $i <= $currentPage + 3; $i++) {
                $active = $i == $currentPage ? 'class="active"':'';
                $html .= "<li $active><a href=".$this->getLink($i).">$i</a></li>";
            }
 
            if ($totalPage - $currentPage >= 5) {
                $html .= "<li><a href='javascript:void(0)'>...</a></li>";
                $html .= "<li><a href=".$this->getLink($totalPage).">$totalPage</a></li>";
            }
        }
 
        return $html .= '</ul>';
    }
 
    /**
     * getLink
     *
     * @param integer $page
     *
     * @return string
     */
    public function getLink($page)
    {
        static $query;
 
        if (is_null($query)) {
            $query = app()->request->get();
        }
 
        $query['page'] = $page;
 
        return "?" . http_build_query($query);
    }
 
     /** {@inhertDoc} */
    public function jsonSerialize()
    {
        return $this->items;
    }
 
    /** {@inhertDoc} */
    public function serialize()
    {
        return serialize($this->items);
    }
    
    /** {@inhertDoc} */
    public function unserialize($data)
    {
        return $this->items = unserialize($data);
    }
    
    /** {@inhertDoc} **/
    public function getIterator()
    {
        return new ArrayIterator($this->items);
    }
    
    /** {@inhertDoc} */
    public function count($mode = COUNT_NORMAL)
    {
        return count($this->items, $mode);
    }
    
    /**
     * Get a data by key
     *
     * @param string $key
     *
     * @return mixed
     */
    public function __get($key) {
        return $this[$key];
    }
    
    /**
     * Assigns a value to the specified data
     *
     * @param string $key
     * @param mixed  $value
     *
     * @return void
     */
    public function __set($key, $value)
    {
        $this->items[$key] = $value;
    }
    
    /**
     * Whether or not an data exists by key
     *
     * @param string $key
     *
     * @return bool
     */
    public function __isset($key)
    {
        return isset($this->items[$key]);
    }
    
    /**
     * Unsets an data by key
     *
     * @param string $key
     */
    public function __unset($key)
    {
        unset($this->items[$key]);
    }
    
    /**
     * Assigns a value to the specified offset
     *
     * @param string $offset
     * @param mixed  $value
     *
     * @return void
     */
    public function offsetSet($offset, $value)
    {
        $this->items[$offset] = $value;
    }
 
    /**
     * Whether or not an offset exists
     *
     * @param string $offset
     *
     * @access public
     *
     * @return bool
     */
    public function offsetExists($offset)
    {
        return isset($this->items[$offset]);
    }
    
    /**
     * Unsets an offset
     *
     * @param string $offset
     *
     * @return array
     */
    public function offsetUnset($offset)
    {
        if ($this->offsetExists($offset)) {
            unset($this->items[$offset]);
        }
    }
    
    /**
     * Returns the value at specified offset
     *
     * @param string $offset
     *
     * @return mixed
     */
    public function offsetGet($offset)
    {
        return $this->offsetExists($offset) ? array_get($this->items, $offset) : null;
    }
}
 
​```
 
 
然后在我们初始化eloquent的方装载这个分页类到eloquent中就好:
 
 
​```php
 
//...
use Rester\Paginator;
 
// 注册分页类
Capsule::setPaginator(function() use ($app, $config) {
    return new Paginator($app->request, $config->get('pager', 'page'));
});
 
//...
 
​```
 
完整的eloquent初始化步骤请参考: https://github.com/overtrue/rester/blob/master/start/eloquent.php
 
 
然后我们就可以正常使用分页功能了:
 
​```php
 
$users = User::paginate(15);
$users = User::where('status', 1)->paginate(15);
...
 
​```
 
因为上面的分页类实现了常用的[预定义接口](http://php.net/manual/zh/reserved.interfaces.php), 所以你可以很方便的使用分页结果:
 
​```php
 
// 遍历
foreach ($users as $user) {
    // do sth.
}
 
// json encode
$json = json_encode($users);
 
// count 
$count = count($users);
 
//...
 
​```
 
另外还考虑到了大家不一定全用它写接口用,所以分页类同样实现了Laravel里的生成分页链接的方法:`$users->links()`, 它会生成bootstrap格式的分页列表:
 
​```html
<ul class="pagination">
    <li><a href="#">&laquo;</a></li>
    <li><a href="#">1</a></li>
    <li><a href="#">2</a></li>
    <li><a href="#">3</a></li>
    <li><a href="#">4</a></li>
    <li><a href="#">5</a></li>
    <li><a href="#">&raquo;</a></li>
  </ul>
​```
demo:
​```php
<div class="container">
    <?php foreach ($users as $user): ?>
        <?php echo $user->name; ?>
    <?php endforeach; ?>
</div>
 
<?php echo $users->links(); ?>

推荐阅读