PHPackages                             jelix/profiles - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. jelix/profiles

ActiveLibrary[Database &amp; ORM](/categories/database)

jelix/profiles
==============

API to manage access and credentials data

v1.3.1(10mo ago)0139LGPL-2.1PHPPHP &gt;=7.2

Since Feb 23Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/jelix/JelixProfiles)[ Packagist](https://packagist.org/packages/jelix/profiles)[ Docs](http://jelix.org)[ RSS](/packages/jelix-profiles/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (1)Versions (7)Used By (0)

API to manage profiles containing access and credentials data.

A profile contains information to access to a service. A service could be a database, a web API for axampe. Inside an application, you can have different profiles for the same type of service.

JelixProfiles allows to indicate those profiles into an ini file. All credentials are then stored into a single file. When a component of your application (let's call it a "connector") needs information about a profile, it will use JelixProfiles.

installation
============

[](#installation)

You can install it from Composer. In your project:

```
composer require "jelix/profiles"

```

configuration
=============

[](#configuration)

Profiles data should be stored into an ini file. This file contains connections parameters needed by your application components: SQL and NoSQL databases, SOAP web services, cache etc.

profile parameters
------------------

[](#profile-parameters)

Each section corresponds to a profile. A profile is a set of parameters of a single connection. Sections names are composed of two names, separated by a ":":

- First name is the name of the connection type, (often corresponding to the composant name)
- Second name is a name of your choice. However, two names have a special meaning: `default` indicates the default profile to use if the profile name is not given. And `__common__`, described below.

The content of the section content connection parameters.

Here is an example for the JelixDatabase component (It allows to access to a SQL database):

```
[jdb:default]
driver=mysqli
host=localhost
login= mylogin
password=mypassword
```

Profile alias
-------------

[](#profile-alias)

You can define some profile alias, i.e. more than one name to a profile. This is useful for example when two libraries use a different profile name, but you want that these libraries use the same connection parameters.

Aliases are defined in a section whose name contains only the name of the connection type. An example with JelixDatabase, defining the alias "jacl2\_profile" for the default profile:

```
[jdb]
jacl2_profile = default

[jdb:default]
driver=mysqli
host=localhost
login= mylogin
password=mypassword
```

An alias should not be linked to another alias.

Common parameters
-----------------

[](#common-parameters)

It is possible to define parameters that are common to all profiles of the same type. This avoids repeating them in each profile. To do this, you must declare them in a special profile, `__common__`.

For example, if all connections to SQL databases must be persistent and are all on the same server:

```
[jdb:__common__]
host=my.server.example.com
persistant=on
```

Of course you can redefine these parameters in profiles.

Using environment variables
---------------------------

[](#using-environment-variables)

Ini files are readed by the `parse_ini_file` function, and so specific syntaxes are available to indicate values coming from outside the ini file.

- You can indicate PHP constants:

```
# somewhere in a file included by your index.php
define("SOMETHING", "hello world");
```

In one of your ini file:

```
foo = SOMETHING
```

Then foo will have the value `"hello world"`.

- You can indicate environment variables:

```
# variables set in the environment of PHP-FPM, PHP-CLI, or Apache (with the PHP module)
MYAPP_MYSQL_LOGIN=admin
MYAPP_MYSQL_PASSWORD=Sup3Rp4ssw0rd!
```

Example, in your ini file, you have to use this syntax `${VARIABLE_NAME}`:

```
[jdb:default]
driver=mysqli
login= ${MYAPP_MYSQL_LOGIN}
password= ${MYAPP_MYSQL_PASSWORD}
```

usage
=====

[](#usage)

You should use the `ProfilesReader` object, that will read the ini file, and store results into a `ProfilesContainer` object. With this object, you will be able to get data of a profile.

If you have this kind of profiles.ini file:

```
[jdb:default]
driver=mysqli
host=localhost
login= mylogin
password=mypassword
```

In the code of the component which uses JelixProfiles:

```
$iniFile = '/somewhere/profiles.ini';
$cacheFile = '/somewhere/profiles.cache.json';

$reader = new \Jelix\Profiles\ProfilesReader();

/** @var \Jelix\Profiles\ProfilesContainer $profiles */
$profiles = $reader->readFromFile($iniFile, $cacheFile);

// get the profile named 'foo' for the type 'jdb'
$profile = $profiles->get('jdb', 'default');

$myDatabaseConnection = new Database(
    $profile['driver'],
    $profile['host'],
    $profile['login'],
    $profile['password']
);
```

Note that you have to give a cache file to `readFromFile`. It allows JelixProfiles to save extra parameters computed during the loading of the ini file.

Virtual profile
---------------

[](#virtual-profile)

You can use a profile which is not declared into the ini file. So you can use a connection whose information are known only during the execution.

A virtual profile must be created before using your component. Use `createVirtualProfile()` method of the object `ProfilesContainer` and pass the type name of connection, a name and an array of parameters.

Example:

```
// let's retrieve a profiles container
$iniFile = '/somewhere/profiles.ini';
$cacheFile = '/somewhere/profiles.cache.json';
$reader = new \Jelix\Profiles\ProfilesReader();
/** @var \Jelix\Profiles\ProfilesContainer $profiles */
$profiles = $reader->readFromFile($iniFile, $cacheFile);

// now create our virtual profile
$params = array(
   'driver'=>'mysqli',
   'host'=>'localhost',
   'database'=>'jelix',
   'user'=>'toto',
   'password'=>'blabla',
   'persistent'=>false,
   'force_encoding'=>true
);
$profiles->createVirtualProfile('jdb', 'my_profil', $params);

// somewhere else
$profile = $profiles->get('jdb', 'my_profil');

//...
```

Of course, all parameters defined in a `__common__` profile apply on virtual profiles.

Using plugins to check parameters
=================================

[](#using-plugins-to-check-parameters)

The connector, the object that uses a profile, may expect to have specific parameters. It may have to check if parameters are ok before using them. It even may have to "calculate" some other parameters, depending on values it finds into given parameters.

To avoid doing these checks or calculation each time the connector is instantiated, there is a solution into JelixProfiles to process these things during the first read of the profiles file, then final parameters are stored into the cache file of profiles.

You can provide a plugin that will do these checks and calculations for a specific category of profiles. This is a class that should inherit from `Jelix\Profiles\ReaderPlugin`, and implements the `consolidate` method which receives the profile parameters as an array, and which returns the completed profile.

Example:

```
// example of a plugin that process a profile containing access parameters to an SQL database
class myDbPlugin extends \Jelix\Profiles\ReaderPlugin
{

    protected function consolidate($profile)
    {
        $newProfile = $profile;
        // Check that the `host` parameter does exist
        if (!isset($profile['driver']) || $profile['driver'] == '' ||
            !isset($profile['host']) || $profile['host'] == '' ||
            !isset($profile['database']) || $profile['database'] == ''
        ) {
            throw new  \Exception('host or database are missing from the profile');
        }

        // check if port is present, if not, let's set a default value
        if (!isset($profile['port']) {
            $profile['port'] = 1234;
        }

        if ($driver == 'pgsql') {
            // let's generate a connection string
            $newProfile['connectionstr'] = 'host='.$profile['host'].';port='.$profile['port'].'database='.$profile['database'];
        }

        // here you probably want to do more checks etc, but for the example, it is enough.

        // return a new profile, that is ready to be used by your database connection object without checking
        // parameters or calculate connectionstr, at each http requests, because all these parameters will be stored
        // into a cache by ProfilesReader
        return $newProfile;
    }
}
```

Next, you have to indicate this plugin to ProfilesReader, by giving the list of plugins corresponding to each category.

```
$reader = new \Jelix\Profiles\ProfilesReader([
    // category name => plugin class name
    'db' => 'myDbPlugin'
]);
```

Another way is to provide a callback function which will return the plugin corresponding to the given category. It is useful if your plugin has a specific constructor, or if the class is loaded in a specific way.

```
class myDbPlugin extends \Jelix\Profiles\ReaderPlugin
{
    // for the example, let's redefine the constructor to have a different constructor than ReaderPlugin...
    public function __construct() {}

    // ...
}

$reader = new \Jelix\Profiles\ProfilesReader(function($category) {
    if ($category == 'db') {
        return new myDbPlugin();
    }
    return null;
});
```

Using plugins to instantiate automatically connectors
=====================================================

[](#using-plugins-to-instantiate-automatically-connectors)

We saw that you can retrieve a profile, and then you have to give it to your connector object:

```
$profile = $profiles->get('jdb', 'default');

$myDatabaseConnection = new Database(
    $profile['driver'],
    $profile['host'],
    $profile['login'],
    $profile['password']
);
```

`ProfilesContainer` has a method to instantiate automatically the connector corresponding to the profile, and it allows also to use the same connector object during all the process of an http request. And your code is less heavy:

```
$myDatabaseConnection = $profiles->getConnector('jdb', 'default');
```

In order to use this method, the plugin must implement the `Jelix\Profiles\ProfileInstancePluginInterface`. It has two methods, `getInstanceForPool($name, $profile)` and `closeInstanceForPool($name, $instance)`.

The first one is to instantiate the connector object. It is called by `getConnector`. The second method should terminate the connector object. For example, if the connector object maintains a connection to a database, `closeInstanceForPool()` should call its methods that close the connection.

```
class myDbPlugin extends \Jelix\Profiles\ReaderPlugin implements
{
    protected function consolidate($profile)
    {
        // ...
    }

    public function getInstanceForPool($name, $profile)
    {
        return new Database(
          $profile['driver'],
          $profile['host'],
          $profile['login'],
          $profile['password']
        );
    }

    /**
     * @param string $name
     * @param Database $instance
     * @return void
     */
    public function closeInstanceForPool($name, $instance)
    {
        $instance->close()
    }
}
```

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance67

Regular maintenance activity

Popularity10

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~389 days

Recently: every ~427 days

Total

6

Last Release

328d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ae8142be36568660282368ce7c1eec904ecbc515ab5b58c759a487f3a6f1d114?d=identicon)[laurentj](/maintainers/laurentj)

![](https://www.gravatar.com/avatar/baa42c7323bbc9245b0c70f770031383879941a1a813f678f2835699fd50b375?d=identicon)[mdouchin](/maintainers/mdouchin)

---

Top Contributors

[![laurentj](https://avatars.githubusercontent.com/u/336034?v=4)](https://github.com/laurentj "laurentj (17 commits)")

---

Tags

databaseaccessprofilescredentials

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/jelix-profiles/health.svg)

```
[![Health](https://phpackages.com/badges/jelix-profiles/health.svg)](https://phpackages.com/packages/jelix-profiles)
```

###  Alternatives

[doctrine/dbal

Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.

9.7k578.4M5.6k](/packages/doctrine-dbal)[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[doctrine/doctrine-bundle

Symfony DoctrineBundle

4.8k241.3M3.3k](/packages/doctrine-doctrine-bundle)[doctrine/migrations

PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.

4.8k204.8M440](/packages/doctrine-migrations)[doctrine/data-fixtures

Data Fixtures for all Doctrine Object Managers

2.9k136.1M516](/packages/doctrine-data-fixtures)[robmorgan/phinx

Phinx makes it ridiculously easy to manage the database migrations for your PHP app.

4.5k46.2M405](/packages/robmorgan-phinx)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
