Skip to content

Commit d09032c

Browse files
committed
Initial commit
0 parents  commit d09032c

File tree

5 files changed

+245
-0
lines changed

5 files changed

+245
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.idea
2+
/vendor
3+
/coverage
4+
composer.lock

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2023-present Markus Wetzel
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Eloquent Inheritance
2+
3+
[![Latest Stable Version](https://poser.pugx.org/proai/eloquent-inheritance/v/stable)](https://packagist.org/packages/proai/eloquent-inheritance) [![Total Downloads](https://poser.pugx.org/proai/eloquent-inheritance/downloads)](https://packagist.org/packages/proai/eloquent-inheritance) [![Latest Unstable Version](https://poser.pugx.org/proai/eloquent-inheritance/v/unstable)](https://packagist.org/packages/proai/eloquent-inheritance) [![License](https://poser.pugx.org/proai/eloquent-inheritance/license)](https://packagist.org/packages/proai/eloquent-inheritance)
4+
5+
Single table inheritance is a way to emulate object-oriented inheritance in a relational database. While other frameworks like Ruby on Rails have a built-in implementation for this pattern, Laravel has not. This package aims to provide an as easy as possible implementation for Laravel.
6+
7+
## Installation
8+
9+
You can install the package via composer:
10+
11+
```bash
12+
composer require proai/eloquent-inheritance
13+
```
14+
15+
Please note that you need at least **PHP 8.0** and **Laravel 9** for this package.
16+
17+
## Usage
18+
19+
First you need to add the `Inheritance` trait to your root model:
20+
21+
```php
22+
use ProAI\Inheritance\Inheritance;
23+
24+
class Pet extends Model
25+
{
26+
use Inheritance;
27+
28+
//
29+
}
30+
```
31+
32+
Then you can extend the root model by other models that use the same table:
33+
34+
```php
35+
class Cat extends Pet
36+
{
37+
//
38+
}
39+
40+
class Dog extends Pet
41+
{
42+
//
43+
}
44+
```
45+
46+
> Note that you need a table `pets` with a column called `type` in order to make the example above work.
47+
48+
Whenever a `Cat` or `Dog` model is instantiated, the attribute `type` will be set to the classname of the class (e.g. `App\Models\Cat`).
49+
50+
Other than that there is no magic and a `Cat` or a `Dog` model will behave just like a normal Eloquent model. You can define cat or dog specific attributes and relationships on these models. An attribute only set for dogs for example should be a nullable column on the table, so that it is set for dogs but `null` for other pets.
51+
52+
### Custom type column
53+
54+
By default the name of the type column is `type`. However, you can set a custom type column name:
55+
56+
```php
57+
use ProAI\Inheritance\Inheritance;
58+
59+
class Pet extends Model
60+
{
61+
use Inheritance;
62+
63+
protected static $inheritanceColumn = 'pet_type';
64+
}
65+
```
66+
67+
### Custom type name
68+
69+
If you want a different name than the classname, you can use the `$inheritanceType` property:
70+
71+
```php
72+
class Cat extends Pet
73+
{
74+
protected static $inheritanceType = 'cat';
75+
}
76+
```
77+
78+
> Hint: The value of `$inheritanceType` can also be an enum value.
79+
80+
## Support
81+
82+
Bugs and feature requests are tracked on [GitHub](https://github.com/proai/eloquent-inheritance/issues).
83+
84+
## License
85+
86+
This package is released under the [MIT License](LICENSE).

composer.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "proai/eloquent-versioning",
3+
"description": "Single table inheritance for Laravel inspired by the Rails implementation",
4+
"keywords": [
5+
"laravel",
6+
"orm",
7+
"eloquent",
8+
"single",
9+
"table",
10+
"inheritance"
11+
],
12+
"homepage": "http://github.com/ProAI/eloquent-inheritance",
13+
"license": "MIT",
14+
"authors": [
15+
{
16+
"name": "Markus J. Wetzel",
17+
"email": "[email protected]"
18+
}
19+
],
20+
"require": {
21+
"php": "^8.0",
22+
"illuminate/support": "^9.0||^10.0"
23+
},
24+
"require-dev": {
25+
"orchestra/testbench": "^7.0||^8.0",
26+
"phpunit/phpunit": "^9.5.10||^10.0"
27+
},
28+
"autoload": {
29+
"psr-4": {
30+
"ProAI\\Inheritance\\": "src/"
31+
}
32+
},
33+
"autoload-dev": {
34+
"psr-4": {
35+
"ProAI\\Inheritance\\Tests\\": "tests/"
36+
}
37+
}
38+
}

src/Inheritance.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
namespace ProAI\Inheritance;
4+
5+
use Illuminate\Support\Str;
6+
7+
trait Inheritance
8+
{
9+
/**
10+
* Defines the column name for use with single table inheritance.
11+
*
12+
* @var string
13+
*/
14+
public static $inheritanceColumn = 'type';
15+
16+
/**
17+
* Defines the type name for use with single table inheritance.
18+
*
19+
* @var mixed
20+
*/
21+
public static $inheritanceType;
22+
23+
/**
24+
* Bootstrap the inheritance trait.
25+
*
26+
* @return void
27+
*/
28+
protected static function bootInheritance()
29+
{
30+
if (! static::modelInherited()) {
31+
return;
32+
}
33+
34+
static::addGlobalScope(function ($query) {
35+
$query->where(static::$inheritanceColumn, static::getInheritanceType());
36+
});
37+
38+
static::creating(function ($model) {
39+
$model->{static::$inheritanceColumn} = static::getInheritanceType();
40+
});
41+
}
42+
43+
/**
44+
* Check if model is inherited.
45+
*
46+
* @return bool
47+
*/
48+
protected static function modelInherited()
49+
{
50+
return self::class !== static::class;
51+
}
52+
53+
/**
54+
* Get the column name for use with single table inheritance.
55+
*
56+
* @return mixed
57+
*/
58+
protected static function getInheritanceType()
59+
{
60+
if (isset(static::$inheritanceType)) {
61+
return static::$inheritanceType;
62+
}
63+
64+
return static::$inheritanceType = static::class;
65+
}
66+
67+
/**
68+
* Get the table associated with the model.
69+
*
70+
* @return string
71+
*/
72+
public function getTable()
73+
{
74+
return $this->table ?? Str::snake(Str::pluralStudly(class_basename($this->getRootClass())));
75+
}
76+
77+
/**
78+
* Get the default foreign key name for the model.
79+
*
80+
* @return string
81+
*/
82+
public function getForeignKey()
83+
{
84+
return Str::snake(class_basename($this->getRootClass())).'_'.$this->getKeyName();
85+
}
86+
87+
/**
88+
* Get the class name of the root class.
89+
*
90+
* @return string
91+
*/
92+
protected function getRootClass()
93+
{
94+
return self::class;
95+
}
96+
}

0 commit comments

Comments
 (0)