panada/app

一个同时追求简洁和性能的PHP框架

安装: 146

依赖项: 0

建议者: 0

安全: 0

星星: 20

关注者: 8

分支: 13

开放问题: 2

语言:CSS

类型:项目

dev-master 2016-07-13 10:36 UTC

This package is not auto-updated.

Last update: 2024-09-14 17:32:01 UTC


README

由于几个工作相关的承诺,开发进度有点慢,对此我深表歉意。然而,我在寻找一些很棒的伙伴 🤘,他们可以贡献并帮助我维护这个项目。如果您有任何关于如何贡献的问题,或者您对如何使用应用中的组件有一般性问题 - 欢迎随时发邮件。我会帮您的! 😸

关于Panada

Panada是一个基于PHP 5.5的高性能开发框架,同时简单易用。不仅在使用上下文中,还包括核心系统如何运行。

目前,Panada 2.0正处于非常重的开发阶段,因此其功能将会有很多变化。

要求

Panada仅支持PHP 5.5及以上版本。

安装

composer create-project panada/app --prefer-dist --stability=dev myweb;
php -S localhost:8181 -t myweb/public;

然后在浏览器中打开 https://:8181

快速入门指南

控制器

从版本1开始,Panada使用 HMVC 设计模式。作为HMVC架构的一部分,控制器负责处理请求和生成响应,包括主应用程序控制器和模块控制器。现在让我们在主应用程序中创建一个。

在 src/Controller 文件夹中创建一个名为 Hello.php 的新文件。然后编写一些类

<?php

namespace Controller;

class Hello
{
    public function index()
    {
        return 'Hello world!';
    }
    
    public function me($firstName = null, $lastName = null)
    {
        return 'My name is:'.$name.' '.$lastName;
    }
}

访问控制器

访问控制器的URL格式如下

ControllerName/ActionName

现在在浏览器中打开 https://:8181/hellohttps://:8181/me/john/doe

在2.0版本中,我们改变了控制器获取控制器辅助方法的方式。要使用此辅助程序,您可以使用 Controller 特性。

<?php

namespace Controller;

class Hello
{
    use \Panada\Resource\Controller;
    
    public function index()
    {
        return 'Hello world!';
    }
}

或者如果您在控制器中使用构造函数,您可以使用

<?php
namespace Controller;

use Panada;
use Panada\Resource\Controller;

class Cookies
{
    use Controller
    {
        Controller::__construct as private _construct;
    }
    
    public function __construct()
    {
        $this->_construct();
        
        $this->session = Panada\Session\Session::getInstance();
    }
    
    public function index()
    {
        $this->response->setHeaders('Content-Type', 'text/html');
     
        if( $this->session->getValue('isLogin') )
            return $this->response->redirect('cookies/protectedPage');
        
        return '<a href="'.$this->uri->location('cookies/set').'">Set session</a>';
    }
    
    public function api()
    {
        $this->response->setHeaders('Content-Type', 'application/json');
        
        return json_encode(['foo' => 'bar']);
    }
}

视图

您可以在 views 文件夹中管理分离的HTML模板文件。现在让我们在 src/view 文件夹中创建一个视图文件,命名为 helloWorld.php

<html>
    <head>
        <title>Hellow world!</title>
    </head>
    <body>
        Hello world!
    </body>
</html>

要在控制器的方法中显示您的视图文件,请使用控制器中的 $this->output() 方法

<?php

namespace Controller;

class Hello
{
    use \Panada\Resource\Controller;
    
    public function index()
    {
        return $this->output('helloWorld');
    }
}

要从控制器传递一个值到视图,只需在 $this->output() 方法的第二个参数中添加一个数组

<?php

namespace Controller;

class Hello
{
    use \Panada\Resource\Controller;
    
    public function index()
    {
        return $this->output('helloWorld', ['name' => 'Panada']);
    }
}

然后在您的视图文件中使用 $name 变量。

<html>
    <head>
        <title><?=$name?></title>
    </head>
    <body>
        <?=$name?>
    </body>
</html>

模型

模型是MVC架构的一部分。它们是代表业务数据、规则和逻辑的对象。模型是一个与数据处理直接相关的类,无论是从数据库还是其他存储系统。

