PHPackages                             summerstreet/woodling - 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. [Testing &amp; Quality](/categories/testing)
4. /
5. summerstreet/woodling

AbandonedLibrary[Testing &amp; Quality](/categories/testing)

summerstreet/woodling
=====================

Easy fixtures for your models

v0.1.6(12y ago)40200.3k↓45.8%4[1 issues](https://github.com/summerstreet/woodling/issues)[1 PRs](https://github.com/summerstreet/woodling/pulls)MITPHPPHP &gt;=5.3.0

Since Feb 10Pushed 11y ago3 watchersCompare

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

READMEChangelogDependencies (3)Versions (6)Used By (0)

Woodling
========

[](#woodling)

[![Latest Stable Version](https://camo.githubusercontent.com/a9faa22497842fb8a0dc102cf0df8e94efef4c46e9342ce5681621546868b844/68747470733a2f2f706f7365722e707567782e6f72672f73756d6d65727374726565742f776f6f646c696e672f762f737461626c652e706e67)](https://packagist.org/packages/summerstreet/woodling) [![Total Downloads](https://camo.githubusercontent.com/65edc7fb6cea5fe7c498545bcb6a70e4299d81673d672f5fa9c39410b7737b60/68747470733a2f2f706f7365722e707567782e6f72672f73756d6d65727374726565742f776f6f646c696e672f646f776e6c6f6164732e706e67)](https://packagist.org/packages/summerstreet/woodling) [![Build Status](https://camo.githubusercontent.com/69d76088d51e7276da8e79cd77b3cbc50cb76f0238c8ad3639d8b163a440f473/68747470733a2f2f7472617669732d63692e6f72672f73756d6d65727374726565742f776f6f646c696e672e706e67)](https://travis-ci.org/summerstreet/woodling)

Easy to use fixtures for your models. Requires no configuration on your side, leverages *your code* to do all the work.

### Installation and initialization

[](#installation-and-initialization)

You can install Woodling via [Composer](http://getcomposer.org/). Put this in your `composer.json` file and run `$ composer update --dev`:

```
"require-dev":
{
	"summerstreet/woodling": "0.1.*"
}
```

You don't need to do anything else. Woodling will be automatically loaded for you when you first use it.

### Defining blueprints

[](#defining-blueprints)

Blueprints are used to construct an instance of your specified model. Woodling guesses which model class you want to use from the name you give your blueprint.

The following code will return an instance of *User* class with `name` attribute set to "John Doe" and `hobbies` attribute set to "Unit Testing".

```
Woodling::seed('User', function($blueprint)
{
	$blueprint->name = 'John Doe';
	$blueprint->hobbies = 'Unit Testing';
});
```

You can also specify a different class name by passing it in with an array of arguments. This will create a blueprint called "Admin" and use class "User" when creating an object:

```
Woodling::seed('Admin', array('class' => 'User', 'do' => function($blueprint)
{
	$blueprint->name = 'John Doe';
	$blueprint->admin = 1;
}));
```

By the way, since Woodling utilises *your* code, you can take advantage of everything that your classes do under the hood. For example, if you were using Laravel's Eloquent, and your model would have a `setPassword()` mutator defined, this method would be called when setting your password.

### Autoloading blueprints

[](#autoloading-blueprints)

Woodling will automagically load your blueprints defined in following locations:

- application/tests/blueprints/\*.php
- application/tests/blueprints.php
- app/tests/blueprints/\*.php
- app/tests/blueprints.php
- tests/blueprints/\*.php
- tests/blueprints.php

You can also add additional search paths. In your bootstrap file add the following lines:

```
use Woodling/Woodling;

// Single path
Woodling::core()->finder->addPaths('src/Acme/DemoBundle/Tests/blueprints');

// Several paths
Woodling::core()->finder->addPaths(array(
	'/absolute/path/to/blueprints',
	'relative/path/to/blueprints'
));

// Search in new paths
Woodling::core()->finder->findBlueprints();
```

When adding paths, keep in mind, that the last segment of the path will be used as both file name and dir name:

```
// Looks in these destinations:
// - tests/blueprints/*.php
// - tests/blueprints.php
Woodling::core()->finder->addPaths('tests/blueprints');
```

### Retrieving blueprints

[](#retrieving-blueprints)

To retrieve instances of your models, you can use the following methods:

```
$user = Woodling::retrieve('User');
$user = Woodling::saved('User');
```

The `retrieve()` method will return an instance of your class. The `saved()` method will create an instance of your class and call the `save()` method on it before returning it.

If your class uses a different method name for persisting, you can change it like this:

```
Woodling::core()->persistMethod = 'mySaveMethod';
```

This will call `mySaveMethod()` when you are retrieving saved instances of your class.

### Retrieving blueprints with attribute overrides

[](#retrieving-blueprints-with-attribute-overrides)

Sometimes you need to retrieve your models with slightly different attributes than the ones you specified in your blueprint. You can do so by passing an array of `key => value` pairs where `key` is the name of the attribute you want to override.

```
$user = Woodling::retrieve('User', array(
	'hobbies' => 'Skateboarding, cooking',
	'occupation' => 'Developer'
));
```

### Retrieving lists

[](#retrieving-lists)

You can also retrieve an array of several instances instead of a single result. Woodling provides two build strategies for you: `retrieveList()` and `savedList()`. Here's how to use them (attribute overrides are optional):

```
$usersArray = Woodling::retrieveList('User', 50);
$savedUsers = Woodling::savedList('User', 50, array('name' => 'Test User'));
```

### Lazy attributes

[](#lazy-attributes)

If you want to calculate your attribute values during instantiation time, you can do so with *lazy attributes*. Just assign a closure to your attribute. The value returned from the closure will be the value used when setting this attribute on your model.

```
Woodling::seed('User', function($blueprint)
{
	$blueprint->created = function() { return time(); };
});
```

### Sequences

[](#sequences)

Very often you have validation rules on your models or in the database that require you to use unique values. If that is the case, you can use *sequences*. A sequence takes a closure, which receives a counter value. You can then use this counter to construct a unique value for your model.

Each time you retrieve an object, it's counter will be incremented. The following code will set an `email` attribute on your model. The first time you retrieve this object, it will receive a counter value of `1`, the second time your retrieve it, counter will be `2` and so on.

```
Woodling::seed('User', function($blueprint)
{
	$blueprint->sequence('email', function($i)
	{
		return "user{$i}@hostname.com";
	});
});
```

### Faux associations

[](#faux-associations)

It is possible to create model associations by returning them from lazy attributes. This is how you'd retrieve an instance with one-to-one relationship from Woodling:

```
Woodling::seed('Weakness', function($weakness)
{
    $weakness->type = 'Fruit';
    $weakness->name = 'Apple';
});

Woodling::seed('Person', function($person)
{
    $person->name = 'Eve';
    $person->weakness = function() { return Woodling::retrieve('Weakness'); };
});

$eve = Woodling::retrieve('Person');
```

And this is how you'd do the same for one-to-many:

```
Woodling::seed('Atom', function($atom)
{
    $atom->element = 'H';
});

Woodling::seed('Molecule', function($molecule)
{
    $molecule->name = 'Water';
    $molecule->atoms = function()
    {
        $h2 = Woodling::retrieve('Atom', array('element' => 'H2'));
        $o = Woodling::retrieve('Atom', array('element' => 'O'));
        return array($h2, $o);
    };
});

$H2O = Woodling::retrieve('Molecule');
```

### Retrieving blueprints with advanced overrides

[](#retrieving-blueprints-with-advanced-overrides)

You can override lazy attributes by passing them in as a regular callback function that returns something. To override sequences, you can put them under `:sequences` array:

```
$user = Woodling::retrieve('User', array(
	'occupation' => 'Developer',
	'created' => function() { return time(); },
	':sequences' => array(
		'email' => function($i) { return "name{$i}@hostname.com"; }
	)
));
```

### More awesome usage

[](#more-awesome-usage)

Here's an example that shows how to use sequences and lazy attributes to create more realistic model instances.

```
Woodling::seed('User', function($blueprint)
{
	$blueprint->name = 'John';
	$blueprint->surname = 'Doe';
	$blueprint->birthday = '1969.07.13';
	$blueprint->sequence('email', function($i) use($blueprint)
	{
		$email = "{$blueprint->name}{$i}@hostname.com";
		return strtolower($email);
	});
	$blueprint->created = function() use($blueprint)
	{
		$date = date('Y.m.d', strtotime("{$blueprint->birthday} + 20 years"));
		return $date;
	};
});
```

### Free tip

[](#free-tip)

Don't forget to put `use Woodling\Woodling;` at the top of your file. This will let you use short class syntax instead of having to prepend it with a namespace.

### License

[](#license)

For license information, check the LICENSE file.

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity42

Moderate usage in the ecosystem

Community13

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 97.1% 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 ~49 days

Recently: every ~60 days

Total

6

Last Release

4596d ago

### Community

Maintainers

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

---

Top Contributors

[![rkrv](https://avatars.githubusercontent.com/u/840660?v=4)](https://github.com/rkrv "rkrv (33 commits)")[![sillylogger](https://avatars.githubusercontent.com/u/168183?v=4)](https://github.com/sillylogger "sillylogger (1 commits)")

---

Tags

testingfixturesfactorieswoodling

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/summerstreet-woodling/health.svg)

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

###  Alternatives

[phpunit/phpunit

The PHP Unit Testing framework.

20.0k910.7M134.8k](/packages/phpunit-phpunit)[phpunit/php-code-coverage

Library that provides collection, processing, and rendering functionality for PHP code coverage information.

8.9k892.4M1.5k](/packages/phpunit-php-code-coverage)[mockery/mockery

Mockery is a simple yet flexible PHP mock object framework

10.7k497.0M23.6k](/packages/mockery-mockery)[behat/behat

Scenario-oriented BDD framework for PHP

4.0k96.8M2.0k](/packages/behat-behat)[behat/mink

Browser controller/emulator abstraction for PHP

1.6k86.1M606](/packages/behat-mink)[orchestra/testbench

Laravel Testing Helper for Packages Development

2.2k39.1M32.1k](/packages/orchestra-testbench)

PHPackages © 2026

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