li₃ is the fast, flexible and most RAD development framework for PHP

Overview

li₃

You asked for a better framework. Here it is.

li₃ is the fast, flexible and the most RAD development framework for PHP.

A framework of firsts

li₃ is the first and only major PHP framework built from the ground up for PHP 5.3+, and the first to break ground into major new technologies, including bridging the gap between relational and non-relational databases through a single, unified API.

Promiscuously opinionated

Some frameworks give you a solid set of classes, but little or no default project organization, leaving you to fend for yourself on each project you create, and spend time wiring up framework classes that should just work together. Others provide you with great organizational conventions, but no way to break out of those conventions if you need to, and too often, no way to override or replace core framework classes.

li₃ is the first framework to give you the best of both worlds, without compromising either. In fact, li₃'s API is intentionally designed to allow you to "grow out of" the framework and into your own custom code over the course of your application's lifecycle, if your needs require.

Technology

li₃ takes full advantage of the latest PHP features, including namespaces, late static binding and closures. li₃'s innovative method filter system makes extensive use of closures and anonymous functions to allow application developers to "wrap" framework method calls, intercepting parameters before, and return values after.

li₃ also complies with PSR-4, the PHP namespacing standard, allowing you to easily integrate other PHP standard libraries and frameworks with li₃ applications, and vice-versa.

li₃ integrates the latest storage technologies, including MongoDB, CouchDB and Redis, with plugin support for Cassandra, ElasticSearch and others.

Flexibility

li₃ gives you full control over your application, from filters to dynamically modify framework internals, to dynamic dependencies to extend and replace core classes with application or plugin classes, to heavy use of adapter-oriented configurations, to make it seamless to move between different technologies and options.

Every component of the li₃ framework stack is replaceable through the robust plugin architecture. Swap out the default ORM / ODM implementation for Doctrine 2 or PHP ActiveRecord. Don't like the templating? Use Twig, Mustache, or roll your own.

If you don't even need to write a full application, build a micro-app in a single file using the routing system, without giving up the maintainability of the framework's structure.