创建模型

要创建模型类,请添加新文件并将其放在文件夹 src/Model/ 中,例如 Users.php

在文件中创建一个具有给定命名空间 "Model" 的 users 类,例如

<?php
namespace Model;

class Users
{    
    public function __construct()
    {
        
    }
}

在模型中加载库

如果您计划在此模型中加载库或另一个类,有两种方法可以做到。首先,如果该类或库的资源将被模型类中的所有方法使用,则检索和初始化可以在构造函数中完成。然而,如果资源只想在特定方法中使用,则初始化和检索可以在相关方法中完成。

在类模型中,最常见的事情之一是加载数据库资源。以下是一个在模型类中加载数据库资源的简单示例

<?php
namespace Model;
use Panada\Database;

class Users
{
    public function __construct()
    {
        $this->db = Database\SQL::getInstance();
    }
}

此外,属性 "$this->db" 可以用于该类中存在的所有方法。以下是一个从数据库获取5条记录的示例

<?php
namespace Model;
use Panada\Database;

class Users
{
    public function __construct()
    {
        $this->db = Database\SQL::getInstance();
    }
    
    public function users()
    {
        return $this->db->results("SELECT * FROM table_name ORDER BY id LIMIT 5");
    }
}

模块

模块是由模型、视图、控制器和其他支持组件组成的子应用程序。与应用程序不同的是,模块不能独立部署,必须位于应用程序中。Panada中的每个模块都位于 Module 文件夹中。

模块中的每个类都应该在其命名空间中添加模块名称。例如

<?php

namespace Module\Foo\Controller;

class Bar
{
    use \Panada\Resource\Controller;
    
    public function index()
    {
        return __METHOD__;
    }
    
    public function blog()
    {
        return __METHOD__;
    }
}

访问模块

访问模块中的控制器的URL格式如下

ModuleName/ControllerName/ActionName

因此,如果我们有一个名为Foo的模块,该模块有一个名为Bar的控制器的名为blog的方法,则URL为

http://www.mysite.com/foo/bar/blog

或者,如果您没有定义控制器名称和操作名称,它将转到控制器Home的index方法。

路由

路由是一种让您定义某些URL并将其映射到应用程序不同区域的方法。与主控制器或模块不同,路由为您提供了定义URL格式的灵活性。

路由器

在路由器配置文件中必须定义3个实体。

1. 模式

模式定义了URL动态部分的格式。实际上,模式对于定义动态路由是必不可少的。例如,post_id和published_date在URL中将由三个不同的模式检测。

2. 默认值

当我们不想在定义路由或创建链接时每次都提及URL的某个部分时,将使用默认值。

3. 路由

从URL到控制器的映射。

Panada的路由配置位于src/config/routes.php,以下是一些示例

<?php

return [
    'pattern' => [
        'year' => '/^[0-9]{4}$/i',
        'month' => '/^[0-9]{2}$/i',
        'id' => '/^[1-9][0-9]+$/i',
        'name' => '/^[a-z][a-z0-9_]+$/i'
    ],
    'defaults' => [
        'method' => 'GET|POST',
        'protocol' => 'http',
        'subdomain' => '',
        'domain' => 'localhost',
        'port' => 8081,
    ],
    'route' => [
        'archive' => [
            'url'=>'/news/:year/:month',
            'controller'=>'news',
            'action'=>'archive'
        ],
        'article' => [
            'url'=>'/post',
            'controller'=>'posts',
            'action'=>'view'
        ],
        'test1' => [
            'url'=>'/test1',
            'controller'=>'Controller\Home',
            'action'=>'test1'
        ],
        'blog' => [
            'url'=>'/blog/:name',
            'controller'=>'Controller\Hidden\HiddenPage',
            'action'=>'index'
        ]
    ]
];

请求处理器优先级规则

有时我们有一个与模块名称同名或与路由规则匹配的控制器。在这种情况下,默认情况下,Panada将首先检查主控制器,然后是模块,然后是路由。如果您希望更改其他规则优先级,可以更改 app/src/config/main.php 文件。

