dgvirtual / codeigniter4-meta-info
Codeigniter4 library enabling use of Entity-Attribute-Value style storage for additional fields of models.
Requires
- php: ^8.1
Requires (Dev)
- codeigniter4/devkit: ^1.3
- codeigniter4/framework: ^4.5
This package is auto-updated.
Last update: 2025-04-22 19:40:42 UTC
README
CodeIgniter4 Meta Info library enables use of Entity-Attribute-Value style storage for additional data of entities used with your models. Library is based on code from Bonfire2 project. It allows storing user-configurable bits of information for your project's entity classes without the need to modify those classes.
Usage case
Lets say you have a users
table to store data of users. Suppose you need to add aditional fields
to the user table to store additional information, whether this is a bio, a website URL, social
links, or anything else.
You can either change the main table each time you need such changes, or, alternatively, – store such data in a separate table, without constantly changing the database schema.
Using this library you can add additional information to a user. Moreover, such data can be seamlessly integrated into the Create/Edit User form so you do not have to modify that one manually on each change of user data schema.
Installation
Install via Composer (you will have to set minimum stability to dev, as this is pre-release library):
composer config minimum-stability dev
composer require dgvirtual/codeigniter4-meta-info
Then run the migration to setup the database table meta_info (assuming you already configured your database):
php spark migrate -n \Dgvirtual\MetaInfo
Setup 1. Defining Meta Fields
If you want to get a functionality preview, you can enable the demo code (read the section demo below).
First you create a config class for your users table, app/Config/Users.php
. Put a property
$metaFields
into that class:
public $metaFields = [ 'Social Links' => [ 'blog' => [ 'label' => 'Blog', 'type' => 'text', 'validation' => 'permit_empty|valid_url_strict' ], ], ];
In the above example:
Social links
is a subcategory that can later be used to build a categorized view for the data;- the key
type
corresponds to the field type (text, checkbox, etc.) in the view (Supportedtype
values: checkbox, textarea, text, and other "text" variants: number, password, email, tel, url, date, time, week, month, color). blog
is thecolumn
for our data.
The other fields are used for data validation:
label
will act as label for validation rule and a label for HTML input, andvalidation
key => value pair will be transformed into arules
with validation rules as value.
Setup 2. Adding Trait to your Entity class
Add the HasMeta
trait and a protected $configClass
property with a string value, the name of the
above-mentioned Config class containing $metaFields
array, to the Entity class that represents
your resource.
use Dgvirtual\MetaInfo\Traits\HasMeta; use CodeIgniter\Entity; class User extends Entity { use HasMeta; protected string $configClass = 'Users'; }
Manipulating data
The User entity has a trait applied, HasMeta
, that provides all the functionality you should need
to work with the meta information for that user.
meta(string $key)
This returns the value of the user's meta named $key
, or null
if nothing has been set for that
user. The name is the key of the array mentioned above.
$blog = $user->meta('blog');
allMeta()
This returns all meta fields for this user. Note that it returns the full database results, not just the name/value.
$meta = $user->allMeta(); var_dump($meta); // Returns: [ 'resource_id' => 123, 'class' => 'App\Entities\User', 'key' => 'blog', 'value' => 'http://example.com', 'created_at' => '2025-01-12 12:31:12', 'updated_at' => '2025-01-12 12:31:12', ]
hasMeta(string $key)
Used to check if a user has a value set for the given meta field.
if ($user->hasMeta('foo')) { // }
saveMeta(string $key, $value)
Saves a single meta value to the user. This is immediately saved. There is no need to save the User through the UserModel.
$url = $this->request->getPost('blog'); $user->saveMeta('blog', $url);
deleteMeta(string $key)
Deletes a single meta value from the user. This is immediately deleted. There is no need to save the User through the UserModel.
$user->deleteMeta('blog');
deleteResourceMeta()
Deletes all meta info associated with an entity. To be used when purging a record.
$user->deletResouceMeta();
syncMeta(array $post)
Given an array of key/value pairs representing the name of the meta field and it's value, this will update existing meta values, insert new ones, and delete any ones that were not passed in. Useful when grabbing the information from a form and updating all the values at once.
$post = [ 'blog' => 'http://example.com', 'fb' => 'johnny.rose' ]; $user->syncMeta($post);
syncMeta()
will also delete meta data for the resource that is present in meta_info
but not
present in the corresponding config file's $metaFields
property, and therefore not used (usually
happens if you change $metaFields
at some point, thus orphaning some data).
metaValidationRules(string $prefix=null)
This examines the specified config file and returns an array with the names of each field and their
validation rules, ready to be used within CodeIgniter's validation library. If your form groups the
name as an array, (like meta[blog]
) you may specify the prefix to append to the field names so
that validation will pick it up properly.
$rules = $user->metaValidationRules('meta'); var_dump($rules); // Returns: [ 'meta.blog' => 'required|string|valid_url', ]
Using views for meta info display/editing
You can use directly (or copy and adapt) views in src/Views/
to include the meta info in your CRUD
views as, for example, view cells, for display (meta_display
) or editing (meta_edit
). See how
that is done in the Demo code.
Using the library for searches
You will want to get the data from meta_info table the same way you would from a related table, and, for example, display it in search results.
Of course that is not as simple as when using a simple join.
To do that you will need to employ WithMeta
trait in your model:
namespace App\Models; use App\Entities\User; use CodeIgniter\Model; use Dgvirtual\MetaInfo\Traits\WithMeta; class UserModel extends Model { use WithMeta; // other code }
Now you can use the methods provided by WithMeta to build queries. For example, you can write the
search()
method in your model employing the trait methods generateMetaSelectClause
,
joinMetaInfo
and orLikeInMetaInfo()
when constructing the query; for example:
public function search(string $term, int $limit = 100, int $offset = 0): array { $termInMeta = config(\Config\Users::class)->includeMetaFieldsInSearch; // First: get the expanded select clause that includes info from meta_info table $selectClause = $this->generateMetaSelectClause($termInMeta, \App\Entities\User::class); $query = $this->select($selectClause)->distinct(); if (!empty($termInMeta)) { // Second: generate the join statement // here the User::class is string representation of the entity class $query->joinMetaInfo(\App\Entities\User::class, $this->table); } if ($term) { $query->like('first_name', $term, 'right', true, true) ->orLike('last_name', $term, 'right', true, true) ->orLike('username', $term, 'right', true, true); if (!empty($termInMeta)) { foreach ($termInMeta as $metaField) { // Third: perform the search through like statements $query->orLikeInMetaInfo($metaField, $term, 'both', true, true); } } } return $query->findAll($limit, $offset); }
This method can now be used in controllers to perform searches and get information with data from meta_info table neatly integrated into the data from the main table.
Demo
A demo is provided with this library. Enabling demo would create a table testusers
in your DB,
which you can remove later.
Steps to enable the demo:
-
update Config\Autoload class to include demo namespace into the list of available namespaces:
public $psr4 = [ APP_NAMESPACE => APPPATH, // add two lines temporarily: 'Dgvirtual\Demo' => ROOTPATH . 'vendor/dgvirtual/codeigniter4-meta-info/demo', 'Tests\Support' => ROOTPATH . 'vendor/dgvirtual/codeigniter4-meta-info/tests/_support', ];
-
Setup the database if you have not done so already, then migrate and seed the demo table:
php spark migrate -n \Dgvirtual\MetaInfo php spark migrate -n \Dgvirtual\Demo php spark db:seed \Tests\Support\Database\Seeds\TestusersSeeder
-
Copy the routes you will need into your Config\Routes.php file:
$routes->group('testusers', ['namespace' => 'Dgvirtual\Demo\Controllers'], static function ($routes) { $routes->get('', 'TestusersController::index'); $routes->get('create', 'TestusersController::create'); $routes->get('edit/(:num)', 'TestusersController::edit/$1'); $routes->get('display/(:num)', 'TestusersController::display/$1'); $routes->post('save', 'TestusersController::save'); $routes->post('save/(:num)', 'TestusersController::save/$1'); $routes->post('delete/(:num)', 'TestusersController::delete/$1'); }); $routes->get('meta_info', '\Dgvirtual\Demo\Controllers\MetaInfoController::index');
Now you can run
php spark serve
and open the demo at http://localhost:8080/testusers -
To modify the meta fields assigned to the
testuser
you can copy the demo's fileConfig/Testusers.php
toapp/Config
, change it's namespace toConfig
and modify it to your liking; the changes will be reflected in the demo'screate
andedit
pages. The display page does not use a dynamic template, so it will remain the same.
To disable the demo, please undo the above-mentioned changes in files. To remove the demo table, use Codeigniter4 migration rollback functionality.
Contributing
If you would like to contribute to this project, please fork the repository and submit a pull request.
Credits
This library was created by Donatas Glodenis. You can reach out to me at [dg@lapas.info] for any questions or feedback.
The library started as an adaptation of Bonfire2 Users meta info functionality for general CodeIgniter 4 use. Bonfire2 was created by Lonnie Ezell lonnieje@gmail.com and contributors. For more information, visit the Bonfire2 project.
License
This project is licensed under the MIT License. See the LICENSE file for details.