Dependency Injection with AngularJS – by Alex Knol

Dependency Injection with AngularJS – by Alex Knol
Disclaimer – I have been contacted by Packt publishing to read and comment the book. Except the book itself I did not get any benefits or compensation.
Dependency Injection with AngularJS – by Alex Knol
Dependency Injection with AngularJS – by Alex Knol

With this book about AngularJS Dependency Injection, Alex Knol attempts to focus on one but surely the most important part of AngularJS components.

You’ll first find a brief introduction about AngularJS, how to setup, and samples to get started. The book will then guide you through good practices and to the why and the how dependency injection helps your application to scale with new features. It covers the SOLID principles, and the complex subject of unit and functional (or e2e) testing with many code samples. Also it suggests code architecture to avoid your application to become a giant mess of .js files.

About the book itself, while it remain a very good introduction to enterprise level application with AngularJS, it stills focus on the essential of the dependency injection component of AngularJS. Experts won’t find here a complete description of all the facets of the library (factories, providers, container hooks and building process…). On the other hand, beginners and intermediate programmers will have a good vision of the power of dependency injection done right with AngularJS.

You can find the book on Pack here and follow Alex here.

An AngularJS CRUD using Azure Mobile Services

Lately, we saw very promising web technologies coming out. I am currently exploring some new web applications stacks that are more RAD and flexible. I especially focused on angularJS and Azure Mobile Services which are in my opinion two of the most interesting technologies of the past months.

Why AngularJs?

AngularJSI would describe AngularJS as a javascript view oriented framework. It offers a very element way to build dynamic web pages using two-way binding, events, controllers, router, … I particularly the very elegant and direct approach of solving the issue by keeping very close with the javascript philosophy. It is comparable to KnockoutJs, EmberJs, or BackboneJs, but I choose none of those because I found they over-thought the issues with too much code and abstractions.

Why Azure Mobile Services?

Windows AzureAt first Azure Mobile Service sounds like a plateform for mobile applications. It offers an online SQL storage with SDKs for iPhone, Android and Windows Phone plateforms for easy CRUD access. It also has some bonuses like a push notification system and a dynamic mode where the SQL schema is enriched every time a new field is pushed on a table. What’s more is the fact that the online stack is an SQL database with a nodejs frontend acting as a REST service. There is also now a javascript SDK that allows web-applications to connect with the storage service.

Building a CRUD

My tutorial is about creating a CRUD for Azure Mobile Services using AngularJS, an interesting alternative has been brought recently using AmberJS, but, as I said, I prefer AngularJS.

First, setup mobile services:

1. First of all you need an Azure account with the preview for Mobile Services activated.
2. Create a mobile services:
Create an Azure Mobile Services
3. Follow the wizard steps then go to your newly created service.
4. Then go the the Data tab then create a table:
Create a data table
5. In the configure tab, be sure that the dynamic schema is activated and that your development/production host is in the cors configuration:
Configure the service
6. In the dashboard tab, note the mobile service url, and in the manage keys popup, get your Application Key:
Get you service url and application key

Then, lets prepare our angular website:

1. The first thing to do is to create a js file, configuring a resource to your mobile service table:

// mobile-service.js
'use strict';

angular.module('mobileServices', ['ngResource']). // new service mobileServices depending on ngResource
    factory('Task', function($resource) { // declaring a MyTable resource
        return $resource('https://myservice.azure-mobile.net/tables/task/:taskId', {taskId: '@id'}, // binding to the table url
            {
                'update': { method:'PATCH' } // adding an update function
            }
        );
    });

Here a new service named mobileServices is configuring the ngResource service to provide a Task resource connected to the table named task in our Azure Mobile Service. Note that we added a supplementary update action that uses the method PATCH. This is because Azure mobile service uses POST only for creation and PATCH must be used for update. Note that the Task resource is already provided with get, query, save, remove and delete.

2. In the app.js file configuring angularjs, lets tweak some code:

// app.js

angular.module('myapp', ['mobileServices']). // setting up our app to use the mobileServices service
    config(['$httpProvider', function($httpProvider) { // coniguring the httpProvider
        $httpProvider.defaults.headers.common['X-ZUMO-APPLICATION'] = 'myapplicationkey'; // add the application key
        $httpProvider.defaults.headers.common['Content-Type'] = 'Application/json';
    }]);

We just configured our app to use the mobileServices service and added the application key that will allow authentication to he Azure Mobile Service.