'requestHandlerRule' => [
    'controllerHandler',
    'moduleHandler',
    'routingHandler'
]

数据库

2.0版本采用NotORM,一个用于简单处理数据库数据的库。

您的数据库配置位于 src/config/database.php

<?php

return [
    'default' => [
        'dsn' => 'mysql:host=127.0.0.1;dbname=panada;port=3306',
		'username' => 'root',
		'password' => '',
		'options' => [
			PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
            PDO::ATTR_PERSISTENT => true
		]
    ]
];

以下是使用NotORM的示例

<?php

namespace Controller;

class Testnotorm
{
    public function __construct()
    {
        $this->db = \Panada\Notorm\NotORM::getInstance();
        
        // pass config name in getInstance method if you have another config
        // $this->db = \Panada\Notorm\NotORM::getInstance('mysql');
    }
    
    public function index()
    {
        $r = null;
        foreach ($this->db->users() as $user) {
            $r .= $user['email'].'<br>';
        }
        
        return $r;
    }
    
    public function singleRow()
    {
        $r = print_r($this->db->users[1]['id'], true);
        $r .= '<br>';
        $r .= print_r($this->db->users('id = ?', 1)->fetch()['id'], true);
    }
    
    public function insert()
    {
        $name = time();
        
        $row = $this->db->users()->insert([
            "name" => $name,
            "email" => $name."@bar.com",
        ]);
        
        return print_r($row['id'], true);
    }
    
    public function update()
    {
        $name = time();
        
        $affected = $this->db->users('id = ?', 1)->fetch()->update(['name' => 'update']);
        
        return print_r($affected, true);
    }
    
    public function delete()
    {
        return var_export($this->db->users[1]->delete(), true);
    }
}

要查看更多如何使用NotORM API的示例,请查看此仓库 https://github.com/panada/notorm

会话

以下是如何使用会话的示例

<?php
namespace Controller;

use Panada;
use Panada\Resource\Controller;

class Admin
{
    use Controller
    {
        Controller::__construct as private _construct;
    }
    
    public function __construct()
    {
        $this->_construct();
        
        $this->session = Panada\Session\Session::getInstance();
        
        // pass config name in getInstance method if you have another session config
        // $this->session = Panada\Session\Session::getInstance('config2');
    }
    
    public function index()
    {
        if( $this->session->getValue('isLogin') )
            return $this->response->redirect('admin/protectedPage');
        
        return '<a href="'.$this->uri->location('admin/set').'">Set session</a>';
    }
    
    public function protectedPage(){
        
        $echo = $this->session->getValue('name').'<br />';
        $echo .= '<a href="'.$this->uri->location('admin/remove').'">Remove session</a>';
        
        return $echo;
    }
    
    public function remove(){
        
        $this->session->destroy();
        
        return $this->response->redirect('admin');
    }
}

缓存

以下是如何使用缓存的示例

<?php
namespace Controller;

use Panada;
use Panada\Resource\Controller;

class Blog
{
    use Controller
    {
        Controller::__construct as private _construct;
    }
    
    public function __construct()
    {
        $this->_construct();
        
        $this->cache = Panada\Cache\Cache::getInstance();
        
        // pass config name in getInstance method if you have another cache config
        // $this->cache = Panada\Cache\Cache::getInstance();'config2');
    }
    
    public function index()
    {
        $key = 'foo';
        $val = 'bar';
        $val2 = 'bar2';
        
        $info;
        
        // insert new value by a key
        $status = $this->cache->setValue($key, $val);
        
        $info .= 'Insert status:<br>'.var_export($status, true);
        
        // get a value
        $status = $this->cache->getValue($key);
        
        $info .= 'Get status:<br>'.var_export($status, true);
        
        // update a value
        $status = $this->cache->updateValue($key, $val2);
        
        $info .= 'Update status:<br>'.var_export($status, true);
        
        // get updated value
        $status = $this->cache->getValue($key);
        
        $info .= 'Get updated value status:<br>'.var_export($status, true);
        
        // delete a value by it key
        $status = $this->cache->deleteValue($key);
        
        $info .= 'Delete status:<br>'.var_export($status, true);
        
        // get deleted value
        $status = $this->cache->getValue($key);
        
        $info .= 'Deleted value status:<br>'.var_export($status, true);
        
        return $info;
    }
}

