rafaelwendel/phpsupabase

PHPSupabase 是用 PHP 语言编写的库,它允许您通过与其 Rest API 集成来使用在 Supabase(https://supabase.io)中创建的项目资源。

0.0.8 2024-08-09 18:00 UTC

This package is auto-updated.

Last update: 2024-09-09 18:28:44 UTC


README

PHPSupabase 是用 PHP 语言编写的库,它允许您通过与其 Rest API 集成来使用在 Supabase(https://supabase.io)中创建的项目资源。

内容

关于 Supabase

Supabase 是 "开源 Firebase 的替代品"。通过它,可以在不到 2 分钟的时间内创建后端。从 Postgres 数据库、身份验证、即时 API、实时订阅和存储开始您的项目。

PHPSupabase 特点

  • 创建和管理 Supabase 项目的用户
  • 管理用户身份验证(通过电子邮件/密码、魔法链接等)
  • 在 Postgres 数据库中插入、更新、删除和获取数据(通过 Supabase 项目的 Rest API)
  • QueryBuilder 类以简单的方式过滤项目数据

安装与加载

PHPSupabase 可在 Packagist 上找到,并且通过 Composer 安装是推荐的方式。将以下行添加到您的 composer.json 文件中

"rafaelwendel/phpsupabase" : "^0.0.1"

或者运行

composer require rafaelwendel/phpsupabase

如何使用

要使用 PHPSupabse 库,您必须在 Supabase 控制面板中有一个账户和一个项目。在项目设置(API 部分)中,您应该记下您项目的 API密钥URL。 (注意:基本上我们有两个用于 URL 的后缀:/rest/v1/auth/v1,但自版本 0.0.5 以来,这些后缀中之一的定义是可选的)

首先,让我们实例化 Service() 类。我们必须在构造函数中传递 API密钥url

<?php

require "vendor/autoload.php";

$service = new PHPSupabase\Service(
    "YOUR_API_KEY", 
    "https://aaabbbccc.supabase.co"
);

//In versions 0.0.4 or earlier it is necessary to set the suffix
$service = new PHPSupabase\Service(
    "YOUR_API_KEY", 
    "https://aaabbbccc.supabase.co/auth/v1" // or https://aaabbbccc.supabase.co/rest/v1
);

Service 类抽象了与项目 API 的操作,同时也提供了其他类的实例(AuthDatabaseQueryBuilder)。

Auth 类

让我们实例化 Auth 类的对象

$auth = $service->createAuth();

$auth 对象有几种用于管理项目用户的方法。通过它,可以创建新用户或验证现有用户的登录。

使用电子邮件和密码创建新用户

以下是如何使用 emailpassword 创建新用户的示例。

$auth = $service->createAuth();

try{
    $auth->createUserWithEmailAndPassword('newuser@email.com', 'NewUserPassword');
    $data = $auth->data(); // get the returned data generated by request
    echo 'User has been created! A confirmation link has been sent to the '. $data->email;
}
catch(Exception $e){
    echo $auth->getError();
}

新创建的用户现在在项目的用户表中,可以在 Supabase 控制面板的 "身份验证" 部分中看到。要启用,用户必须访问发送到电子邮件的确认链接。

createUserWithEmailAndPassword 方法的第三个参数中,您可以传递包含要保存的 user_metadata 的数组(例如:nameage)。

$user_metadata = [
    'name' => 'Lebron James',
    'age' => '34'
];
$auth->createUserWithEmailAndPassword('lebron@email.com', 'LebronPassword', $user_metadata);

使用电子邮件和密码登录

现在让我们看看如何进行用户认证。认证请求返回一个access_token(Bearer Token),可以在以后的操作中使用,并检查过期时间。此外,还会返回其他信息,如refresh_token和用户数据。无效的登录凭据会导致抛出一个新的异常。

$auth = $service->createAuth();

try{
    $auth->signInWithEmailAndPassword('user@email.com', 'UserPassword');
    $data = $auth->data(); // get the returned data generated by request

    if(isset($data->access_token)){
        $userData = $data->user; //get the user data
        echo 'Login successfully for user ' . $userData->email;

        //save the $data->access_token in Session, Cookie or other for future requests.
    }
}
catch(Exception $e){
    echo $auth->getError();
}

获取登录用户的资料

要获取用户数据,您需要拥有在登录操作中返回的access_token(Bearer Token)。

$auth = $service->createAuth();
$bearerToken = 'THE_ACCESS_TOKEN';

try{
    $data = $auth->getUser($bearerToken);
    print_r($data); // show all user data returned
}
catch(Exception $e){
    echo $auth->getError();
}

更新用户资料

可以更新用户数据(如电子邮件和密码),还可以创建/更新metadata,这是我们可以创建的附加数据(如first_namelast_nameinstagram_account或其他)。

updateUser方法必须以bearerToken作为参数。除了它之外,我们还有三个可选参数:emailpassworddata(数组)。如果您不想更改这些数据中的某些数据,只需将其设置为null

以下是一个保存/更新用户两个新元数据(first_namelast_name)的示例。

$auth = $service->createAuth();
$bearerToken = 'THE_ACCESS_TOKEN';

$newUserMetaData = [
    'first_name' => 'Michael',
    'last_name'  => 'Jordan'
];

try{
    //the parameters 2 (email) and 3(password) are null because this data will not be changed
    $data = $auth->updateUser($bearerToken, null, null, $newUserMetaData);
    print_r($data); // show all user data returned
}
catch(Exception $e){
    echo $auth->getError();
}

请注意,在现在返回的数组中,已将first_namelast_name键添加到user_metadata中。

数据库类

Database类提供了执行对Supabase项目提供的Postgre数据库表的操作(插入、更新、删除和获取)的功能。

对于下面的示例,请考虑以下数据库结构

categories (id INT AUTO_INCREMENT, categoryname VARCHAR(32))
products (id INT AUTO_INCREMENT, productname VARCHAR(32), price FLOAT, categoryid INT)

Database类也是从service对象实例化的。您必须传递将要使用的table及其相应的主键(通常是id)。

让我们创建一个对象来处理categories

$db = $service->initializeDatabase('categories', 'id');

通过db变量可以执行对categories表的操作。

注意:如果使用表中启用了行级安全(RLS),则将bearerToken传递给Service对象

$bearerToken = 'THE_ACCESS_TOKEN'; //returned in the login action.
$db = $service->setBearerToken($bearerToken)->initializeDatabase('categories', 'id');

插入数据

categories表中插入新记录

$db = $service->initializeDatabase('categories', 'id');

$newCategory = [
    'categoryname' => 'Video Games'
];

try{
    $data = $db->insert($newCategory);
    print_r($data); //returns an array with the new register data
    /*
        Array
        (
            [0] => stdClass Object
                (
                    [id] => 1
                    [categoryname] => Video Games
                )

        )
    */
}
catch(Exception $e){
    echo $e->getMessage();
}

现在让我们插入一个来自分类1 - Video Games的新产品

$db = $service->initializeDatabase('products', 'id');

$newProduct = [
    'productname' => 'XBOX Series S',
    'price'       => '299.99',
    'categoryid'  => '1' //Category "Video Games"
];

try{
    $data = $db->insert($newProduct);
    print_r($data); //returns an array with the new register data
    /*
        Array
        (
            [0] => stdClass Object
                (
                    [id] => 1
                    [productname] => XBOX Series S
                    [price] => 299.99
                    [categoryid] => 1
                )
        )
    */
}
catch(Exception $e){
    echo $e->getMessage();
}

更新数据

要更新数据库中的记录,我们使用update方法,将待更新的记录的id(PK)作为参数传递,以及包含新数据的array(注意:目前无法使用除主键之外的其他参数执行更新)。

在下面的示例中,我们将更新具有id=1的产品("Xbox Series S"更改为"XBOX Series S 512GB"和"299.99"更改为"319.99")的productnameprice

$db = $service->initializeDatabase('products', 'id');

$updateProduct = [
    'productname' => 'XBOX Series S 512GB',
    'price'       => '319.99'
];

try{
    $data = $db->update('1', $updateProduct); //the first parameter ('1') is the product id
    print_r($data); //returns an array with the product data (updated)
    /*
        Array
        (
            [0] => stdClass Object
                (
                    [id] => 1
                    [productname] => XBOX Series S 512GB
                    [price] => 319.99
                    [categoryid] => 1
                )
        )
    */
}
catch(Exception $e){
    echo $e->getMessage();
}

删除数据

要从表中删除记录,只需调用delete方法,并将待删除记录的id(PK)作为参数传递。

以下代码删除了products表中的id=1的产品

$db = $service->initializeDatabase('products', 'id');

try{
    $data = $db->delete('1'); //the parameter ('1') is the product id
    echo 'Product deleted successfully';
}
catch(Exception $e){
    echo $e->getMessage();
}

获取数据

Database类中提供了以下方法来获取数据

  • fetchAll():获取所有表记录;
  • findBy(string $column, string $value):按列/值(使用=运算符)获取过滤记录;
  • findByLike(string $column, string $value):按列/值(使用LIKE运算符)获取过滤记录;
  • join(string $foreignTable, string $foreignKey):在设置的表和另一个相关表之间创建join并获取记录;
  • createCustomQuery(array $args):构建自定义SQL查询。以下keysargs参数有效
    • select
    • from
    • join
    • where
    • limit
    • range

所有上述方法都返回Database类的自实例。要访问获取到的数据,请调用getResult方法。

查看一些示例

$db = $service->initializeDatabase('products', 'id');

try{
    $listProducts = $db->fetchAll()->getResult(); //fetch all products
    foreach ($listProducts as $product){
        echo $product->id . ' - ' . $product->productname . '($' . $product->price . ') <br />';
    }
}
catch(Exception $e){
    echo $e->getMessage();
}

现在,使用findBy方法的一个示例

$db = $service->initializeDatabase('products', 'id');

try{
    $listProducts = $db->findBy('productname', 'PlayStation 5')->getResult(); //Searches for products that have the value "PlayStation 5" in the "productname" column
    foreach ($listProducts as $product){
        echo $product->id . ' - ' . $product->productname . '($' . $product->price . ') <br />';
    }
}
catch(Exception $e){
    echo $e->getMessage();
}

搜索products并添加与categories表的连接

$db = $service->initializeDatabase('products', 'id');

try{
    $listProducts = $db->join('categories', 'id')->getResult(); //fetch data from "products" JOIN "categories"
    foreach ($listProducts as $product){
        //SHOW "productname" - "categoryname"
        echo $product->productname . ' - ' . $product->categories->categoryname . '<br />';
    }
}
catch(Exception $e){
    echo $e->getMessage();
}

搜索所有价格(price大于200.00)的idproductnameprice的所有products的自定义查询示例,"JOIN" categories过滤

$db = $service->initializeDatabase('products', 'id');

$query = [
    'select' => 'id,productname,price',
    'from'   => 'products',
    'join'   => [
        [
            'table' => 'categories',
            'tablekey' => 'id'
        ]
    ],
    'where' => 
    [
        'price' => 'gt.200' //"gt" means "greater than" (>)
    ]
];

try{
    $listProducts = $db->createCustomQuery($query)->getResult();
    foreach ($listProducts as $product){
        echo $product->id . ' - ' . $product->productname . '($' . $product->price . ') <br />';
    }
}
catch(Exception $e){
    echo $e->getMessage();
}

自定义查询的其他示例

//products with price > 200 AND productname LIKE '%n%'
$query = [
    'select' => 'id,productname,price',
    'from'   => 'products',
    'where' => 
    [
        'price' => 'gt.200', //"gt" means "greater than" (>)
        'productname' => 'like.%n%' //like operator
    ]
];

//products with categoryid = 1
$query = [
    'select' => 'id,productname,price',
    'from'   => 'products',
    'where' => 
    [
        'categoryid' => 'eq.1', //"eq" means "equal" (=)
    ]
];

//products with price < 1000 LIMIT 4 results
$query = [
    'select' => 'id,productname,price',
    'from'   => 'products',
    'where' => 
    [
        'price' => 'lt.1000', //"lt" means "less than" (<)
    ],
    'limit' => 4 //4 first rows
];

比较运算符

可用于where子句的主要运算符

  • eq:等于
  • neq:不等于
  • gt:大于
  • gte:大于等于
  • lt:小于
  • lte:小于等于
  • like:在列中搜索指定的模式
  • ilike:在列中搜索指定的模式(不区分大小写)

其他可用运算符

  • is
  • in
  • cs
  • cd
  • sl
  • sr
  • nxl
  • nxr
  • adj
  • ov
  • fts
  • plfts
  • phfts
  • wfts
  • not.eq
  • not.neq
  • not.gt
  • not.gte
  • not.lt
  • not.lte
  • not.like
  • not.ilike
  • not.is
  • not.in
  • not.cs
  • not.cd
  • not.sl
  • not.sr
  • not.nxl
  • not.nxr
  • not.adj
  • not.ov
  • not.fts
  • not.plfts
  • not.phfts
  • not.wfts

QueryBuilder 类

QueryBuilder类提供动态构建SQL查询的方法。它从service对象实例化。

$query = $service->initializeQueryBuilder();

注意:如果任何使用的表启用了行级安全(RLS),则将bearerToken传递给Service对象

$bearerToken = 'THE_ACCESS_TOKEN'; //returned in the login action.
$query = $service->setBearerToken($bearerToken)->initializeQueryBuilder();

可用方法

  • select(string $select):字段(以逗号分隔)或*
  • from(string $from):表
  • join(string $table, string $tablekey, string $select = null):相关表
  • where(string $column, string $value):条件
  • limit(int $limit):限制行数
  • order(string $order):排序字段
  • range(string $range):结果范围(例如:“0-3”)

所有提到的方法都返回QueryBuilder类的自身实例。要运行挂载的查询,请调用execute方法。然后,要访问检索到的数据,请调用getResult方法。

products表获取所有数据的示例

$query = $service->initializeQueryBuilder();

try{
    $listProducts = $query->select('*')
                ->from('products')
                ->execute()
                ->getResult();
    foreach ($listProducts as $product){
        echo $product->id . ' - ' . $product->productname . '($' . $product->price . ') <br />';
    }
}
catch(Exception $e){
    echo $e->getMessage();
}

products "JOIN" categories获取所有数据的示例

$query = $service->initializeQueryBuilder();

try{
    $listProducts = $query->select('*')
                ->from('products')
                ->join('categories', 'id')
                ->execute()
                ->getResult();
    foreach ($listProducts as $product){
        echo $product->id . ' - ' . $product->productname . '($' . $product->price . ') - '. $product->categories->categoryname .' <br />';
    }
}
catch(Exception $e){
    echo $e->getMessage();
}

按价格排序获取categoryid=1price>200products

$query = $service->initializeQueryBuilder();

try{
    $listProducts = $query->select('*')
                ->from('products')
                ->join('categories', 'id')
                ->where('categoryid', 'eq.1') //eq -> equal
                ->where('price', 'gt.200') // gt -> greater than
                ->order('price.asc') //"price.desc" for descending
                ->execute()
                ->getResult();
    foreach ($listProducts as $product){
        echo $product->id . ' - ' . $product->productname . '($' . $product->price . ') - '. $product->categories->categoryname .' <br />';
    }
}
catch(Exception $e){
    echo $e->getMessage();
}

where方法中使用的某些运算符可在比较运算符部分中查看。