Giter Club home page Giter Club logo

parable's Introduction

DEPRECATION NOTICE

NOTE: devvoh/parable:1.2.2 is now no longer being developed. For the next chapter in Parable's future, go to parable-php/framework for the 2.0.0 version.

Parable 2.0.0 is a full rewrite, but it is possible to move over an application built on the 1.0 family to 2.0 in a reasonable time. If you need any assistance, please open an issue here.

Thank you for supporting Parable!

Parable PHP Framework

Build Status Latest Stable Version Latest Unstable Version License StyleCI

Parable is a PHP micro-framework intended to be readable, extensible and out-of-your-way.

Installation

Parable can be installed by using Composer.

$ composer require devvoh/parable

This will install Parable and all required dependencies. Parable requires PHP 5.6 or higher.

Simple Usage

Create an index.php file and include the composer autoloader:

<?php
require_once __DIR__ . '/vendor/autoload.php';

$app = \Parable\DI\Container::create(\Parable\Framework\App::class);

$app->get('/hello/{name}', function ($name) use ($app) {
    return "Hello, {$name}!";
});

$app->run();

Then go into the vendor/devvoh/parable directory and run make server. You can then open http://127.0.0.1:5678/hello/parable and you should be greeted by "Hello, parable!". You can also serve it through a regular webserver.

Advanced Usage

To use Parable for more than straightforward apps like in the Basic Usage above, and you want to use Controllers, Actions, Views and more, after installation, run the following command:

$ vendor/bin/parable init-structure

Now you're ready! Simply open the url it should be at in in your browser and you should see a welcome page.

If you want to use nginx or another server, that's cool too, but as of yet there's no example configuration available.

Getting Started

After you've run parable init-structure, you should have a basic structure to work from. The example files show most of what you'll need to build something. The example \Config\App file includes some of the most important things Parable itself will listen to.

Now, if you want to keep this out of your git (or other vcs) repository, you can place this in a separate config file and exclude it using a .gitignore file.

More information

Read the documentation for more detailed information on how to use Parable, and CHANGELOG.md for recent changes.

Contributing

Any help in improving Parable is much appreciated, but check CONTRIBUTING.md before creating any pull requests.

Contact

Any questions or constructive feedback? Find me at devvoh.com or ask me a question by adding an issue on github. I generally respond fairly quickly, since this is a passion project, after all.

License

Parable PHP Framework is open-sourced software licensed under the MIT license.

parable's People

Contributors

devvoh avatar dmvdbrugge avatar jerry1970 avatar robin-mollie avatar

Stargazers

 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

parable's Issues

ConsoleApp instantiates and prepares every available command

It does init-structure and help itself, and the rest through CommandLoader, while only one will be used.

It probably does this to get to know the name of the command to figure out which command must be run, and help uses this + description too.

This should be optimised to only instantiate the command to run, and I think name and description should be made static (or use Reflection for non-bc-break *shivers*).

To install in doc root or parent?

With a dir public I assumed the project root (with dirs app, public, and vendor) was one level above the document root. (I prefer the app outside the document root.) With a default document root public_html I made a symlink from public_html to public. Works.

But now, buildBaseUrl (in vendor/devvoh/parable/src/Http/Url.php), removing /public/index.php from $_SERVER['SCRIPT_NAME'], results in a URL starting with the domain plus /index.php/, for example:

<link rel="icon" type="image/png" href="http://mytestdomain.dev/index.php/images/icon-32.png">

Easy to change but wanted to let you know.

Allow multiple route files

My next project has lots of endpoints, so lots of defined routes. But I don't want to add them all into Config\App.

I would really appreciate if you'd made loadRoutes working like Framework\App::loadInits().
Or if you thinks that's bloat, maybe two hooks:

  • parable_routing_load_before
  • parable_routing_load_after

What do you think @devvoh? ๐Ÿ™‚

Json->prepare() should have check on valid json_encode

It took a while to find out why a controller action returned false but it was something in an array that could not be converted to a json. The line $content = json_encode($content) made $content = false.

json_last_error_msg() says "Malformed UTF-8 characters, possibly incorrectly encoded". Something with encoding but I am sure my database table is in UTF8 and all scripts are too. Will look into this.

More love for Parable Console, create your own commands

Example command class:

class ModelMakeCommand extends \Parable\Console\Command
{
    protected $name = 'make:model';

    protected $description = 'Create a new model class';

    public function fire()
    {
        parent::fire();

        // ...
    }
}
  • Move parable executable one level up (please? ๐Ÿ˜‡ ).
  • Add new \Commands namespace.
  • Export app/Commands with InitializeParableCommand.
  • Things I've missed...

Some inspiration (copied from Laravel Console):

/** Run the console command. */
public function run(\Parable\Console\Input $input, \Parable\Console\Output $output)

