Git Product home page Git Product logo

assert's Introduction

Assert

Build Status Code Coverage GitHub issues

PHP Version Stable Version

Total Downloads Monthly Downloads Daily Downloads

A simple php library which contains assertions and guard methods for input validation (not filtering!) in business-model, libraries and application low-level code. The library can be used to implement pre-/post-conditions on input data.

Idea is to reduce the amount of code for implementing assertions in your model and also simplify the code paths to implement assertions. When assertions fail, an exception is thrown, removing the necessity for if-clauses in your code.

The library is not using Symfony or Zend Validators for a reason: The checks have to be low-level, fast, non-object-oriented code to be used everywhere necessary. Using any of the two libraries requires instantiation of several objects, using a locale component, translations, you name it. Its too much bloat.

Installation

Using Composer:

composer require beberlei/assert

Example usages

<?php
use Assert\Assertion;

function duplicateFile($file, $times)
{
    Assertion::file($file);
    Assertion::digit($times);

    for ($i = 0; $i < $times; $i++) {
        copy($file, $file . $i);
    }
}

Real time usage with Azure Blob Storage:

<?php
public function putBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
{
    Assertion::notEmpty($containerName, 'Container name is not specified');
    self::assertValidContainerName($containerName);
    Assertion::notEmpty($blobName, 'Blob name is not specified.');
    Assertion::notEmpty($localFileName, 'Local file name is not specified.');
    Assertion::file($localFileName, 'Local file name is not specified.');
    self::assertValidRootContainerBlobName($containerName, $blobName);

    // Check file size
    if (filesize($localFileName) >= self::MAX_BLOB_SIZE) {
        return $this->putLargeBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
    }

    // Put the data to Windows Azure Storage
    return $this->putBlobData($containerName, $blobName, file_get_contents($localFileName), $metadata, $leaseId, $additionalHeaders);
}

NullOr helper

A helper method (Assertion::nullOr*) is provided to check if a value is null OR holds for the assertion:

<?php
Assertion::nullOrMax(null, 42); // success
Assertion::nullOrMax(1, 42);    // success
Assertion::nullOrMax(1337, 42); // exception

All helper

The Assertion::all* method checks if all provided values hold for the assertion. It will throw an exception of the assertion does not hold for one of the values:

<?php
Assertion::allIsInstanceOf(array(new \stdClass, new \stdClass), 'stdClass'); // success
Assertion::allIsInstanceOf(array(new \stdClass, new \stdClass), 'PDO');      // exception

Assert::that() Chaining

Using the static API on values is very verbose when checking values against multiple assertions. Starting with 2.6.7 of Assert the Assert class provides a much nicer fluent API for assertions, starting with Assert::that($value) and then receiving the assertions you want to call on the fluent interface. You only have to specify the $value once.

<?php
Assert::that($value)->notEmpty()->integer();
Assert::that($value)->nullOr()->string()->startsWith("Foo");
Assert::that($values)->all()->float();

There are also two shortcut function Assert::thatNullOr() and Assert::thatAll() enabling the "nullOr" or "all" helper respectively.

Lazy Assertions

There are many cases in web development, especially when involving forms, you want to collect several errors instead of aborting directly on the first error. This is what lazy assertions are for. Their API works exactly like the fluent Assert::that() API, but instead of throwing an Exception directly, they collect all errors and only trigger the exception when the method verifyNow() is called on the Assert\SoftAssertion object.

<?php
Assert::lazy()
    ->that(10, 'foo')->string()
    ->that(null, 'bar')->notEmpty()
    ->that('string', 'baz')->isArray()
    ->verifyNow();

The method that($value, $propertyPath) requires a property path (name), so that you know how to differentiate the errors afterwards.

On failure verifyNow() will throw an exception Assert\\LazyAssertionException with a combined message:

The following 3 assertions failed:
1) foo: Value "10" expected to be string, type integer given.
2) bar: Value "<NULL>" is empty, but non empty value was expected.
3) baz: Value "string" is not an array.