要了解更多关于缓存包的使用,请访问 https://github.com/panada/cache

附加库

Panada 2.0完全支持Composer。安装附加的Panada包或外部库通过Composer处理。

Web服务器

Nginx

Nginx 是一个免费、开源、高性能且极其快速的HTTP服务器。要使其与您的Panada项目一起工作,您可以使用以下示例服务器配置

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    # this is the root of your project
    root /var/www/public;
    index index.php;

    location / {
            try_files $uri /index.php$request_uri;
    }

    location ~ \.php(/|$) {
        index index.php;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
        deny all;
    }
}

Apache

在您的公共文件夹中创建一个 .htaccess 文件,然后填写以下内容

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]

从版本1.1升级

由于Panada为2.0完全重写,因此1.1和2.0之间存在很多差异。因此,从1.1版本升级不如从次版本升级那么简单。

前端控制器(index.php)

index.php文件的所有内容都完全更改了。在2.0版本中,我们不再使用任何全局常量。因此,如果您使用了以下常量之一:APP、INDEX_FILE或GEAR,请更新它们。

文件夹名称

所有文件夹名称都已更改

  • app 更改为 src
  • 将/app/Controllers重命名为/src/Controller
  • 将/app/views重命名为/src/view
  • 将/app/Modules重命名为/src/Module

Panada文件夹现在已移动到vendor/panada。

视图

在版本1.1中,要显示输出,开发者只需像这样简单地echo变量

public function index($id = 0)
{
    echo 'This is the news with ID' . $id;
}

或者,使用$this->output()方法从视图文件显示

public function index()
{        
    $this->output('helloworldViewFile');
}

但在版本2.0中,您只需返回对象即可,就像这样

public function index($id = 0)
{
    return 'This is the news with ID' . $id;
}
public function page()
{        
    return $this->output('helloworldViewFile');
}

控制器

控制器的命名空间现在变为

<?php
namespace Controller;

控制器的父类从

class Home extends \Libraries\Controller
{
    public function __construct()
    {
        parent::__construct();
    }
    
    public function index()
    {
        
    }
}

更改为

class Home
{
    use Controller {
        Controller::__construct as private _construct;
    }
    
    public function __construct()
    {
        $this->_construct();
    }
    
    public function index()
    {
        
    }
}

我们支持trait的特性。

别名

控制器功能已被移除,仅支持方法别名。为了适应您的别名功能,您可以使用路由。

如果您需要使用其他名称作为别名方法,您可以在app/src/config/main.php中更改它。

数据库

从版本2.0开始,Panada使用PDO作为默认数据库驱动程序。我们还移除了Active Recored功能,并替换为NotORM。因此,在版本2.0中,您无法再使用当前的查询。您必须更新所有数据库查询。

然而,我们仍然保留了查询构建器。但您需要更新位于app/src/config/database.php的文件数据库配置。

版本1的Panada数据库配置看起来像

<?php

return array(

    'default' => array(
        'driver' => 'mysqli',
        'host' => 'localhost',
        'port' => 3306,
        'user' => 'root',
        'password' => '',
        'database' => 'panada',
        'tablePrefix' => '',
        'charset' => 'utf8',
        'collate' => 'utf8_general_ci',
        'persistent' => false,
    );
);

在版本2中应该是

return [
    'default' => [
        'dsn' => 'mysql:host=127.0.0.1;dbname=mydb1;port=3306',
		'username' => 'root',
		'password' => '',
		'options' => [
			PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
            PDO::ATTR_PERSISTENT => true
		]
    ],
];

更多关于查询构建器请参阅https://github.com/panada/database

完整文档

我们还没有为Panada版本2.X提供完整的文档。如果您认为您可以帮助我们编写一些,那将非常不错。只需在https://github.com/panada/documentation/tree/with-pure.0.5.0的文档分支上进行fork即可。

贡献

Panada 2.0由多个子包组成。为了报告任何错误或进行一些贡献,请前往每个包的repo。