3. Now, you can easily import the Task resource in any controller, here is an example:

// controller.js

function MyCtrl($scope, Task) {
    $scope.tasks = Task.query(); // load all tasks
    $scope.newTask = new Task(); // create an empty new task

    // saving a new task
    $scope.createTask = function() {
        // call the service
        $scope.newTask.$save(function() {
            // when saved, reload the list and recreate a new task
            $scope.tasks = Task.query();
            $scope.newTask = new Task();
        });
    }

    // removing a task
    $scope.deleteTask = function(task) {
        // call the service
        task.$delete(function() {
            // when deleted, reload the list
            $scope.tasks = Task.query();
        });
    }

    // saving an existing task
    $scope.updateTask = function(task) {
        // call the service
        task.$update();
    }
}

Ad you can see, this commented controller is very straight forward. The controller has a list of tasks and an empty one dedicated to the creation process. Three functions allows to create, update and remove a task.

4. To complete the example here is a possible HTML usage:

<!DOCTYPE html>
<html ng-app="myapp">
<head>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript" src="angular.js"></script>
    <script type="text/javascript" src="angular-resources.js"></script>
    <script type="text/javascript" src="mobile-service.js"></script>
    <script type="text/javascript" src="controllers.js"></script>
    <script type="text/javascript" src="app.js"></script>
</head>
<body>
    <div ng-controller="MyCtrl">
        <ul>
            <li ng-repeat="task in tasks">
                <input type="checkbox" ng-model="task.done"
                       ng-click="updateTask(task)">
                <span>{{ task.text }}</span>
                <a ng-click="deleteTask(task)">delete</a>
            </li>
        </ul>
        <form ng-submit="createTask()">
            <input type="text" ng-model="newTask.text"
                   placeholder="add new task here">
            <input type="submit" value="create">
        </form>
    </div>
</body>
</html>

Here we display the list of task. Each item has a checkbox which is instantly saved upon click and a delete button. Also a form allows the creation of a new task.

Wrap up

Thanks to AngularJS + Azure Mobile Services. In a very few lines of codes and configuration, we were able to build a CRUD web application in a very reactive way.

How to run your Symfony2 PHP app on Azure website

Windows AzureBestComparator is part of the DojoBoost accelerator in Paris and a Bizpark partner. We have the chance to have some partnerships with Microsoft and thus have some support and early access to some technology. Especially about Windows 8 and Azure.

Talking about Azure, they made tremendous upgrades to the platform during the year. They moved from a PAAS platform to a full layered cloud solution. From SAAS to IAAS you can do almost everything. Create a WordPress in a few clicks, create a VM, configure a VPN, create a SQL server, create a mobile service that interface an autogenerated backend storage with your iPhone/Android/Windows phones, scale your services by moving a slider…
Being at the Azure Open Source Summit really amazed me about all the possibilities that are offered to developers and how fast new features comes to the portal. One of those which interested me the most is the possibility to run a PHP website on Azure using the Web Site feature.

About PHP and Azure

PHPYou currently have two main options to run PHP on azure.

First you can simply create a VM using Azure Virtual Machine, after choosing an OS (Windows Server, CentOS, Suse, Ubuntu…) you just connect to your server and configure everything you need. You can change the size of you VM, it goes up to 8 cores and 15GB of RAM. I am running it in production for a few mounts now, and it is pretty stable and reliable. Nevertheless there are some drawbacks. You have to maintain your environment (which is not my job) and it has some limitations in terms of scalability (if you want more power, you will need to maintain another VM and start configuring load balancing and synchronization…). This is pure IAAS.

The other option I recently explored is using Azure website. You simply ask for a computation service which uses a code synchronized via git. It takes care about all the environment maintenance for you and just runs your code. Moreover, you can leverage some nice features such as the possibility to increase the size of the underlying instance (up to 4 cores and 7GB of RAM), but also increase the number of instances (up to 20) seamlessly. Azure takes care of the rest for you. This is more PAAS oriented and let you concentrate on developing your app.

Let’s start a first PHP website:

  1. First of all go to your azure portal
  2. Create a new website using the custom wizard
  3. Select the name of your website, the region, a database (or not) and check the “publish from source control” option
    step2
  4. Choose “git” and “local git repository” as source control setup
    step3
  5. In a third step select your credential, they will be required for git synchronization and ftp login (if you want to)
  6. Now, open the deployments panel in the newly created website you will find there the git url
    step4
  7. On your local machine, simply clone the repository (or set a remote): git clone https://michel@blog-test.scm.azurewebsites.net/blog-test.git
  8. Put your PHP code in the cloned repository, commit, and push to azure
  9. When pushing to azure, it will automatically publish the newly updated code to the website, you can visualize it directly by connecting to the url of the website displayed in the website dashboard