You can also retrieve all the AssertionFailedExceptions by calling getErrorExceptions(). This can be useful for example to build a failure response for the user.

For those looking to capture multiple errors on a single value when using a lazy assertion chain, you may follow your call to that with tryAll to run all assertions against the value, and capture all of the resulting failed assertion error messages. Here's an example:

Assert::lazy()
    ->that(10, 'foo')->tryAll()->integer()->between(5, 15)
    ->that(null, 'foo')->tryAll()->notEmpty()->string()
    ->verifyNow();

The above shows how to use this functionality to finely tune the behavior of reporting failures, but to make catching all failures even easier, you may also call tryAll before making any assertions like below. This helps to reduce method calls, and has the same behavior as above.

Assert::lazy()->tryAll()
    ->that(10, 'foo')->integer()->between(5, 15)
    ->that(null, 'foo')->notEmpty()->string()
    ->verifyNow();

Functional Constructors

The following functions exist as aliases to Assert static constructors:

  • Assert\that()
  • Assert\thatAll()
  • Assert\thatNullOr()
  • Assert\lazy()

Using the functional or static constructors is entirely personal preference.

Note: The functional constructors will not work with an Assertion extension. However it is trivial to recreate these functions in a way that point to the extended class.

List of assertions

<?php
use Assert\Assertion;

Assertion::alnum(mixed $value);
Assertion::base64(string $value);
Assertion::between(mixed $value, mixed $lowerLimit, mixed $upperLimit);
Assertion::betweenExclusive(mixed $value, mixed $lowerLimit, mixed $upperLimit);
Assertion::betweenLength(mixed $value, int $minLength, int $maxLength);
Assertion::boolean(mixed $value);
Assertion::choice(mixed $value, array $choices);
Assertion::choicesNotEmpty(array $values, array $choices);
Assertion::classExists(mixed $value);
Assertion::contains(mixed $string, string $needle);
Assertion::count(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count);
Assertion::date(string $value, string $format);
Assertion::defined(mixed $constant);
Assertion::digit(mixed $value);
Assertion::directory(string $value);
Assertion::e164(string $value);
Assertion::email(mixed $value);
Assertion::endsWith(mixed $string, string $needle);
Assertion::eq(mixed $value, mixed $value2);
Assertion::eqArraySubset(mixed $value, mixed $value2);
Assertion::extensionLoaded(mixed $value);
Assertion::extensionVersion(string $extension, string $operator, mixed $version);
Assertion::false(mixed $value);
Assertion::file(string $value);
Assertion::float(mixed $value);
Assertion::greaterOrEqualThan(mixed $value, mixed $limit);
Assertion::greaterThan(mixed $value, mixed $limit);
Assertion::implementsInterface(mixed $class, string $interfaceName);
Assertion::inArray(mixed $value, array $choices);
Assertion::integer(mixed $value);
Assertion::integerish(mixed $value);
Assertion::interfaceExists(mixed $value);
Assertion::ip(string $value, int $flag = null);
Assertion::ipv4(string $value, int $flag = null);
Assertion::ipv6(string $value, int $flag = null);
Assertion::isArray(mixed $value);
Assertion::isArrayAccessible(mixed $value);
Assertion::isCallable(mixed $value);
Assertion::isCountable(array|Countable|ResourceBundle|SimpleXMLElement $value);
Assertion::isInstanceOf(mixed $value, string $className);
Assertion::isJsonString(mixed $value);
Assertion::isObject(mixed $value);
Assertion::isResource(mixed $value);
Assertion::isTraversable(mixed $value);
Assertion::keyExists(mixed $value, string|int $key);
Assertion::keyIsset(mixed $value, string|int $key);
Assertion::keyNotExists(mixed $value, string|int $key);
Assertion::length(mixed $value, int $length);
Assertion::lessOrEqualThan(mixed $value, mixed $limit);
Assertion::lessThan(mixed $value, mixed $limit);
Assertion::max(mixed $value, mixed $maxValue);
Assertion::maxCount(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count);
Assertion::maxLength(mixed $value, int $maxLength);
Assertion::methodExists(string $value, mixed $object);
Assertion::min(mixed $value, mixed $minValue);
Assertion::minCount(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count);
Assertion::minLength(mixed $value, int $minLength);
Assertion::noContent(mixed $value);
Assertion::notBlank(mixed $value);
Assertion::notContains(mixed $string, string $needle);
Assertion::notEmpty(mixed $value);
Assertion::notEmptyKey(mixed $value, string|int $key);
Assertion::notEq(mixed $value1, mixed $value2);
Assertion::notInArray(mixed $value, array $choices);
Assertion::notIsInstanceOf(mixed $value, string $className);
Assertion::notNull(mixed $value);
Assertion::notRegex(mixed $value, string $pattern);
Assertion::notSame(mixed $value1, mixed $value2);
Assertion::null(mixed $value);
Assertion::numeric(mixed $value);
Assertion::objectOrClass(mixed $value);
Assertion::phpVersion(string $operator, mixed $version);
Assertion::propertiesExist(mixed $value, array $properties);
Assertion::propertyExists(mixed $value, string $property);
Assertion::range(mixed $value, mixed $minValue, mixed $maxValue);
Assertion::readable(string $value);
Assertion::regex(mixed $value, string $pattern);
Assertion::same(mixed $value, mixed $value2);
Assertion::satisfy(mixed $value, callable $callback);
Assertion::scalar(mixed $value);
Assertion::startsWith(mixed $string, string $needle);
Assertion::string(mixed $value);
Assertion::subclassOf(mixed $value, string $className);
Assertion::true(mixed $value);
Assertion::uniqueValues(array $values);
Assertion::url(mixed $value);
Assertion::uuid(string $value);
Assertion::version(string $version1, string $operator, string $version2);
Assertion::writeable(string $value);

