Open5
Spiral Framework の必要情報を雑にまとめる
ORM周りの実装
エンティティを作る
php app.php create:entity task -f id:primary -f title:string -f content:text -e
これで、ひな型とリポジトリが作成される。
/**
* @Cycle\Entity(repository="\App\Repository\TaskRepository")
*/
class Task
{
/**
* @Cycle\Column(type = "primary")
*/
public $id;
/**
* @Cycle\Column(type = "string")
*/
public $title;
/**
* @Cycle\Column(type = "text")
*/
public $content;
}
と
class TaskRepository extends Repository
{
}
リレーション
リレーションはいろんなやり方がありそうだけど、一応アノテーション使う
<?php
declare(strict_types=1);
namespace App\Database;
use Cycle\Annotated\Annotation as Cycle;
use Cycle\Annotated\Annotation\Relation\BelongsTo;
/**
* @Cycle\Entity(repository="\App\Repository\CommentRepository")
*/
class Comment
{
/**
* @Cycle\Column(type = "primary")
*/
public $id;
/**
* @BelongsTo(target = "Task", nullable=false)
*/
public $task;
/**
* @Cycle\Column(type = "text")
*/
public $content;
}
これでマイグレーションを作ると外部キーとかも作ってくれる
php app.php cycle:migrate -v
<?php
namespace Migration;
use Spiral\Migrations\Migration;
class OrmDefault7a811cafb53185 extends Migration
{
protected const DATABASE = 'default';
public function up(): void
{
$this->table('comments')
->addColumn('id', 'primary', [
'nullable' => false,
'default' => null
])
->addColumn('content', 'text', [
'nullable' => false,
'default' => null
])
->addColumn('task_id', 'integer', [
'nullable' => false,
'default' => null
])
->addIndex(["task_id"], [
'name' => 'comments_index_task_id_60dece74ef2e7',
'unique' => false
])
->addForeignKey(["task_id"], 'tasks', ["id"], [
'name' => 'comments_foreign_task_id_60dece74ef303',
'delete' => 'CASCADE',
'update' => 'CASCADE'
])
->setPrimaryKeys(["id"])
->create();
}
public function down(): void
{
$this->table('comments')->drop();
}
}
リレーション含めた保存とかはこんな感じ。
public function testSaveWithTask()
{
$task = new Task;
$task->title = 'あいうえお';
$task->content = 'かきくけこ';
$comment = new Comment;
$comment->content = 'たちつてと';
$comment->task = $task;
$tr = $this->app->get(TransactionInterface::class);
$tr->persist($comment);
$tr->run();
$orm = $this->app->get(ORM::class);
$todo = $orm->getRepository(Task::class)->findOne(['title' => $task->title]);
$comm = $orm->getRepository(Comment::class)->findOne(['content' => $comment->content]);
$this->assertEquals($task->content, $todo->content);
$this->assertEquals($comment->content, $comm->content);
}
}
HasMany 側のセーブ
こんな感じで行けそう。
Task.php
/**
* @HasMany(target = "Comment")
*/
public $comments;
public function __construct()
{
$this->comments = new ArrayCollection;
}
public function testSaveWithComment()
{
$task = new Task;
$task->title = 'あいうえお';
$task->content = 'かきくけこ';
$comment = new Comment;
$comment->content = 'たちつてと';
// コメントに追加
$task->comments->add($comment);
$tr = $this->app->get(TransactionInterface::class);
$tr->persist($task);
$tr->run();
$orm = $this->app->get(ORM::class);
$todo = $orm->getRepository(Task::class)->findOne(['title' => $task->title]);
$comm = $orm->getRepository(Comment::class)->findOne(['content' => $comment->content]);
$this->assertEquals($task->content, $todo->content);
$this->assertEquals($comment->content, $comm->content);
}
どうせならリポジトリに書きたい
永続化時にIDは足される。
public function testSaveWithComment()
{
//......
$this->assertEquals($todo->id, $task->id);
$this->assertEquals($comm->id, $comment->id);
}
ManyToMany
これもアノテーションで行ける
<?php
//....
class Battle
{
//....
/** @ManyToMany(target = "User", though = "BattleUser") */
public $users;
public function __construct()
{
$this->users = new PivotedCollection;
}
}
保存するときは
$battle = new Battle;
$battle->users->add($user1);
$battle->users->add($user2);
/** @var TransactionInterface */
$tr->persist($battle);
$tr->run();
中間テーブルに値を入れたい場合は、
<?php
/**
* {project-name}
*
* @author {author-name}
*/
declare(strict_types=1);
namespace App\Database;
use Cycle\Annotated\Annotation as Cycle;
/**
* @Cycle\Entity()
*/
class BattleUser
{
/**
* @Cycle\Column(type = "bigPrimary")
*/
public $id;
/**
* @Cycle\Column(type = "boolean")
*/
public $is_win;
public function __construct(bool $is_win)
{
$this->is_win = $is_win;
}
}
のように定義しておいて、
$battle = new Battle;
$battle->users->add($user1);
$battle->users->setPivot($user1, new BattleUser(true));
$battle->users->add($user2);
$battle->users->setPivot($user2, new BattleUser(false));
/** @var TransactionInterface */
$tr->persist($battle);
$tr->run();
これで行ける。