At this point you can upload PHP code to Azure and run it. Here is what you might want to know:

  • You can switch PHP version (5.3 and 5.4) in the configure tab
  • You can scale the size and the number of the instances in the scale tab
  • You can map your domain name using the “manage domain” option available in the bottom bar if you are in “shared” or “reserved” mode (available in the scale tab)
  • If you don’t want to deploy from a local git repo, you can using github, codeplex or bitbuket. It is configurable from the wizard in step 4.
  • You can set environment variables in the configure tab
  • You can choose which branch of your git to deploy in the configure tab
  • You can access the server via ftp using the credential given in step 5 and the ftp configuration in the dashboard
  • You can override the php.ini by giving a .user.ini at the root of your repo

What about Symfony2 websites?

Symfony2 LogoRunning a Symfony2 website is doable but it will require some more work. You will have two main issues to fix:

  1. Activate url rewriting to web/app.php, and reroute web requests to the web directory
  2. Find a way to use the composer and the console

The first issue can be tackled simply by adding a Web.Config file at the root of you repo. It works just like .htaccess for apache but for IIS. Here is the content:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="web directory">
                    <match url=".*" ignoreCase="false" />
                    <action type="Rewrite" url="web/{R:0}" appendQueryString="true" />
                </rule>
                <rule name="app_php handling" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/web/app.php" appendQueryString="true" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

In the Web.Config file we define two rules. The first one reroutes every request to the web directory, and the second one routes the requests to the web/app.php script when there is no physical file requested.

I did not yet tackled the second issue (ie. composer and console use). What I know is that there is no command line access to Azure website but it seems like you can use the exec PHP function from PHP scripts. So everything seems doable with some web interface that simulates command line using PHP functions. I will edit this post as soon as I find a better solution.

What if I want to add some extensions/tweak to PHP runtime?

You may notice that Symfony recommends the use of the intl extension for PHP which is used for internationalization of the validation component (and also in some BCC bundles). You might also need a specific setup of PHP such as a specific version, a configuration which cannot be overridden in the .user.ini file or another extension.