Remember: When a configuration parameter is necessary, it is always passed AFTER the value. The value is always the first parameter.

Exception & Error Handling

If any of the assertions fails a Assert\AssertionFailedException is thrown. You can pass an argument called $message to any assertion to control the exception message. Every exception contains a default message and unique message code by default.

<?php
use Assert\Assertion;
use Assert\AssertionFailedException;

try {
    Assertion::integer($value, "The pressure of gas is measured in integers.");
} catch(AssertionFailedException $e) {
    // error handling
    $e->getValue(); // the value that caused the failure
    $e->getConstraints(); // the additional constraints of the assertion.
}

Assert\AssertionFailedException is just an interface and the default implementation is Assert\InvalidArgumentException which extends the SPL InvalidArgumentException. You can change the exception being used on a package based level.

Customised exception messages

You can pass a callback as the message parameter, allowing you to construct your own message only if an assertion fails, rather than every time you run the test.

The callback will be supplied with an array of parameters that are for the assertion.

As some assertions call other assertions, your callback will need to example the array to determine what assertion failed.

The array will contain a key called ::assertion that indicates which assertion failed.

The callback should return the string that will be used as the exception message.

Your own Assertion class

To shield your library from possible bugs, misinterpretations or BC breaks inside Assert you should introduce a library/project based assertion subclass, where you can override the exception thrown as well.

In addition, you can override the Assert\Assertion::stringify() method to provide your own interpretations of the types during error handling.

<?php
namespace MyProject;

use Assert\Assertion as BaseAssertion;

class Assertion extends BaseAssertion
{
    protected static $exceptionClass = 'MyProject\AssertionFailedException';
}

As of V2.9.2, Lazy Assertions now have access to any additional assertions present in your own assertion classes.

Contributing

Please see CONTRIBUTING for more details.

assert's People

Contributors

