All packages are Nette 3 ready

This week the last packages static-router was tagged with support for Nette 3. This means that all our packages are ready. 🤗

Nextras Dbal 3.1+
Nextras Orm 3.1+
Nextras Migrations 3.1+
Nextras Form Components 1.0+ (formerly nextras/forms)
Nextras Forms Rendering 1.0+ (formerly nextras/forms)
Nextras Secured Links 1.5+
Nextras Datagrid 3.1+
Nextras Mail Panel 2.5+
Nextras Static Router 2.0+

Orm 3.1 – Property containers

Today we are releasing Nextras Orm 3.1 – a release without much features, but with plenty small fixes and enhancements. Let’s examine the major enhancement of property containers. Also, see full release notes.

Property containers

Until now, Orm property containers were quite limited to pretty simple functionality, such as converting encapsulating object as a JSON. (You may have read an article about implementing such container.) Some advanced transformations to class-backed enums were possible, but limited just to the entity interface. The conversion may have failed you just minute later. ICollection required non-converted values for Dbal queries and converted values for in-memory queries. In 3.1 this is fixed. Property containers may define the reverse deserialize function, which will be used in ICollection for proper comparison/query building. Let’s see an example:

We define an enum with marc-mabe/php-enum:

class GeometryType extends MabeEnum\Enum 
{
    const PLACE = 1;
    const CITY = 2;
    const COUNTRY = 3;
    const CONTINENT = 4;
}

Then we define generic reusable enum property container for enums. To this, we inherit from abstract helper class ImmutableValuePropertyContainer that already implements a lot of IPropertyContainer interface.

The definition of EnumContainer is reusable, e.g. you may use it multiple times in different properties with different enum classes. Of your you may write just one-time-purpose property containers.

use MabeEnum\Enum;
use Nextras\Orm\Entity\ImmutableValuePropertyContainer;
use Nextras\Orm\Entity\Reflection\PropertyMetadata;

class EnumContainer extends ImmutableValuePropertyContainer
{
    /** @var string */
    private $enumClass;

    public function __construct(PropertyMetadata $propertyMetadata)
    {
        parent::__construct($propertyMetadata);
        // check the property has one valid type
        assert(count($propertyMetadata->types) === 1);
        $this->enumClass = key($propertyMetadata->types);
        // check the enum class exists
        assert(class_exists($this->enumClass));
    }

    public function convertToRawValue($value)
    {
        assert($value instanceof Enum);
        return $value->getValue();
    }

    public function convertFromRawValue($value)
    {
        $enumClass = $this->enumClass;
        return $enumClass::byValue($value);
    }
}

By default ImmutableValuePropertyContainer allows null values, if you want the null to be part of enum, you have to override setRawValue, getRawValue respectively.

    public function setRawValue($value)
    {
        $this->value = $this->convertFromRawValue($value);
    }

    public function getRawValue()
    {
        return $this->convertToRawValue($this->value);
    }

The usage then is pretty simple:

/**
 * @property int|null          $id   {primary}
 * @property GeometryType|null $type {container EnumContainer}
 */
final class Geometry extends Entity {}

$geometry = new Geometry();
$geometry->type = GeometryType::PLACE();

Filtering require using proper enum instances:

$geometriesRepository->findBy([
    'type' => GeometryType::CONTINENT()
]);

Property containers may be uses to other data encapsulation use-cases. This enum examples nicely add type-safety to your code without much effort.

JSON in Nextras Orm 3.0

Storing an array/std-like object structure as json structure in one db column is pretty common use-case. However, the correct approach in Nextras Orm may not be obvious.


🔝 Use property container 😉

First, create your JSON container, by implementing abstract methods of predefined helper class ImmutableValuePropertyContainer.

use Nette\Utils\Json;
use Nextras\Orm\Entity\ImmutableValuePropertyContainer;

class JsonContainer extends ImmutableValuePropertyContainer
{
    protected function serialize($value)
    {
        return Json::encode($value); // or simple json_encode()
    }
    protected function deserialize($value)
    {
        return Json::decode($value); // or simple json_decode()
    }
}

Then, simply define your entity property with container:

/** 
 * ...
 * @property Nette\Utils\ArrayHash $data {container JsonContainer}
 */
class Users extends Nextras\Orm\Entity\Entity {}

Please note that ImmutableValuePropertyContainer API may lightly change in the future minor versions.


🆗 The second possible way is to write custom mapping in StorageReflection – add converter callbacks for your specific property.


🙈 The last possibility is to transform value in setters, getters and entity event callbacks. Please do not do this.

Nextras Orm 3.0

It’s here. It took more time than I have expected. Nextras Orm 3.0 comes with few major features, huge internal refactoring and many small fixes.

Check the release notes on GitHub and upgrade guide.

Collection Custom Functions & OR

Collection custom functions are a powerful enhancement of repository layer. Now you may do more advanced filtering & sorting of ICollection. We also added support for disjunction – OR filtering. As you might have guessed, it is internally also implemented as custom functions.

Custom functions hold the high level abstraction when being applied, though, they internally allow implementing low level behavior specific for the array and SQL storage.

// filter collection by entities with name Jan or age 10
$collection->findBy([
     ICollection::OR,
     ['name' => 'Jan'], 
     ['age' => 10], 
]);

Custom functions are quite powerful because the can be nested!

