devvoh / parable Goto Github PK
View Code? Open in Web Editor NEWParable is a PHP micro-framework, intended to just let you do your thing.
License: MIT License
Parable is a PHP micro-framework, intended to just let you do your thing.
License: MIT License
It will handle --option value
just fine, but the equals-sign makes it not recognise the option.
Maek fix do work proper.
When calling this in a view template:
<?= $this->url->getUrl('/') ?>
the result is http://project.dev/index.php/
.
I expected just http://project.dev/
.
I'm on version 0.12.7.
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.
The Request
class could use a getBody()
method to provide easy access to php://input
.
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.
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.
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
.
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.
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();
// ...
}
}
parable
executable one level up (please? ๐ ).\Commands
namespace.app/Commands
with InitializeParableCommand
.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 = [])
A fresh installation of Parable on a Windows system should show the default view (View/Home/index.phtml
).
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->__construct('ParableC:\\MAMP\\...')
#1 C:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Framework\Toolkit.php(90): Parable\Framework\Toolkit->loadResourceMap()
#2 C:\MAMP\htdocs\cgi_whereabouts_dashboard\vendor\devvoh\parable\src\Framework\View.php(123): Parable\Framework\Toolkit->getResourceMapping('Config')
#3 C:\MAMP\htdocs\cgi_whereabouts_dashboard\app\View\Home\index.phtml(7): Parable\Framework\View->__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 />
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?
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.
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.
Since it uses \Parable\Framework\Toolkit
, it must be a Framework
module as well.
You could use Style CI. It's free for open source! ๐
Or use PHP Coding Standards Fixer, manually... (no SaaS, very sad!)
My production environment uses HTTP/2, so I suggest something like this to make it future-proof:
header("{$_SERVER['SERVER_PROTOCOL']} {$this->getHttpCode()} {$this->getHttpCodeText()}");
http://php.net/manual/en/function.header.php#92305
And please do throw away that array of HTTP status codes. It's not needed, because you can use http_response_code()
. http://php.net/manual/en/function.http-response-code.php#116880
This involves all Hook calls in \Framework
And should also be called redirectToRouteByName.
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,
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?
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
.
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*).
...so I can add it to the About page of my site.
๐
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.
As title says ๐
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")! ๐
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! ๐
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? ๐
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.
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.
In \Parable\Http\Values\GetSet
on line 115-119:
if ($this->useLocalResource) {
$this->localResource[] = $values;
} else {
$GLOBALS[$this->getResource()] = $values;
}
$this->localResource[] = $values;
should be changed to $this->localResource = $values;
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.