abacaphiliac avatar andersonamuller avatar asm89 avatar ayesh avatar beberlei avatar chalasr avatar chh avatar christeredvartsen avatar drschimke avatar edorian avatar fritsjanb avatar fvdb avatar gitnik avatar gronostajo avatar jaapverloop avatar jeroendedauw avatar lapistano avatar lexty avatar localheinz avatar pscheit avatar ptondereau avatar raphaelstolt avatar rquadling avatar rskuipers avatar shadowhand avatar tacovandenbroek avatar thewilkybarkid avatar timwolla avatar vaclavsir avatar webmozart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

assert's Issues

Validate Only If

Is it possible validate the email (for example) only if it is filled?

Like the field is not required, but if populated check if is valid.

I just don't want to do something like:

if(!empty($value)) {
   Assert...
}

No assertion Assertion#date exists.

Hi,

I'm trying assert a valid date inside a class, but when I use the method Assertion::date, it throws an exception "No assertion Assertion#date exists." I'm using the "beberlei/assert": "^2.4" in composer.json and using PHP 5.3.

Do you know if is that because of the Assert's version I'm using?

Many thanks.

Negated checks for ```eq``` and ```same```

I'm thinking about negated checks for the assertions eq and same (aka neq and notSame). What do you think about this additional methods? In my opinion these checks are quite common. Currently the only way to do a negated check is to catch the exception and proceed only in this case.

Maybe an extension similar to the magic __callStatic-nullOr{Method} as not{Method} could also make sense and would be a generic way?? Hmmmm...

Using assertions in annotations

We've started using the library in our domain and it's great. We use a lot of transfer objects which have their own validation and tehre is a large overlap, however it is not as extensive as this library.

Our existing framework for validating transfer objects uses annotations.

Is there a recommended way to do this? Would you accept a PR or would it be better suited to a separate project entirely to save on dependencies?

example of own assertion in a DDD context

this library is very good for DDD, however at first sight is very hard for a newbie to see that

the last example on the readme poses an Assertion class but the name is too simple, not even YourOwnAssertion which even though is bad, is better than the Assertion example. Beyond this point perhaps one can show how the CustomAssertion is used in an example.

Enhancement: Constants gathering

When checking method parameters i often want to check if it is a correct value of some constants that fit here. So i made a convenience method in my Assert subclass. The source is below, perhaps its useful for you to integrate in some way.

For example you can do:

public class C
{
const MODE_A = 1;
const MODE_B = 2;

const OTHER_XYZ = 'something';

public functio setMode($mode)
{
    Assert::that($mode)->inArray(Assert::Constants(__CLASS__, "MODE"));
}

}

/**
 * Gather constants having a certain prefix e.g. for validating against them
 *
 * @param mixed $objectOrClassname
 * @param string $prefix
 * @param mixed[] $exclude
 * @return mixed[]
 */
public static function Constants($objectOrClassname, $prefix, array $exclude = array())
{
    // Make array from mode constants for easy validation
    $class = new \ReflectionClass($objectOrClassname);
    $found = array();
    foreach ($class->getConstants() as $constName => $constValue)
    {
        if (mb_strpos($constName, $prefix, null) === 0)
        {
            if (!array_search($constValue, $exclude))
            {
                $found[] = $constValue;
            }
        }
    }
    return $found;
}

Multibyte string functions

It would be great to use multibyte string functions in Assertion::minLength(), Assertion::maxLength(), etc. methods.

isJsonString accepts an empty string and null

json_last_error() returns 0 when json_decode-ing an empty string and when json_decode-ing null.

The result:

Assertion::isJsonString('');
Assertion::isJsonString(null);

both do not throw an exception

To me this looks like unwanted behavior. Can I send a PR for this?

v1.3 Release soon?

Hi,

thanks a lot for this great library! I'm integrating it into many projects because I find my code much more readable.

There have been some changes and especially 'library/project based assertion subclass' are a feature I really would like to use. Do you think this is stable enough to release a v1.3 version?

Cheers,
Adrian

No notInArray() Assertion