Comments
  • I don't like Li3 because...

    I don't like Li3 because...

    Don't be shy, express yourself on things you don't like in Li3. Don't be stingy with criticisms (I personally like being abused). Makes your criticism as detailed as possible with comparisons with how it works with your favorite framework if possible.

    Thanks in advance for helping us to make Li3 an even better framework.

    rfc 
    opened by jails 57
  • Plain test output

    Plain test output

    Example of usage:

    bash console/li3 test tests --format=plain |& tee plain.txt
    

    Example Output:

    before:

    ----
    Test
    ----
    
    S.......................SS......SSS.........................
    ............................................................
    ..S...F.....................................................
    ..SSSSSSSSSSSSS.............................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ...............E..E.........................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ................
    

    After:

    ----
    Test
    ----
    
    S.......................SS......SSS.........................
    ............................................................
    ..S...F.....................................................
    ..SSSSSSSSSSSSS.............................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ...............E..E.........................................
    ............................................................
    ............................................................
    ............................................................
    ............................................................
    ................
    
    enhancement 
    opened by shopblocks 41
  • Lithium Package and Dependency Management

    Lithium Package and Dependency Management

    What about using http://packagist.org and composer to manage plugin dependencies? It looks like it is getting more traction and maybe we can integrate it with the Library class too. Also, if people are encouraged to add their plugins there too we have a "central" repository of libraries which can easily be reused.

    This is marked as an RFC and it would be cool to get comments both from the core devs and the community to see what they think about it and how they want to use it.

    Regards, Michael

    rfc 
    opened by daschl 39
  • Lithium Documentation Hack Day!

    Lithium Documentation Hack Day!

    The biggest suggestion, from our users, is for better documentation so on Saturday, May 18th 2013 starting at 9am CST (-6) to 5pm CST we are having our very first documentation hack day!

    This is when we all get together and add as much documentation do the code comments or the li3 manual.

    Right now, list below things you wish were more documented such as classes, methods, procedures, or anything you just don't understand after reading the current documentation!

    Later, on May 18th head into #li3 on irc.freenode.net and we'll get to work! We can give you something to document, or feel free to work on one you know a little about or want to learn about by documenting it. We'll keep the discussion going to prevent overlapping.

    Anybody can contribute, so I'll see you then!

    Add to Google Calendar

    docs 
    opened by bayleedev 35
  • error in save entity without all fields that is defined in model validate .

    error in save entity without all fields that is defined in model validate .

    when you find entity model with fields parameter and this result don't include fields that has defined in model validate, you can't save it and you take validate error on not selected fields.

    opened by koushki 31
  • Add psr-0 autoloading with target-dir to composer.json

    Add psr-0 autoloading with target-dir to composer.json

    This lifts the dependency on composer/installers and uses composer autoloading directly.

    This makes lithium no longer install into /libraries/lithium, but instead puts it into /vendor/UnionOfRad/lithium/lithium (second lithium is needed for psr-0 path completion).

    Now, I'm not sure if you actually want this. The benefit of doing so is that it plays nice with everyone else. Instead of saying "fuck you, I'm going to make my own folder", putting everything in the vendor dir allows all the library code to be in one place, and the end user can customize it if he wants to.

    Let me know if you have any questions.

    This PR replaces #916. It was originally spawned off of composer/composer#1865.

    opened by igorw 31
  • RFC: New MongoClient class of MongoDB Native Driver version 1.3.0

    RFC: New MongoClient class of MongoDB Native Driver version 1.3.0

    There is a shift coming in the MongoDB Native Driver for PHP: http://blog.mongodb.org/post/36666163412/introducing-mongoclient?yey

    Specifically as of version 1.3.0, Mongo will be deprecated and replaced with MongoClient

    There's a few new features, that I'm aware of:

    • Write Concern, which will replace safe and fsync.
      • array("w" => 3)
    • Read Preference which provides better control than setSlaveOkay over replica sets.
      • array("readPreference" => MongoClient::RP_PRIMARY_PREFERRED)

    (see: http://us2.php.net/manual/en/mongoclient.construct.php for reference)

    rfc 
    opened by ericcholis 31
  • SQLite everyother row

    SQLite everyother row

    I have a users table which I get all rows (there are 4 total) by calling

    $users = Users::all();
    

    my index page displays my results

            <?php foreach ($users as $user) { ?>
                <li>
                    <?=$user->username; ?>
                </li>
            <?php } ?>
    

    of which only 2 show, with ids 1 and 3 showing

    a call to $users->count(); returns 2 results

    querying the $sql variable shows: SELECT * FROM "users" AS "Users";

    If I delete the row with id 1, ids 2 and 4 will show.

    My conclusion is that for some reason, only every other row will get returned to the record set. I created a quick php page to query the sqlite table and there are 4 rows to begin with, and my deletion of row with id 1 will only delete that one row. My php page:

    
    try {
        //open the database
        $db = new PDO('sqlite:..\data\PSER.db');
    
        //create the database
        //$db->exec("CREATE TABLE users(id integer PRIMARY KEY, username text UNIQUE NOT NULL, password text, usertype integer)");    
        //$db->exec("ALTER TABLE users ADD COLUMN usertype");
    
        //now output the data to a simple html table...
        print "<table border=1>";
        print "<tr><td>id</td><td>username</td><td>password</td><td>usertype</td></tr>";
        $result = $db->query('SELECT * FROM "users" AS "Users"');
        foreach($result as $row)
        {
          print "<tr><td>".$row['id']."</td>";
          print "<td>".$row['username']."</td>";
          print "<td>".$row['password']."</td>";
          print "<td>".$row['usertype']."</td></tr>";
        }
        print "</table>";
    
        // close the database connection
        $db = NULL;
    }
    catch(PDOException $e) {
        print 'Exception : '.$e->getMessage();
    }
    
    
    ?>
    

    I got pulled down lithium from git on the 2nd, what am I doing wrong?

    bug 
    opened by tonyeung 31
  • Exporter::_update is giving bad results with embedded documents

    Exporter::_update is giving bad results with embedded documents

    I have created a little test for anyone willing to check it out: http://pastium.org/view/4a35aeb1bf856634d7185df970bc7981

    Basically, after saving the second list of documents in "otherDocs", the content of "docs" is inserted inside the parent document which we don't want...

    I've been looking at the _update method inside Exporter.php and it seems the results it's giving for embedded documents are not really appropriate.

    Hope this helps!

    (Mongo version 1.8.2)

    bug 
    opened by marcghorayeb 31
  • \lithium\data\source\Database should use closures to format values, particularly for date-like values like timestamp

    \lithium\data\source\Database should use closures to format values, particularly for date-like values like timestamp

    Originally discussed in #855, the current formatters don't pass through constant values like MySQL's CURRENT_TIMESTAMP when set as the default value for a column in the database. This fixes that issue by replacing the named function date with a closure that can be overridden by subclasses. It also addresses deprecating the odd _toNativeBoolean() method that acts as a formatter on the Postgres adapter in favor of this new approach. A patch for the Postgres adapter is included.

    opened by al-the-x 29
  • Fix assert conflicts in `test\Unit` adding `assetNotIdentical()`

    Fix assert conflicts in `test\Unit` adding `assetNotIdentical()`

    • assertXX & assertNotXX should share the same code base.
    • consistent API for assertNull() / assetNotNull().
    • adding missing assetNotIdentical().
    • normalize line endings.
    • typo fix: renaming $actual to $result all way long
    • remove assertRegExp(), conflict with assertPattern().
    • remove assertNotRegExp, conflict with assertNoPattern().
    • remove assertEmpty(), conflict with assertFalse().
    • remove assertNotEmpty(), conflict with assertTrue().
    opened by jails 29
  • redis config select database

    redis config select database

    Redis use database 0 by default. In my project, I had to get the data from another database. I read this document. I added the selected database configuration to the lovely lithium.

    opened by ehsansabet 0
  • Unable to use JSON query operands in fields list

    Unable to use JSON query operands in fields list

    Lithium Version: 1.0

    $data = MyModel::all([
        'fields' => [
            'IFNULL(prices->\'$."1"\', prices->\'$."default"\') as MyModel.price',
        ],
    ])->data();
    

    I'm trying to access a value of a json field in my field list (returns many results and processing serverside isn't very feasible because of speed concerns). I'm getting an error in /data/source/Database.php on line 680. It appears to be splitting all the field name values on '.' in order to sort them?

    I have also tried 'MyModel.price' => 'IFNULL(prices->\'$."1"\', prices->\'$."default"\')' and received the same result.

    To my knowledge there is no way to retrieve data from a JSON field within a query without specifying a path, which requires using the '$.field' notation. Is there a way for me to mark this as a calculated field and prevent this from happening? Alternately is there an official way to access JSON fields with li3, or to disable this "sorting" from occurring?

    opened by texonidas 0
  • couchdb 2.3 is not working with lithium

    couchdb 2.3 is not working with lithium

    In case of Couchdb 2.3 the method: $this->connection->{$method}($path, $data, $options); in https://github.com/UnionOfRAD/lithium/blob/bec3f4fdf61ea5002904754f43941ad1430ecec7/data/source/http/adapter/CouchDb.php#L122 is an array instead of string..

    This breaks the logic inside of the describe function.

    opened by alexanderhaensch 1
  • Detect correct type on request when there are multiple media types mapped to the same content type

    Detect correct type on request when there are multiple media types mapped to the same content type

    In the case where multiple types are registered to lithium\net\http\Media with the same content type, even when distinguished by conditions, an instance of lithium\action\Request will fail to determine the correct type to use to decode the request body. For example, if we register another type which uses 'application/json' as a content type like this:

    use lithium\net\http\Media;
    
    Media::type('json_base64', ['application/json'], [
        'encode' => function ($data) {
            return base64_encode(json_encode($data));
        },
        'decode' => function ($data) {
            return json_decode(base64_decode($data), true);
        },
        'cast' => true,
        'conditions' => [
            'http:content_transfer_encoding' => 'base64'
        ]
    ]);
    

    A call to Media::type('application/json') will return an array like:

    [
    	'json_base64',
    	'json'
    ]
    

    This case is not handled by lithium\net\http\Message::type(), which causes lithium\action\Request::$_type to be assigned as the content type of 'application/json'.

    Futhermore, when Request::body() is called to decode the request body, the Media class fails to find a handler for 'application/json' (it expects a short name like 'json').

    To fix this, lithium\net\http\Message::type() must be extended by lithium\action\Request. In the case that $type is a string and equals the result of the parent's call, we can loop over each type returned by Media::type() and attempt to match the request to it like this:

    public function type($type = null) {                                            
        if (!$type && !empty($this->params['type'])) {                              
            $type = $this->params['type'];                                          
        }                                                                           
        $_type = parent::type($type);                                               
        if (is_string($type) && $_type === $type) {                                 
            $media = $this->_classes['media'];                                      
            $content = $media::type($type);                                         
            if (is_array($content) && !isset($content['content'])) {                
                foreach ($content as $short_type) {                                 
                    $conf = $media::type($short_type);                              
                    $conf['name'] = $short_type;                                    
                    if ($media::match($this, $conf)) {                              
                        $_type = $short_type;                                       
                        break;                                                      
                    }                                                               
                }                                                                   
            }                                                                       
        }                                                                           
        return ($this->_type = $_type);                                             
    }
    

    This will correctly determine a single short name to use for the type of the request data, and it can now correctly decode the request body.

    opened by gscherer 2