/** Execute the console command. */
public function execute(\Parable\Console\Input $input, \Parable\Console\Output $output)

/** Call another console command. */
public function call($command, array $args = [])

/** Call another console command silently. */
public function callSilent($command, array $args = [])

SQL errors not thrown by PDOMySQL class

Several times my SQL queries (which are perfect thanks to Parable's query builder!) failed during execution. I've mistaken a unique index on one of my columns.

But... Parable never warned me! Database::query() simply returned false. Which is legit, according to the PHP docs here.

PDO errors are silenced by default when the occur (see PHP docs once more). Please, make them load with warnings or exceptions (by "Parable default")! ๐Ÿ˜„

Parable views not working for developers with Windows systems

Expected Behavior

A fresh installation of Parable on a Windows system should show the default view (View/Home/index.phtml).

Current Behavior

The default Parable view (View/Home/index.phtml) shows the following output:

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

        <title><br />
<b>Fatal error</b>:  Uncaught ReflectionException: Class ParableC:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Auth\Authentication does not exist in C:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Framework\Toolkit.php:71
Stack trace:
#0 C:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Framework\Toolkit.php(71): ReflectionClass-&gt;__construct('ParableC:\\MAMP\\...')
#1 C:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Framework\Toolkit.php(90): Parable\Framework\Toolkit-&gt;loadResourceMap()
#2 C:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Framework\View.php(123): Parable\Framework\Toolkit-&gt;getResourceMapping('Config')
#3 C:\MAMP\htdocs\cgi_whereabouts_dashboard\app\View\Home\index.phtml(7): Parable\Framework\View-&gt;__get('config')
#4 C:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Framework\View.php(110): require('C:\\MAMP\\htdocs\\...')
#5 C:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Framework\View.p in <b>C:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Framework\Toolkit.php</b> on line <b>71</b><br />

Possible Solution

Our temporary fix in Parable\Framework\Toolkit:

// $fullClassName = str_replace($this->path->getDir('vendor/devvoh/parable/src'), '', $file->getRealPath());
$fullClassName = str_replace($this->path->getDir('vendor\\devvoh\\parable\\src'), '', $file->getRealPath());

You might want to identify the development machine?

Context

As a Mac user I had to code the whole project all by myself.
My team members (Windows users) couldn't do anything for a very very long time, because Windows.

Joke.

Your Environment

  • Version used: Parable 0.8.14+
  • Environment name and version (e.g. Chrome 39, node.js 5.4): Chrome 54
  • Operating System and version (desktop or mobile): Windows 10 (x64)
  • Link to your project: -

MySQL database connection might require charset

After searching for the reason why the json_encode failed that I mentioned in #18 , I found out it had to do with the encoding of the data. I solved this by specifying the charset to the DSN.

In ORM\Database, method createPDOMySQL I changed added ;charset=utf8 to the DSN:

// old
$dsn = 'mysql:host=' . $location . ';dbname=' . $database;
// new
$dsn = 'mysql:host=' . $location . ';dbname=' . $database . ';charset=utf8';

I now get properly formed data from the database and the json_encode succeeds.

Since I used a fixed charset in my previous project and it worked right away, I never spent time figuring out why the PDO connection requires me setting the charset.

With PSR requiring everything in UTF8 and almost everybody creating new projects in UTF8 I can only assume (silly me) that people set their data fields to UTF8 as well so for new projects I don't think adding the fixed charset to the DSN is bad. But for a framework default I can imagine you would want to turn that into a variable.

Add all 'parable.*' to `\Config\App` structure file

Yesterday I got stuck on some fatal error what couldn't be shown, because my parable.debug option wasn't set. I totally forgot the config option existed, until I dove into Parable's source code.

Adding all of Parable's config options into the \Config\App file would be very helpful! ๐Ÿ˜„

Dispatcher & Response don't handle mixed-type content very well

Dispatcher::97:

$content = $this->response->returnOutputBuffer() . $content;

This does not handle array data. Make it:

$bufferContent = $this->response->returnAllOutputBuffers();
if (!empty($bufferContent)) {
    $this->response->appendContent($bufferContent);
}

This still appends it before the provided $content, but lets Response handle the data type.

HOWEVER. Response::248:

public function appendContent($content)
{
    if (!empty($content)) {
        if (is_array($this->content)) {
            $this->content[] = $content;
        } else {
            $this->content .= $content;
        }
    }
    return $this;
}

So okay, cool, we check the type of $this->content and append appropriately.

But what if $this->content is a string but $content is an array?

Quick fix: take $this->content's string value, do $this->setContent([$this->content]); and continue along. From that point on, all content is seen as array values.

Even quicker and more consistent fix: Always store content in an array and just add new key/value pairs always. If setContent() is called with a string, pack it into a new array and boom, consistency.

Mixed types bad.

More consistency in Parable's default folder names

Parable's current application structure:

  • app/Config
  • app/Controller
  • app/Init
  • app/Model
  • app/Routes
  • app/View/Home

I would love to see this application structure use a singular or plural form with folder naming. I'd prefer plural, but some names aren't made for it. ๐Ÿ˜œ

What do you think, @devvoh?

Typo in docs: initLocations should be inits?

From Init\Example:

 * the location of these scripts needs to be set in a Config file, using the root key
 * 'initLocations'. See app/Config/App.php.

From Config\App:

"inits" => [
    \Init\Example::class,

Console/Output: cursor and linelength

Not sure if bug or mis-use but shouldn't cursorBack and -Forward affect the linelength in some way? Consider this case (overly simplified version obviously):

// Inside a Console\App::run()
for ($i = 1; $i <= 1000; $i++) {
    // I could use clearLine() instead, however: I know for sure that whatever I'm
    // writing >= what's already there, thus no need for the actual clearing
    $this->output->cursorBack($this->output->getLineLength());
    $this->output->write($i);
}

$this->output->clearLine();
$this->output->writeln('All done');

What is the final result of this? You'd think it'd be just a single line "All done". However, due to how it works internally, it prints 9 * 1 + 90 * 2 + 900 * 3 + 1 * 4 = 2893 spaces (obviously spanning multiple lines), then tries to move back 2893 places but only goes as far as the start of the current line, and then prints "All done" on the beginning of the line, resulting in a lot of unexpected "blank" lines.

Solution (if you don't consider this a bug) might be something like a new function cursorReset which moves the cursor to the beginning of the line and sets linelength back to 0. This loses the ability to clear the current line, however seeing my given case that's not always needed anyway: replace the cursorBack call with this cursorReset and all behaves as expected ( / needed for this scenario).

However while my case is an extreme one, the mismatch can happen way earlier. Think of a console width of 80 characters, I print 45, go back 15, print another 45. Actual line is now 75, all one line. However because of linelength, clearLine() will print 90 spaces, thus basically inserting a newline.

GetSet that uses php://input?

You've added getBody() to the Request in 0.12.7. But I expected a GetSet class reading the body as well.

There is the abstract class BaseInput with the excellent extractAndSetData(). Its constructor reads the request body and use setAll().

Now, three classes extend from this: Patch, Put, and Delete. These three have a $resource as well, meaning the setAll() will not do anything with the values from the body (see the if block there).

This means there is no GetSet class actually having the body values. I think this is a bug?

I am using axios for my ajax calls and axios uses a HTTP POST with a body. (Not sure why, though, but I like axios enough to keep using it as it flows nicely with vue.)

So... I could request the GetSet\Post extending BaseInput but that would not solve my problem.
Therefore, I think it would be very nice to have something like GetSet\JsonBody that extends BaseInput and does not have a $resource.

extractParameterValues checks for empty(), disabling value '0'

In Route->extractParameterValues, there is a check for if (!empty($value)), which means that the 0 in /api/users/123/access/0 is skipped. Then there is no route match and a 404 follows.

I think checking for an empty string is enough. 0 or '0' should be passed as values as well. Only empty strings are not valid URL parts. The URL is always a string, so NULL will never happen here. I therefore think checking for an empty string is enough to check for in extractParameterValues.

`Repository` should offer `buildAndSet()` and `buildOrSet()` without first needing to call `createQuery()`

Currently, the following is needed to getByConditionSet():

$entityRepository = $this->toolkit->getRepository(\Model\Entity::class);

$entities = $entityRepository->returnOne()->getByConditionSet(
    $entityRepository->createQuery()->buildAndSet([
        ["primary_id", "=", 1],
        ["secondary_id", "=", 1],
    ])
);

The call to $entityRepository->createQuery()->buildAndSet() is awkward in use. Having to call createQuery for this is not intuitive and not easy to discover.

Change this to the following: $entityRepository()->buildAndSet() and simply proxy that onto the Query instance.

Call to undefined function posix_isatty()

devvoh/parable @ e11664f

PHP Fatal error:  Uncaught Error: Call to undefined function Parable\Console\posix_isatty() in C:\(...)\csv2qif\vendor\devvoh\parable\src\Console\Input.php:190
Stack trace:
#0 C:\(...)\csv2qif\vendor\devvoh\parable\src\Console\Input.php(115): Parable\Console\Input->isInteractiveShell()
#1 C:\(...)\csv2qif\vendor\devvoh\parable\src\Console\Input.php(198): Parable\Console\Input->enableShowInput()
#2 [internal function]: Parable\Console\Input->__destruct()
#3 {main}
  thrown in C:\(...)\csv2qif\vendor\devvoh\parable\src\Console\Input.php on line 190

As you can see in the stacktrace: Windows PC. However, code is executed in "Git Bash", which is mostly MinGW. PHP, when running inside this, is not detected as being run on Windows. However, because in reality it is, it doesn't have the posix functions.

I will try to fix this the correct way myself (because obviously edge case) when I have time.

Undefined index 'REQUEST_SCHEME' on MAMP environment

Hi @devvoh,

Congrats on the amazing new pre-release 0.11! ๐ŸŽ‰

But here's the first teeny-tiny bug on a fresh Parable install:

Notice: Undefined index: REQUEST_SCHEME in /Applications/MAMP/htdocs/<project>/vendor/devvoh/parable/src/Http/Url.php on line 17

Dumping the $_SERVER gave me this:

array(46) {
  ["PHP_FCGI_CHILDREN"]=>
  string(1) "4"
  ["PWD"]=>
  string(27) "/Applications/MAMP/fcgi-bin"
  ["SHLVL"]=>
  string(1) "0"
  ["PHP_FCGI_MAX_REQUESTS"]=>
  string(3) "200"
  ["__CF_USER_TEXT_ENCODING"]=>
  string(8) "0x46:0:0"
  ["ORIG_SCRIPT_NAME"]=>
  string(23) "/fcgi-bin/php7.1.1.fcgi"
  ["ORIG_PATH_TRANSLATED"]=>
  string(56) "/Applications/MAMP/htdocs/<project>/public/index.php"
  ["ORIG_PATH_INFO"]=>
  string(10) "/index.php"
  ["ORIG_SCRIPT_FILENAME"]=>
  string(41) "/Applications/MAMP/fcgi-bin/php7.1.1.fcgi"
  ["SCRIPT_NAME"]=>
  string(10) "/index.php"
  ["REQUEST_URI"]=>
  string(1) "/"
  ["QUERY_STRING"]=>
  string(0) ""
  ["REQUEST_METHOD"]=>
  string(3) "GET"
  ["SERVER_PROTOCOL"]=>
  string(8) "HTTP/1.1"
  ["GATEWAY_INTERFACE"]=>
  string(7) "CGI/1.1"
  ["REDIRECT_URL"]=>
  string(10) "/index.php"
  ["REMOTE_PORT"]=>
  string(5) "64231"
  ["SCRIPT_FILENAME"]=>
  string(56) "/Applications/MAMP/htdocs/<project>/public/index.php"
  ["SERVER_ADMIN"]=>
  string(15) "[email protected]"
  ["DOCUMENT_ROOT"]=>
  string(46) "/Applications/MAMP/htdocs/<project>/public"
  ["REMOTE_ADDR"]=>
  string(3) "::1"
  ["SERVER_PORT"]=>
  string(2) "80"
  ["SERVER_ADDR"]=>
  string(3) "::1"
  ["SERVER_NAME"]=>
  string(23) "<project>.localhost"
  ["SERVER_SOFTWARE"]=>
  string(6) "Apache"
  ["SERVER_SIGNATURE"]=>
  string(0) ""
  ["PATH"]=>
  string(29) "/usr/bin:/bin:/usr/sbin:/sbin"
  ["HTTP_COOKIE"]=>
  string(42) "PHPSESSID=<session>"
  ["HTTP_ACCEPT_LANGUAGE"]=>
  string(53) "nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2,fi;q=0.2"
  ["HTTP_ACCEPT_ENCODING"]=>
  string(17) "gzip, deflate, br"
  ["HTTP_DNT"]=>
  string(1) "1"
  ["HTTP_ACCEPT"]=>
  string(85) "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
  ["HTTP_USER_AGENT"]=>
  string(121) "<user-agent>"
  ["HTTP_UPGRADE_INSECURE_REQUESTS"]=>
  string(1) "1"
  ["HTTP_CACHE_CONTROL"]=>
  string(9) "max-age=0"
  ["HTTP_CONNECTION"]=>
  string(10) "keep-alive"
  ["HTTP_HOST"]=>
  string(23) "<project>.localhost"
  ["REDIRECT_STATUS"]=>
  string(3) "200"
  ["REDIRECT_HANDLER"]=>
  string(11) "php-fastcgi"
  ["REDIRECT_REQUEST_SCHEME"]=>
  string(4) "http"
  ["FCGI_ROLE"]=>
  string(9) "RESPONDER"
  ["PHP_SELF"]=>
  string(10) "/index.php"
  ["REQUEST_TIME_FLOAT"]=>
  float(1498944741.97)
  ["REQUEST_TIME"]=>
  int(1498944741)
  ["argv"]=>
  array(0) {
  }
  ["argc"]=>
  int(0)
}

Somehow I do have a REDIRECT_REQUEST_SCHEME environment variable. I'm pretty sure it has to do something with FastCGI.

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.