There are not* assertions for lots of methods, but there isn't one for notInArray. I need this assertion for a project I'm working on, and, at the moment, I'm having to do this manually unless there is a better way of doing it.

Would it be possible to add this assertion?

Check File Persmissions

Moar code:

/**
 *
 * @param string $file
 * @param array $modes
 * @throws Dispatcher_FilePermission_Exception
 */
public static function check( $file, array $modes, $notExistsOk = false )
{
    if( $notExistsOk && !file_exists( $file ) ){
        return true;
    }

    foreach( $modes as $mode ){
        switch( $mode ){
            case 'e':
                if( !file_exists( $file ) ){
                    throw new Dispatcher_FilePermission_Exception('path/file not found ' . $file );
                }
                break;
            case 'f':
                if( !is_file( $file ) ){
                    throw new Dispatcher_FilePermission_Exception('path is not a file ' . $file );
                }
                break;
            case 'd':
                if( !is_dir( $file ) ){
                    throw new Dispatcher_FilePermission_Exception('path is not a dir ' . $file );
                }
                break;
            case 'l':
                if( !is_link( $file ) ){
                    throw new Dispatcher_FilePermission_Exception('path is not a link ' . $file );
                }
                break;
            case 'r':
                if( !is_readable( $file ) ){
                    throw new Dispatcher_FilePermission_Exception('path not readable ' . $file );
                }
                break;
            case 'w':
                if( !is_writable( $file ) ){
                    throw new Dispatcher_FilePermission_Exception('path not writable ' . $file );
                }
                break;
            case 'x':
                if( !is_executable( $file ) ){
                    throw new Dispatcher_FilePermission_Exception('path/file not found ' . $file );
                }
                break;
            default:
                throw new Dispatcher_FilePermission_Exception( 'unknown mode ' . $mode );
        }
    }
}

Functions file causes collisions if package is used more than once

The functions.php file is pulled in throught the Composer autoloader file mechanism: https://github.com/beberlei/assert/blob/master/composer.json#L20

If this package is used more than once in one PHP session (my use case is several WordPress plugins including it), this causes a fatal error:

Fatal error: Cannot redeclare Assert\that() [...]

I know that Composer should be used at the site level, not multiple times in one site. However, this could easily be fixed to allow for that use case, too, which would at least simplify the development process.

min, max, range Assertions don't accept integerish

Hi Benjamin,

With the new fluid API it's very easy to assert that a value is a positive integer or in some range of integers.

Assert\that($number)->nullOr()->integerish()->min(1);
Assert\that($number)->nullOr()->integerish()->range(1, 10);

The problem is that min, max, range and maybe other Assertions first assert that the value(s) is/are integer(s). Any integerish parameter that comes in through a controller will be a string, so those Assertions will fail. Doing a (int) typecast earier in the chain is an error prone approach.
(int) 'foobar' -> 0
Also we're loosing the dynamic typing, the Domain does not care if 5 comes in as an int or a string and you have the intergerish Assertion there for a reason.

Maybe if would be a good idea to add a boolean switch "acceptIntegerish" to those methods? Or the other way round, add a "strict" switch which defaults to true?
Other possibility would be to add sister Assertions like minIntegerish(), but I don't like that so much.

What do you think?

Best regards, Anton

Use numbered placeholders in sprintf templates

This way one can use this placeholders in custom messages without taking care of the arguments given first. The (obvious) downside is, that one needs to one which argument comes at which position, but the alternative seems to be a (custom) template system like str_replace("{{foo}}", "$foo", $message) ๐Ÿ˜‰

\Assert\that($msg)
    ->length(42, 'The message must be 42, but it\'s %3$s');

Assertion "date" missing

Hello,

I think an assertion for valid dates is missing Assertion::date($value, $format).
Is anyone able to add this please? :)

please remove wiki tab

i think the github option should be defaulted to hidden, is a checkbox in the settings panel

Arithmetic

Currently need to verify the sum of two integers, but I wonder, if something like this (+, *, -, \, %) fits into the library itself like