Releases(v2.0.0)
  • v2.0.0(Dec 8, 2022)

    Change Log

    v2.0.0

    Changed

    • Dropped support for PHP 7.x

    • The Mongo data source adapter has been updated to work with the mongodb extension instead of the old mongo extension. This brings back full li₃ support for MongoDB on PHP 7.x. Due to how the new extension works, we do not support GridFS through the adapter anymore. You can still access GridFS using the underlying connection object. (Simon Jaillet, Dirk Brünsicke)

    • Removed deprecated functionality: magic download header in action response, unit testing's expectException method. (David Persson)

    • ConfigExceptions (thrown when accessing non existent configurations) are now allowed to bubble up in Cache.

    • The following previously deprecated things have been removed:

      • The XCache Cache adapter
      • Glob brace support in Libraries
      • Per adapter filters
      • The String class
      • Long options like --foo-bar are now only made available as fooBar and not foo-bar after parsing in the console router.
      • The test Mocker class
      • Support for mcrypt in the sesion Encrypt strategy
      • Support for old-style rendering instructions i.e. ['template' => '/path/to/template']
      • The FirePhp logging adapter
      • Support for old-style AOP filters
      • Support for gernally retrieving class parents via _parents(), it is still possible to call this method in subclasses of Controller and Model.
      • Support for generally halting executing via _stop(), it is still possible to call this method in subclasses of Controller and `Command.
      • Support for generally using __set_state().
      • Support for generally using respondsTo().
      • Support for generally using invokeMethod().
      • Support for generally using _instance().
    • The Apc adapter has been migrated from the traditional, now-unsupported APC extension, to APCu. No code changes are required—simply upgrade to the new extension.

    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Dec 8, 2022)

    Change Log

    v1.3.0

    This is an API-compatible upgrade of Li3 1.2 for all users of PHP 7.4.

    Added

    • PHP 7.4 support

    Removed

    • PHP 7.3 support (and below)
    Source code(tar.gz)
    Source code(zip)
Owner
Union of RAD
Community of developers helping each other write better software.
Union of RAD
Flare is a PHP full-stack web framework that is light, fast, flexible, and secure.

Flare framework is a PHP full-stack web framework that is simple ,powerful , fast , flexible, and secure with long-term support.

Flare framework 3 Oct 24, 2022
CodeIgniter - a PHP full-stack web framework that is light, fast, flexible and secure

CodeIgniter 4 Development What is CodeIgniter? CodeIgniter is a PHP full-stack web framework that is light, fast, flexible and secure. More informatio

CodeIgniter 4 web framework 4.5k Jan 4, 2023
Framework used for most of my PHP projects.

PHP boilerplate code that most of my php projects share. Requires php: >=7.3 ext-json: * ext-pdo: * ext-phalcon: >=4.0.0 ext-posix: * ext-

Dennis Stücken 1 Jan 12, 2022
🚀Hyperf is an extremely performant and flexible PHP CLI framework

Hyperf is an extremely performant and flexible PHP CLI framework, powered by a state-of-the-art coroutine server and a large number of battle-tested components. Aside from decisively beating PHP-FPM frameworks in benchmarks, Hyperf is unique in its focus on flexibility and composition.

Hyperf 4.9k Dec 30, 2022
Hyperf is an extremely performant and flexible PHP CLI framework

?? A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.

Hyperf 5k Jan 4, 2023
FuelPHP v1.x is a simple, flexible, community driven PHP 5.3+ framework, based on the best ideas of other frameworks, with a fresh start! FuelPHP is fully PHP 7 compatible.

FuelPHP Version: 1.8.2 Website Release Documentation Release API browser Development branch Documentation Development branch API browser Support Forum

Fuel 1.5k Dec 28, 2022
CleverStyle Framework is simple, scalable, fast and secure full-stack PHP framework

CleverStyle Framework is simple, scalable, fast and secure full-stack PHP framework. It is free, Open Source and is distributed under Free Public Lice

Nazar Mokrynskyi 150 Apr 12, 2022
Framework X is a simple and fast micro framework based on PHP

Framework X is a simple and fast micro framework based on PHP. I've created a simple CRUD application to understand how it works. I used twig and I created a custom middleware to handle PUT, DELETE methods.

Mahmut Bayri 6 Oct 14, 2022
PHP Kafka client is used in PHP-FPM and Swoole. PHP Kafka client supports 50 APIs, which might be one that supports the most message types ever.

longlang/phpkafka Introduction English | 简体中文 PHP Kafka client is used in PHP-FPM and Swoole. The communication protocol is based on the JSON file in

Swoole Project 235 Dec 31, 2022
Framework X – the simple and fast micro framework for building reactive web applications that run anywhere.

Framework X Framework X – the simple and fast micro framework for building reactive web applications that run anywhere. Quickstart Documentation Tests

Christian Lück 620 Jan 7, 2023
QPM, the process management framework in PHP, the efficient toolkit for CLI development. QPM provides basic daemon functions and supervision mechanisms to simplify multi-process app dev.

QPM QPM全名是 Quick(or Q's) Process Management Framework for PHP. PHP 是强大的web开发语言,以至于大家常常忘记PHP 可以用来开发健壮的命令行(CLI)程序以至于daemon程序。 而编写daemon程序免不了与各种进程管理打交道。Q

Comos 75 Dec 21, 2021
Hamtaro - the new web framework for front-end / back-end development using Php and Javascript.

Hamtaro framework About Technologies Controllers Components Commands Front-end development Getting Started About Hamtaro is the new web framework for

Phil'dy Jocelyn Belcou 3 May 14, 2022
Yii 2: The Fast, Secure and Professional PHP Framework

Yii 2 is a modern framework designed to be a solid foundation for your PHP application. It is fast, secure and efficient and works right out of the bo

Yii Software 14k Dec 31, 2022
Fast and easy PHP framework

Español | English Fácil, rápido y en español (Or should I say fast and easy?) Bienvenidos a KumbiaPHP Framework Versión 1 Manual en construcción de la

KumbiaPHP Framework 281 Jan 2, 2023
A powerful yet easy-to-use PHP micro-framework designed to help you build dynamic and robust Web applications - fast!

A powerful yet easy-to-use PHP micro-framework designed to help you build dynamic and robust Web applications - fast! Condensed in a single ~65KB file

Bong Cosca 2.6k Dec 30, 2022
Woski is a fast and simple lightweight PHP Framework for building applications in the realm of the web.

Woski is a simple fast PHP framework for the Realm The Project Installation Clone the repository $ composer create-project clintonnzedimma/woski myApp

Clinton Nzedimma 19 Aug 15, 2022
Simple, fast and secure PHP Framework with easy integration.

simple-php-framework Simple, fast and secure PHP Framework with easy integration.

winact 2 Nov 23, 2021
Fast and easy PHP framework

Español | English Fácil, rápido y en español (Or should I say fast and easy?) Bienvenidos a KumbiaPHP Framework Versión 1 Manual en construcción de la

KumbiaPHP Framework 280 Dec 26, 2022
A super fast, customizable and lightweight PHP MVC Starter Framework to extend for your own...

PHPMVC A super fast, customizable and lightweight PHP MVC Starter Framework to extend for your own... How to Start Clone this repo - git clone https:/

Maniruzzaman Akash 9 Dec 11, 2022