Don’t worry, you can give to Azure you own PHP runtime:

  1. Go to http://windows.php.net/download/ and get the version of PHP you want (which has to be “VC9 x86 Non Thread Safe”)
  2. Unzip it to a directory in your repo, in my case in a ./bin directory
  3. Configure your php.ini file in bin/php.ini
  4. Remove the extensions you don’t want in bin/ext/*
  5. Add, commit and push the files (which might take some time considering the size of your php runtime)
  6. When git is synchronized, go the configure tab on azure
  7. At the bottom of the section, add a handler mapping configuration. The extension is *.php and the script processor path is D:\home\site\wwwroot\bin\php-cgi.exe (because D:\home\site\wwwroot\ is the root of the website and my PHP runtime is in the bin directory)
    step5

Everything is set and you website now runs on your own PHP runtime.

Wrap up

Despite Azure is very young, it offers a lot of possibilities in terms or configuration. I hope this post will help you understand better how it works and how to setup your favorite PHP environment while leveraging all the nice features of Azure.

My take on the Mahout and Myrrix recommendation algorithms

MahoutWhereas BestComparator has his own recommendation engine based on user profiling, behavior analysis and analysis of product specs, I recently wanted to explore the possibilities of the famous recommendation engine built inside Mahout.

First of all, Mahout is a set of machine learning algorithms which leverage the Hadoop environment, providing powerful and scalable algorithms. One of its main target is the recommendation algorithms also known as taste collaborative filtering.

Recommendation algorithms have been made famous by websites such as Amazon, Youtube or Netflix. They use it to make suggestions based on what you bought, watched or liked.

Myrrix

MyrrixOne of the author of Taste/Mahout recommender engine, Sean Owen decided to give the engine a more formal structure by building Myrrix.

Myrrix is a recommendation engine based on Mahout. It offers an out of the box configuration for a recommendation engine accessible with a Rest API. The good to know are:

  • Scalable as Mahout and Hadoop are scalable, using computing parallelization and a distributed file system
  • Runs an optimized version of Taste (currently Taste 3)
  • Runs in real time
  • Can be efficient even with a relatively small amount of data

Recommendation process

The first thing you want to do is to feed your model (ie. Your algorithm) with current observed data. The models aggregates users, items and the associations between them. These associations are called preferences and are qualified by their value, describing the strength of the association between the user and the item.

Feeding the engine means pushing every observed associations with the user id, the item id and the strength. You are simply giving the engine your current taste graph, linking users to items via their tastes.

When your engine is fed, you have to ask it to refresh. Thus it will re-analyze the given graph and compute an actualized, and thus better, model. This may take some time, but Myrrix has the ability to continue answer your requests during this time.

Finally, with your shinny model you can ask questions and get recommendations. Here are the main queries:

  • Recommend to a user
  • Recommend to a group of users
  • Recommend to an anonymous user
  • Recommend similar items
  • Estimate the strength of the preference between an user and an item

With such a panel of tools you can easily guess that answering the question “What item users like me also liked?” becomes accessible.

Consuming Myrrix from PHP

PHPIn order to integrate Myrrix results to my recommendation engine, I had to build a PHP Myrrix client. I decided to use the Guzzle library that provides a really neat way of building a PHP client for Rest APIs. You can download my library on the open source Github Project: https://github.com/michelsalib/bcc-myrrix.

After installing the library, you can write some very fancy code:

// Get a client
$this->client = MyrrixClient::factory(array(
    'hostname' => 'localhost',
    'port'     => 8080,
));

// Put a user/item assocation, here use #101 as an association of strength 0.5 with item #1000
$command = $this->client->getCommand('PostPref', array(
    'userID' => 101,
    'itemID' => 1000,
    'value'  => (string)0.5,
));
$this->client->execute($command);

// Refresh the index
$command = $this->client->getCommand('Refresh');
$this->client->execute($command);

// Get a recommendation for user #101
$command = $this->client->getCommand('GetRecommendation', array(
    'userID' => 101,
));
$recommendation = $this->client->execute($command)->json();

Here we instantiate a Myrrix client hosted on the localhost on port 8080. We put into the model a preference of 0.5 between the user #101 and the item #1000. We then ask the model to refresh. Finally we get a recommendation for the user #101. The recommendation result is an array of item id with their estimated strength for the given user.

The library is pretty straight forward and help you leverage in a very simple way all the powerfulness of the Myrrix engine from PHP.

I also made a Symfony Bundle that helps you get the client from the dependency container, and offers a cleaner configuration process: https://github.com/michelsalib/BCCMyrrixBundle.

Don’t hesitate to get the code, install it and test it. I would be very happy to get contributions, feedbacks or feature requests.

WinRT: How to properly implement ISupportIncrementalLoading with navigation

BestComparator is about to publish its new Windows 8 application, and I ran into a really weird and frustrating issue when implementing ISupportIncrementalLoading.

Supporting infinite scrolling pagination

The best way to support infinite scrolling, is to use a GridView or a ListView and bind it an ObservableCollection that implements the ISupportIncrementalLoading.

You will probably end with a class like this one:

public class PaginatedCollection : ObservableCollection, ISupportIncrementalLoading
{
    private Func<uint, Task<IEnumerable>> load;
    public bool HasMoreItems { get; protected set; }

    public PaginatedCollection(Func<uint, Task<IEnumerable>> load)
    {
        HasMoreItems = true;
        this.load = load;
    }

    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        return AsyncInfo.Run(async c => {
            var data =  await load(count);

            foreach (var item in data) {
                Add(item);
            }

            HasMoreItems = data.Any();

            return LoadMoreItemsResult() {
                Count = data.Count,
            };
        });
    }
}

Then you can simply create a bindable collection for your GridView or ListView in you ViewModel this way:

// in your view model
Items = new PaginatedCollection(async count => {
    var result = // your logic to load more items asynchronusly
    return result;
});

At binding time, the control will automatically detect that you binded a ISupportIncrementalLoading collection and will automatically call the LoadMoreItemsAsync when needed.

The incomprehensible AccessViolationException

Everything seems to work fine but if you happen to navigate in and out of a page using this interface you might get this exception for apparently no reason: AccessViolationException. You will get no stack trace to debug. Basically, the platform crash at a very low level around the C++ layer. Apparently, the asynchronous loading get bugged when you leaved the page and it is destroyed.

The almost easy workaround

I was stuck on this issue for quite a long time. I event though of manually implementing the infinite scrolling the way I did it in wp7, which I was not found of because it was quite hack (I was listening to the compress state of the scroller in order to detect when the end of the list was reached). Then I got the idea of caching the pages at a low level using the NavigationCacheMode of the Page control. It is simply done in the LayoutAwarePage constructor:

public LayoutAwarePage()
{
    NavigationCacheMode = NavigationCacheMode.Enabled;
    // the rest of the logic…
}

By doing so, you tell the framework to keep the page in the memory and directly use it when navigating forth and back to the page. This way, because the page still lives in memory, your asynchronous request to get more items continues to behave properly when navigating.

The hidden issue behind page caching

But, the fix is not complete yet. By using page caching, it is not properly regenerated when you navigate to a page already loaded but with a different context. Let’s take an example: BestComparator has a homepage listing different categories of products. When selecting the smartphones category, you navigate to a CategoryPage with the id of the category as a parameter. This was the smartphones category is completely fetched with its corresponding products. But if you go back to the homepage and then navigate to the laptops category, the framework will use the previously cached CategoryPage which was loaded with smartphones… and won’t trigger the load of the laptops.

The fix here is quite subtle, what you need to do is to trigger the LoadState procedure not only when the page is new, but also when navigating forward, mimicking the windows phone 7 navigation system. Just go to the OnNavigatedTo method of the LayoutAwarePage and add in the first line a test concerning the NavigationMode:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    // Returning to a cached page through navigation shouldn't trigger state loading
    if (this._pageKey != null && e.NavigationMode == NavigationMode.Back) return;
    // The rest of the logic...
}

And here it is, you completely support infinite scrolling with no bug, and won a nice page caching strategy on the way.

Wrap up

The new interface ISupportIncrementalLoading provided in WinRT can be very useful but its behavior when asynchronously loading items and navigating is quite bugged. What you have to do is activate a Page caching strategy and don’t forget to tweak the loading state process and everything should run smoothly.

About work, open source and commitment

With this post, I want to take some time to explain my commitment to open source, especially to Symfony and how it is tangled with my everyday work.

What do I do?

I am currently developing for my new startup I founded with two of my associates and friends. We knew each other at engineer school ECE Paris, and were always hungry for entrepreneurship. We worked together for years now, and had some ideas on the way. Some were bad, some were better, and one was genial enough to deserve a real leap into the world of startup creation.

And so we created BestComparator.

BestComparator?

BestComparatorIt is service that helps everyday consumer to choose the best product according to his profile, his urges, and the general quality vs. price value of the products available on the market.

Our ultimate goal is to make the best product recommendation answering this simple sentence: “I am Michel, I am a 23 years old nerd, I need a new Laptop, and most of my time I develop, listen to podcasts and surf on the web.”

We worked really hard, developing the service, creating partnership with price comparison services, and defining exactly how the UX/algorithm would look like. We starting working full time on September 2011. We released an early private preview on October and a public beta on March 2012.

The service is finally online since July 2012 and we already have some nice recommendations and the business is smoothly starting.

This is just a start and many thing could be, and will be, better in the coming months. We also have a heavy roadmap, containing very nice (killer) features, more products, better recommendations, an ecosystem, and some other surprises.

So what do I do in that venture?

BestComparator is a 3 men job. While my associates work on the business and the UX, I spend my time coding the foundations of the service. I am the Data, Architecture, Algorithm, Information System guy. AKA the CTO/Lead developer/Cofounder.

The challenge is quite big. We have to aggregate, consolidate and extract meaning from a gigantic amount of data, from products specifications to our member’s behaviors and desires. Those are coming through various funnel, from our partners, the socials networks, what the users say and don’t say… I needed a solid base with a solid promise.

Three years ago I was already a symfony 1.4 junky. This was with tremendous thrill that I started working with Symfony2 nearly two years ago when the first preview appeared. I saw in Symfony2 a very powerful tool moving at a fast pace, bringing many new core concepts to the PHP world (bundles, annotation, DI…), and gathering a very prolific community. Symfony2 is scalable, fast, flexible and stable. Most of all, it made PHP better with a modern architecture and better practices. Its strength is well known and since we adopted it Drupal, eZ Publish, phpBB and many more followed the way.

As a proof of or commitment you can have a look at the credit page at BestComparator.

As you can see we have a quite exhaustive architecture, composed around Symfony2.1 we are running on Doctrine2.3, ElasticSearch, Behat, Sonata, Assetic, Twig and many more.

I also committed to a community

Of course we started when Symfony2 was young, and in some ways it still is young. Along the way, I was involved in some features of the framework (especially around the translation components), and I pushed into the Sonata project for instance. I also developed some standalone bundles such as the BCCExtraToolsBundle, the BCCCronManagerBundle… which are quite famous now.

Developing such bundles requires time. I love to spend it working on open source projects, especially when it matters to people. Thus, I am very happy today when I can work on BCC Bundles, designed for BestComparator and pushed to the open world.

As a bonus I also develop some C# apps for Windows Phone 7: Gi7 and Readr7. They are open source, and some other might come around the Windows 8 platform.

I try to allocate as much energy that I can, following, debugging and improving these projects. That’s my second commitment.

How about a third commitment

Also I am getting married teaching programming at ECE Paris for a year now. Mostly C and C#, I also have some involvement in some web development and Java courses.

I do it partly because it allow me to earn enough money to pursue my work at BestComparator and mostly because I like to share.

I can also tell you that committing to a hundreds of students is not a so easy commitment and it requires time and patience (and patience too).

Follow up

First of all I enquire to go on BestComparator, things are French for the moment, as long as we need some contracts with local resellers. Here are the common way of getting updates on the venture: twitter, facebook, g+.

You can watch and fork my work on github, and pack your PHP projects on packagist. My windows apps are on the market place.

And if you are interesting in a very prolific and fast growing engineer school (with very talent teachers of course), go have a look on the ECE Paris website.

The BCCEnumerableUtility is out

The BCCEnumerableUtility is out

One of the most frustrating things you may encounter as a PHP developer is definitely the lack of clarity and consistency of many of the core array and string manipulation functions.

What goes wrong

Let’s take for example the function that checks if a string contains another string. You might want to use strstr but you should use strpos for performance purpose. You already noticed the lack of clarity in the name of the functions, and the fact that whatever you do, the better way of dealing with strings in php is never straightforward.
You may also know that the case insensitive equivalents of these function adds an i in the middle of their names (stristr, stripos). Again, this is not very explicit. Finally, some functions does not respect the same format, such as str_split or str_replace.

And the same matters occur with the array functions.

As you may know, I also have a .NET background, especially in C#. One of the thing I like is the way they deal with this issue. First of all, strings and arrays are objects… They also have the IEnumerable interface that is implemented by everything that is an enumeration of items (strings are enumeration of characters). They added a bunch a generic methods that extends the IEnumerable interface to provide clear and powerful functionalities. So whenever you have something that is enumerable you leverage automatically tens of filtering, ordering, transformation and manipulation functions.

I really miss IEnumerable when I am using PHP.

The BCCEnumerableUtility

When PHP5.4 came out, I saw in traits a way to port IEnumerable from C# to PHP.

So I mimicked the C# interface and made the Enumerable trait, with the Collection and String classes that leverage the trait.

Let’s avoid taking too much, here is an example with the Collection class that leverage the trait:

select(function($item) { return $item*$item; })->average();

// filter the even numbers and then order
$values->where(function($item) { return $item%2 == 0; })->orderBy();

The Enumerable trait comes with a bunch of nice functions that you can discover on the BBCEnumerableUtility Github repository.

The String class

The library also provides a String class that adds some string dedicated functions:

replace('world', 'pineapple') // replace world by pineapple
->toUpper() // to upper case
->skip(6) // skip the 6 first letters
->takeWhile(function($char) { $char != '!'; }); // take the rest while the char is different from '!'

echo $string; // PINEAPPLE

I know many people won’t like the idea of a String class, so I provide a StringUtility helper that gives you access to all the functionality with static calls:

&lt;?php
use BCCEnumerableUtilityStringUtility;

$string = 'Hello world!';

$string = StringUtility::replace ($string, 'world', 'pineapple'); // replace world by pineapple
$string = StringUtility::toUpper ($string); // to upper case
$string = StringUtility::skip ($string, 6); // skip the 6 first letters
$string = StringUtility::takeWhile($string, function($char) { $char != '!'; }); // take the rest while the char is different from '!'

echo $string; // PINEAPPLE

Wrap up

The BCCEnumerableUtility library will help you manipulate strings and arrays more easily.

As usual, I published this library on Github. I welcome remarks, bugs and contributions🙂