\Assert\thatAll([$foo, $bar])->sum(42, 'The sum of foo and bar must be 42');

What do you think?

License question

Hey Benjamin,

I'd like to create very light weight version of the fluent interface to assert for use in some code that is going be very heavily used in my app. Your license file states that the copyright notice needs to be retained. So, would you like the following retained?

<?php
/**
 * Assert
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to [email protected] so I can send you a copy immediately.
 */
namespace Assert;
/**
 * Assert library
 *
 * @author Benjamin Eberlei <[email protected]>
 *
*/

Callable message

I think it could be useful if it was possible to be able to pass a callable message instead of a string because sometimes the message creation can be time consuming. Is it good or bad idea? What do you think?

[RFC] Allow parameterized messages

I was wondering if you would be up for a PR for parameterized strings.

Eg.:

<?php

try {
    Assert\Assertion::same("a", "b", "The left argument (%left%) should be the same as the right argument(%right%) but they are not the same.");
} catch (Assert\AssertionFailedException $e) {
    echo $e->getMessage();
    // Prints => The left argument (a) should be the same as the right argument(b) but they are not the same.
}

\Assert\that() method chaining not found

I use this library for a long time, and never had issues with it in Phpstorm, until now. Not a single method of the AssertionChain gets recognised anymore.

\Assert\that($name)->string(); // Method 'string' not found in class

I might have to redirect this issue to Phpstorm itself, since I'm not sure if I have this problem since a newer version of this library or since the Phpstorm 9 update. But I ask it here first, because the following snippet (which uses the same mechanics) works like a charm:

/**
 * @method Foo bar()
 */
class Foo {
}

/**
 * @return Foo
 */
function test()
{
    return new Foo();
}

test()->bar(); // method is recognised

Need chaining assertions with allow fails.

It may look like

\Assert\ThatOneOf($someObject, 'Value must be string or object with method "__toString".')
    ->string()
    ->methodExists($someObject, '__toString')
    ->end();

This chain fails only if both assertions fails.
I know this check can be realize as it described in #83.

try {
    Assert::string($someObject);
} catch (AssertionFailedException $e) {
    Assert::methodExists($someObject, '__toString');
}

But if we need more assertions next looks better.

\Assert\ThatOneOf($x, '-30 < x < -20 || -10 < x < 10 || 20 < x < 30 || 40 < x < 50')
    ->range(-30, -20)
    ->range(-10,  10)
    ->range( 20,  30)
    ->range( 40,  50)
    ->end();

What do you think about it?

Tag/release required

Hi.

Please can you tag/release master. The Date assertion is very useful and including a frozen version is so much nicer than shipping master.

If you are unable to continue maintenance, then I'm happy to take over.

alnum() misleading, should use ctype_alnum()

Currently, Assertion::alnum() tests that a value consists of alphabetic and numeric characters only and starts with a letter. I think this is misleading, as it is different to what ctype_alnum() does.

I think that alnum() should be changed to use ctype_alnum() internally, moreover helpers for the other ctype_*() functions should be implemented.

We can add another helper testing that a string starts with a letter: startsWithLetter (using ctype_alpha($string[0]) internally) - analogous to startsWith

What do you think?

Missing null/isNull assertion

Hi. Is there a reason why there is an assertion notNull but isNull/null assertion is missing? I know same can be used instead but it is also possible to use notSame instead of notNull. Looks like it's not consistent. But I believe there is a reason behind this. Or not?

Fluent API does not use own Assertion class

There is no way to use a specific Assertion class when using the fluent api. So using fluent api andd an own excpetion type at the same time have a drawback to me. When changing the assertion a differnt exception will be thrown.

try {
    \My\Custom\Assertion::notNull(null);
    // throws \My\Custom\Assertion::$exceptionClass

    \Assert\that(null)->notNull();
    // throws \Assert\Assertion::$exceptionClass
}
catch(\My\Custom\AssertionFailedException $e) {
    // ...
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.