// filter collection by entities where name starts with Jan or age is 10
// note thet LikeFunction is not included in Orm
$collection->findBy([
     ICollection::OR,
     [LikeFunction::class, 'name', 'Jan'], 
     ['age' => 10], 
]);

Model

We have enhanced also the general model. Now it comes with two important functions:

  • clear() – flushes all the caches & references to entities;
  • refreshAll() – refreshes all data directly from the storage;

DateTimeImmutable

We have dropped support for \DateTime – sorry for that. On the other hand, we now support much better \DateTimeImmutable type.

PHP 7.0 scalar types & PHP 7.2

This release also adds scalar types where is it possible. We currently require PHP 7.0, therefore we do not use nullable types.

Also we have fixed support for PHP 7.2.

MSSQL support

We do not expect many of you will use Microsoft’s SQL server, though, this is quite nice feature and hopefully someone will be happy about that. Some of edge cases are not fully supported (e.g. there is an internal workaround). Please test it and report bugs 🙂


Thanks

I’d like to thank all the contributor and users. You support, question and Orm usage drives me in the further development. Namely I want to thank to Jan Tvrdik and David Matejka for the help with the development and valuable feedback and review. Thank to you guys.


Trainings

We have partnered with GeekyEdu and as a result there is the first Nextras Orm training ever in Prague. 🙂

The progress of Orm 3.0

Hi there! It’s been a while I have published some info about the upcoming release of Nextras Orm 3.0. So, what’s the current schedule?

Nextras Orm 3.0 will be released in 2017!

So, few notes to the current release plan:

  1. I apologize for such delay. The plans were quite extreme. I was not able to fulfill them. Though, many new great features will come, specifically: OR operator and custom functions.
  2. Some feature will be postponed: The most difficult part of these feature is the design. I would have a time to code them, but I had not enough time to design the API, to think it through, to validate the ideas. Also, this is a great oportunity for you to contribute: take a look and think how should the storage reflection factory look, how it should behave.
  3. Currently, only some minor features are missing. Personally, I have deployed current master branch to production of my quite big project. So I have already validated the stability and I expect quite a short RC phase.

The major features of Orm 3.0 will be:

  • OR operator: add a disjunction operator on collection: $collection->findBy(ICollection::OR, [...], [...]);
  • custom functions: create own filtering function to filter data over database and array collection;
  • IModel::refreshAll(): you may refresh the whole entity cache;
  • IModel::clear(): safely clear entity cache;
  • enforced DateTimeImmutable and full support for it;
  • fixed relationship caching, login, traversing;
  • PHP 7.0 type hints;
  • MS SQL Server support;

Orm will be released also with Dbal 3.0. Dbal will bring these features:

  • IConnection interface;
  • enhanced Tracy panel;
  • %json modifier;
  • nested transactions;
  • transaction isolation level;
  • MS SQL Server support;

Orm hackathon & plans for 3.0

Nextras Orm is getting more serious with every day. It has already passed 2000 installs per month! That is an exciting number!

The last weekend I, Jan Tvrdík and David Matějka have met to elaborate on Orm’s internal design and to hack some new needed features. We have discussed many topics, including mapper & repository architecture refactoring or support for new RDBMSes (such as MS SQL Server, which support is on the way into Nextras Dbal 3.0).

Finally, we agreed on the following hacking topics:

  • Refresh: implementing refresh is not an easy task, mainly because it’s pretty complicated to through the “refresh” consequences out; Therefore we decided to start with the easier possible implementation: Model::refreshAll() function that will refresh all loaded entities in your identity map. David Matejka was hacking this and it is available in a pull-request.
  • ICollection operations: another broad topic which should bring you a lot of variability for your collections. This feature should allow you to define special filtering implementations in your mapper layer, however, easily reusable in your collections (repository layer). This Jan Tvrdik’s hacking also includes complex refactoring of collection internals.
  • Embeddables: feature available in Doctrine, however, with few important limitations such as no-nullable embeddable. This was my hacking topic and the partial result is in this pull-request and it is waiting for Jan Tvrdik’s topic.
  • Mapper & Repository dependency: David Matějka continued with another complex refactoring for mapper, storage reflection, repository and identity map classes. The awesome result is already merged in the master branch.

The next day (on Saturday) Mikuláš Dítě has joined us and hacked “migrations plan” pull-request for save migrations running and merging in Nextras Migrations package.

Hackaton just started

The hackaton was taking place manGoweb offices. Thank you for the opportunity!


We didn’t finished all our work, but such meeting & hackaton proved that discussing and hacking in person may bring new ideas and information about Orm’s usage that I didn’t know.

All mentioned features are scheduled for 3.0 release. You may also take a look at 3.0 milestone on GitHub. I’d like to release the first 3.0 Release Candidate at the end of June. So the feature freeze should be in the middle of June.

You may help us by testing current master branch and reporting issues, or by enhancing the documentation, which is opensourced directly in the Orm’s repository.

Welcome to Nextras blog!

Welcome to Nextras official blog! We are proud to start this new blog, Nextras components are getting bigger and bigger and we felt the need for an official publishing platform.

We plan to blog-post about:

  • new releases,
  • readmap and planned release dates,
  • development insider info,
  • othe info connected with Nextras components.

You may subscribe for new posts by RSS or you can follow us on our Twitter account @nextrasfw.