Convert Figma logo to code with AI

Anahkiasen logounderscore-php

A redacted PHP port of Underscore.js with additional functions and goodies – Available for Composer and Laravel

1,121
88
1,121
36

Top Related Projects

32,133

The Laravel Framework.

29,606

The Symfony PHP framework

Collections Abstraction Library

19,650

The PHP Unit Testing framework.

A PHP parser written in PHP

Quick Overview

Underscore-PHP is a PHP port of the popular JavaScript utility library Underscore.js. It provides a set of functional programming helpers that allow you to write concise, expressive, and DRY (Don't Repeat Yourself) code.

Pros

  • Comprehensive Functionality: Underscore-PHP provides a wide range of utility functions, covering areas such as collections, arrays, objects, functions, and more, similar to its JavaScript counterpart.
  • Readability and Expressiveness: The library's functions promote a more declarative and readable coding style, making the code easier to understand and maintain.
  • Cross-Language Compatibility: Developers familiar with Underscore.js can easily transition to using Underscore-PHP, as the APIs are designed to be consistent across the two languages.
  • Active Development and Community: The project has an active community, with regular updates and contributions from developers.

Cons

  • Dependency on External Library: Underscore-PHP is a dependency that needs to be included in your project, which may not be suitable for all use cases.
  • Potential Performance Overhead: The abstraction and functionality provided by the library may introduce some performance overhead compared to writing the same functionality from scratch.
  • Potential Conflicts with Native PHP Functions: Some of the library's function names may conflict with native PHP functions, which could lead to unexpected behavior if not properly managed.
  • Limited Adoption Compared to JavaScript Counterpart: While Underscore-PHP is a well-known library, it may not have the same level of widespread adoption and community support as Underscore.js in the JavaScript ecosystem.

Code Examples

Here are a few examples of how you can use Underscore-PHP in your code:

  1. Filtering and Mapping Collections:
use Underscore\Types\Arrays;

$numbers = [1, 2, 3, 4, 5];
$filteredNumbers = Arrays::filter($numbers, function ($num) {
    return $num > 2;
});
$doubledNumbers = Arrays::map($numbers, function ($num) {
    return $num * 2;
});
  1. Chaining Methods:
use Underscore\Types\Arrays;

$data = [
    ['name' => 'John', 'age' => 30],
    ['name' => 'Jane', 'age' => 25],
    ['name' => 'Bob', 'age' => 35],
];

$result = Arrays::from($data)
    ->where('age', '>', 30)
    ->pluck('name')
    ->value();
  1. Functional Programming Helpers:
use Underscore\Types\Functions;

$add = function ($a, $b) {
    return $a + $b;
};
$multiply = function ($a, $b) {
    return $a * $b;
};

$result = Functions::compose($multiply, $add)(2, 3);
  1. Object Manipulation:
use Underscore\Types\Objects;

$person = [
    'name' => 'John Doe',
    'age' => 30,
    'email' => 'john@example.com',
];

$updatedPerson = Objects::extend($person, [
    'age' => 31,
    'phone' => '555-1234',
]);

Getting Started

To get started with Underscore-PHP, you can follow these steps:

  1. Install the library using Composer:
composer require anahkiasen/underscore-php
  1. Import the required classes and start using the library in your PHP code:
use Underscore\Types\Arrays;
use Underscore\Types\Objects;

$data = [
    ['name' => 'John', 'age' => 30],
    ['name' => 'Jane', 'age' => 25],
    ['name' => 'Bob', 'age' => 35],
];

$names = Arrays::pluck($data, 'name');
$oldestPerson = Objects::max($data, 'age');
  1. Refer to the [Underscore-PHP

Competitor Comparisons

32,133

The Laravel Framework.

Pros of Laravel Framework

  • Comprehensive full-stack framework with built-in features for routing, ORM, authentication, and more
  • Large ecosystem with extensive documentation and community support
  • Regular updates and long-term support

Cons of Laravel Framework

  • Steeper learning curve due to its extensive feature set
  • Potentially heavier and slower for simple applications
  • More opinionated, which may limit flexibility in some cases

Code Comparison

Laravel Framework:

Route::get('/users', function () {
    $users = User::all();
    return view('users.index', compact('users'));
});

Underscore-php:

$users = __::filter($allUsers, function($user) {
    return $user->isActive();
});

Summary

Laravel Framework is a full-featured PHP framework offering a complete ecosystem for web application development. It provides a wide range of built-in tools and features, making it suitable for complex projects. However, this comprehensiveness can lead to a steeper learning curve and potential overhead for simpler applications.

Underscore-php, on the other hand, is a utility library focused on providing functional programming helpers for PHP. It's lightweight and easy to integrate into existing projects, but lacks the full-stack capabilities of Laravel.

Choose Laravel Framework for comprehensive web application development, and Underscore-php for adding functional programming utilities to your PHP projects.

29,606

The Symfony PHP framework

Pros of Symfony

  • Comprehensive full-stack framework with extensive features and components
  • Large, active community and ecosystem with extensive documentation
  • Well-established, battle-tested in enterprise environments

Cons of Symfony

  • Steeper learning curve due to its size and complexity
  • Can be overkill for smaller projects or simple applications
  • Potentially slower performance compared to lightweight libraries

Code Comparison

Symfony (Routing):

use Symfony\Component\Routing\Annotation\Route;

class ProductController extends AbstractController
{
    #[Route('/product/{id}', name: 'product_show')]
    public function show(int $id): Response
    {
        // ...
    }
}

Underscore-php (Array manipulation):

use Underscore\Types\Arrays;

$array = [1, 2, 3, 4, 5];
$filtered = Arrays::filter($array, function($value) {
    return $value % 2 == 0;
});

Summary

Symfony is a full-featured PHP framework suitable for large-scale applications, while Underscore-php is a utility library focused on array and object manipulation. Symfony offers a complete ecosystem but may be complex for simple projects, whereas Underscore-php provides targeted functionality with a simpler learning curve. The choice between them depends on project requirements and scale.

Collections Abstraction Library

Pros of Collections

  • More focused on object-oriented collection handling
  • Better integration with Doctrine ORM and other Doctrine projects
  • Stronger type safety and consistency

Cons of Collections

  • Less extensive array manipulation functions
  • Steeper learning curve for developers not familiar with Doctrine ecosystem
  • More verbose syntax for simple operations

Code Comparison

Collections:

$collection = new ArrayCollection([1, 2, 3, 4, 5]);
$filtered = $collection->filter(function($item) {
    return $item % 2 == 0;
});

Underscore-php:

$array = [1, 2, 3, 4, 5];
$filtered = __::filter($array, function($item) {
    return $item % 2 == 0;
});

Summary

Collections is more suited for complex object-oriented applications, especially those using Doctrine ORM. It provides stronger type safety and consistency but may be overkill for simple array operations.

Underscore-php offers a wider range of array manipulation functions and has a simpler syntax for basic operations. It's more accessible for developers coming from JavaScript backgrounds or working on smaller projects.

The choice between the two depends on the project's complexity, integration requirements, and the development team's familiarity with each library's paradigms.

19,650

The PHP Unit Testing framework.

Pros of PHPUnit

  • Industry standard for PHP unit testing, widely adopted and supported
  • Comprehensive feature set for testing, including mocking and code coverage
  • Extensive documentation and community resources

Cons of PHPUnit

  • Steeper learning curve compared to Underscore-php
  • More complex setup and configuration required
  • Primarily focused on testing, while Underscore-php offers utility functions

Code Comparison

PHPUnit (Test Case):

class CalculatorTest extends PHPUnit\Framework\TestCase
{
    public function testAdd()
    {
        $this->assertEquals(4, Calculator::add(2, 2));
    }
}

Underscore-php (Utility Function):

use Underscore\Types\Arrays;

$result = Arrays::filter([1, 2, 3, 4], function($value) {
    return $value % 2 == 0;
});

Summary

PHPUnit is a robust testing framework for PHP, offering comprehensive testing capabilities and wide industry adoption. It requires more setup and has a steeper learning curve compared to Underscore-php. Underscore-php, on the other hand, focuses on providing utility functions for array and object manipulation, making it more suitable for general-purpose use in PHP projects. The choice between the two depends on the specific needs of your project: testing (PHPUnit) or utility functions (Underscore-php).

A PHP parser written in PHP

Pros of PHP-Parser

  • More powerful and flexible for analyzing and manipulating PHP code
  • Provides a complete Abstract Syntax Tree (AST) representation of PHP code
  • Actively maintained with regular updates and improvements

Cons of PHP-Parser

  • Steeper learning curve due to its complexity and focus on low-level parsing
  • May be overkill for simple string or array manipulations
  • Requires more setup and configuration for basic tasks

Code Comparison

PHP-Parser (parsing PHP code):

$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
$ast = $parser->parse('<?php echo "Hello World!";');

underscore-php (string manipulation):

$greeting = __::stringCase('hello world', 'title');
echo $greeting; // Outputs: "Hello World"

Summary

PHP-Parser is a powerful tool for parsing and analyzing PHP code, offering a complete AST representation. It's ideal for complex code analysis and manipulation tasks. underscore-php, on the other hand, focuses on providing utility functions for common operations like string and array manipulations, making it more suitable for simpler tasks and easier to use for beginners. The choice between the two depends on the specific requirements of your project and the level of code analysis needed.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Underscore.php

Build Status Latest Stable Version Total Downloads Scrutinizer Quality Score Code Coverage Support via Gittip

The PHP manipulation toolbelt

First off : Underscore.php is not a PHP port of Underscore.js (well ok I mean it was at first). It's doesn't aim to blatantly port its methods, but more port its philosophy.

It's a full-on PHP manipulation toolbet sugar-coated by an elegant syntax directly inspired by the Laravel framework. Out through the window went the infamous __(), replaced by methods and class names that are meant to be read like sentences à la Rails : Arrays::from($article)->sortBy('author')->toJSON().

It features a good hundred of methods for all kinds of types : strings, objects, arrays, functions, integers, etc., and provides a parsing class that help switching from one type to the other mid-course. Oh also it's growing all the time. The cherry on top ? It wraps nicely around native PHP functions meaning Strings::replace is actually a dynamic call to str_replace but with the benefit of allowed chaining and a finally consistant argument order (all functions in Underscore put the subject as the first argument, NO MATTER WHAT).

It works both as a stand-alone via Composer or as a bundle for the Laravel framework. So you know, you don't really have any excuse.

Install Underscore

To install Underscore.php simply run composer require anahkiasen/underscore-php. Note that Underscore's type classes (Arrays/Strings/etc) are by default namespaced in the Types folder, so to use Arrays, you would do the following :

use Underscore\Types\Arrays;

Using Underscore

It can be used both as a static class, and an Object-Oriented class, so both the following are valid :

$array = array(1, 2, 3);

// One-off calls to helpers
Arrays::each($array, function($value) { return $value * $value; }) // Square the array
Function::once($myFunction) // Only allow the function to be called once
Number::paddingLeft(5, 5) // Returns '00005'
Object::methods($myObject) // Return the object's methods
Strings::length('foobar') // Returns 6

// Or chain calls with the 'from' method
Arrays::from($array)->filter(...)->sort(...)->get(2)

// Which does this in the background
$array = new Arrays($array);
$array->filter(...)->sort(...)->get(2)

For those nostalgic of ye old __() a generic Underscore class is provided that is able to go and fetch methods in all of Underscore.php's methods. For this it looks into the methods it knows and analyzes the subject of the method (meaning if you do Underscore::contains('foobar', 'foo') it knows you're not looking for Arrays::contains).

On types : it's important to note that using a specific type class to create an Underscore repository will convert the type of provided subject. Say you have an object and do new Arrays($myObject) – this will convert the object to an array and allow you to use Arrays methods on it. For this Underscore uses its Parse class's methods that for the most part just type cast and return (like this (array) $object) but it also sometimes go the extra mile to understand what you want to do : if you convert an array to a string, it will transform it to JSON, if you transform an array into an integer, it returns the size of the array, etc.

The core concept is this : static calls return values from their methods, while chained calls update the value of the object they're working on. Which means that an Underscore object don't return its value until you call the ->obtain method on it — until then you can chain as long as you want, it will remain an object. The exception are certains properties that are considered breakers and that will return the object's value. An example is Arrays->get.

Note that since all data passed to Underscore is transformed into an object, you can do this sort of things, plus the power of chained methods, it all makes the manipulation of data a breeze.

$array = new Arrays(['foo' => 'bar']);

echo $array->foo // Returns 'bar'

$array->bis = 'ter'
$array->obtain() // Returns array('foo' => 'bar', 'bis' => 'ter')

Customizing Underscore

Underscore.php provides the ability to extend any class with custom functions so go crazy. Don't forget that if you think you have a function anybody could enjoy, do a pull request, let everyone enjoy it !

Strings::extend('summary', function($string) {
  return Strings::limitWords($string, 10, '... — click to read more');
});

Strings::from($article->content)->summary()->title()

You can also give custom aliases to all of Underscore's methods, in the provided config file. Just add entries to the aliases option, the key being the alias, and the value being the method to point to.

Extendability

Underscore.php's classes are extendable as well in an OOP sense. You can update an Underscore repository with the setSubject method (or directly via $this->subject = granted you return $this at the end). When creating an Underscore repository, by default it's subject is an empty string, you can change that by returning whatever you want in the getDefault method.

class Users extends Arrays
{
  public function getDefault()
  {
    return 'foobar';
  }

  public function getUsers()
  {
    // Fetch data from anywhere

    return $this->setSubject($myArrayOfUsers);
  }
}

$users = new Users; // Users holds 'foobar'
$users->getUsers()->sort('name')->clean()->toCSV()

// Same as above
Users::create()->getUsers()->sort('name')->clean()->toCSV()

It is important to not panic about the mass of methods present in Underscore and the dangers extending one of the Types would cause : the methods aren't contained in the classes themselves but in methods repositories. So if you extend the Strings class and want to have a length method on your class that has a completely different meaning than Strings::length, it won't cause any signature conflict or anything.

Also note that Underscore method router is dynamic so if your subject is an array and mid course becomes a string, Underscore will always find the right class to call, no matter what you extended in the first place. Try to keep track of your subject though : if your subject becomes a string, calling per example ->map will return an error.

Call to native methods

Underscore natively extends PHP, so it can automatically reference original PHP functions when the context matches. Now, PHP by itself doesn't have a lot of conventions so Arrays:: look for array_ functions, Strings:: look for str_ plus a handful of other hardcoded redirect, but that's it. The advantage is obviously that it allows chaining on a lot of otherwise one-off functions or that only work by reference.

Arrays::diff($array, $array2, $array3) // Calls `array_diff`
Arrays::from($array)->diff($array2, $array3)->merge($array4) // Calls `array_diff` then `array_merge` on the result

Documentation

You can find a detailed summary of all classes and methods in the repo's wiki or the official page. The changelog is available in the CHANGELOG file.

About Underscore.php

There is technically another port of Underscore.js to PHP available on Github — I first discovered it when I saw it was for a time used on Laravel 4. I quickly grew disapoint of what a mess the code was, the lack of updates, and the 1:1 mentality that went behind it.

This revamped Underscore.php doesn't aim to be a direct port of Underscore.js. It sometimes omits methods that aren't relevant to PHP developers, rename others to match terms that are more common to them, provides a richer syntax, adds a whole lot of methods, and leaves room for future ones to be added all the time — whereas the previous port quickly recoded all JS methods to PHP and left it at that.

If you come from Javascript and are confused by some of the changes, don't put all the blame on me for trying to mess everything up. A basic example is the map function : in PHP it has a completely different sense because there exists an array_map function that basically does what __::invoke does in JS. So map is now Arrays::each. Always keep in mind this was made for PHP developpers first, and differences do exist between the two to accomdate the common terms in PHP.