本文将记录我在Phalcon开发过程当中遇到的问题,以及如何如何解决。php
本文首发在个人博客,我更新以后会更新过来;若是想查看最新的,能够到个人博客:Phalcon填坑手册:开发中会遇到的问题和解决方案(不断更新)css
通常状况下,GET/POST请求获取参数:html
$this->request->get(参数名); $this->request->getPost("参数名")
路由模式下route获取参数要用dispatcher->getParam();
route下定义好了参数名称能够直接经过参数名称来获取:nginx
this->dispatcher->getParam("参数名");
route没有定义好名称,只是规则中写了:params作匹配,能够在控制器中按顺序来获取:redis
class NewsController extends Controller { public function showAction($id, $testParam) { echo $id, '|' , $testParam; } }
默认自动解析/:controller/:action/:params
模式:
在实例化时,不加false参数:数组
$router = new Router();
url将会自动进行/:controller/:action/:params
参数的解析, 好比https://www.goozp.com/login
将会解析成Login controller下的默认action。缓存
当使用路由时,保留默认解析模式有时候会致使解析混乱,比较建议采用彻底自定义路由模式。
彻底自定义路由,在new时加上false:cookie
$router = new Router(false);
不自动解析/:controller/:action/:params
这些规则, 具体的路由匹配规则本身来编写,例如:php7
$router->add('/login', [ 'module' => 'admin', 'controller' => 'login', 'action' => 'index', ] )->setName('login');
这样不会由于自动解析而致使url混乱,可是全部url都要本身来定制路由规则。app
重写后输出的html标签是字符串,外面带""
由于有Apache+.htaccess文件重写规则 或者 nginx配置到public/index.php的重写规则,咱们不须要项目中的url带有/publc/index.php。
可是默认是指到了/public/index.php中(好比$_SERVER["PHP_SELF"]获取从根目录到当前页面自己的路径); 因此,若是有Apache重写规则或者nginx配置到public/index.php的重写配置,咱们须要把url设置为不带public/index.php的,因而就有了官方的这个设置:
使用 $_SERVER["PHP_SELF"],而且正则去除/public/index.php
'baseUri' => preg_replace('/public([\/\\\\])index.php$/', '', $_SERVER["PHP_SELF"]),
这是动态写法,这种写法的问题在于 $_SERVER["PHP_SELF"] 的不肯定性,返回的值将根据 Apache 或 nginx 配置的 root,是否配置host或者域名,$_SERVER["PHP_SELF"]会有不一样的返回值。这样的话上面写法前面的正则并非所有兼容的,因此这样写调试起来就稍麻烦。
简单一点,用静态写法:
设置host或者配置域名
'baseUri' => '/',
若是是想在localhost下直接打开,则须要加上项目外层目录名,例如:
'baseUri' => '/zphal/',
这样的话,咱们在定义url服务的时候只须要把这个定义的配置传进去:
$di->setShared('url', function () { $config = $this->getConfig(); $url = new UrlResolver(); $url->setBaseUri($config->application->baseUri); // baseUri return $url; });
以上写法的WebServer配置:
.hatccess按照官方配置就能够;配置host时配置到public下或者public外面一层的项目根目录也能够:
<VirtualHost *:80> DocumentRoot "D:\phpStudy\WWW\zPhal\public" ServerName goozp.com ServerAlias <Directory "D:\phpStudy\WWW\zPhal\public"> Options FollowSymLinks ExecCGI AllowOverride All Order allow,deny Allow from all Require all granted </Directory> </VirtualHost>
大概的配置以下,配置到public下,并定义rewrite规则:
server { listen 80; server_name www.goozp.com goozp.com; root /data/www/zPhal/public; index index.php index.html index.htm; charset utf-8; client_max_body_size 100M; fastcgi_read_timeout 1800; location / { # Matches URLS `$_GET['_url']` try_files $uri $uri/ /index.php?_url=$uri&$args; } location ~ \.php$ { try_files $uri =404; #fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; fastcgi_pass php-fpm:9000; fastcgi_index /index.php; include fastcgi_params; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED /data/www/zPhal/public/$fastcgi_path_info; fastcgi_param SCRIPT_FILENAME /data/www/zPhal/public/$fastcgi_script_name; } location ~ /\.ht { deny all; } location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; access_log off; } }
被手册误导,理解错误了。
下面是 错误 的写法,在dispatcher中去定义了监听事件:
$di->set('dispatcher', function () { // 建立一个事件管理器 $eventsManager = new EventsManager(); $media = new Media(); $media->setEventsManager($eventsManager); // 监听分发器中使用插件产生的事件 $eventsManager->attach( "media", new AliYunOss() ); $dispatcher = new Dispatcher(); $dispatcher->setDefaultNamespace('ZPhal\Modules\Admin\Controllers\\'); $dispatcher->setEventsManager($eventsManager); // 分配事件管理器到分发器 return $dispatcher; });
然而我想封装的是文件上传功能,跟 dispatcher分发器 没有任何关系,因此起不了做用还报错;应该注册一个返回DI容器的文件上传服务:
$di->set('mediaUpload',function (){ // 建立一个事件管理器 $eventsManager = new EventsManager(); $media = new Media(); $eventsManager->attach( "media", new AliYunOss() ); $media->setEventsManager($eventsManager); return $media; });
扔进去的对象报错;须要给关联的对象定义alias,经过alias来获取。
若是是这样:
$terms = new Terms(); $terms->name = $name; $terms->slug = $slug; $termTaxonomy = new TermTaxonomy(); $termTaxonomy->Terms = $terms; // 这里 $termTaxonomy->taxonomy = $type; $termTaxonomy->save();
在$termTaxonomy->Terms = $terms;这里,Terms是TermTaxonomy Model中定义的关系的别名(alias);
定义方式以下,在model中:
$this->belongsTo( "term_id", "ZPhal\\Models\\Terms", "term_id", [ "alias" => "Terms", ] );
不起alias别名会报错。
经过$model -> getWriteConnection() -> lastInsertId();
来获取:
$model = new model(); if($model -> create($data)) { $insertId = $model -> getWriteConnection() -> lastInsertId($model -> getSource()); }
或者直接在执行以后拿id属性:
<?php $model = new model(); if($model -> create($data)) { $insertId = $model -> id; }
在 beforeCreate 事件中定义数据表字段的数据检查和数据赋值,不生效。
beforeCreate 在执行以前就会检查字段是否符合要求(validation),因此在beforecreate时再插入不行,会报错,须要在执行create前就传值,或者设置默认值。
能够在 beforeValidation 时进行赋值检查的操做。
表现为save或者update失败,且不报错的问题。
状况:主键设置为两个字段,更新时更新了其中一个字段。
解决:不该该修改主键。
参考:https://stackoverflow.com/questions/3838414/can-we-update-primary-key-values-of-a-table
Cached keys need to be enabled to use this function (options['statsKey'] == '_PHCR')!
Redis的默认配置有一个参数为‘_PHCR’前缀,因此queryKeys()时须要带上查询前缀。
能够加上return阻断:
$this->dispatcher->forward([ "controller" => "error", "action" => "route404" ]); return;
在分发后后面的代码将再也不执行。
使用cookie时,默认会使用Crypt加密,而使用Crypt加密须要定义一个全局加密key。
能够禁用cookie加密:
<?php use Phalcon\Http\Response\Cookies; $di->set( "cookies", function () { $cookies = new Cookies(); $cookies->useEncryption(false); return $cookies; } );
或者设置一个key:
<?php use Phalcon\Crypt; $di->set( "crypt", function () { $crypt = new Crypt(); $crypt->setKey('#1dj8$=dp?.ak//j1V$'); // 使用你本身的key! return $crypt; } );
正常删除时:
$this->cache->delete($key)
若是设置了前缀,会在$key自动加上前缀。
queryKeys列出来的已经带上了前缀,因此这样删除:
$keys = $this->cache->queryKeys(); foreach($keys as $key) { $this->cache->delete($key) }
传进去的key还会自动再加一遍前缀,就找不到缓存了,致使删除失败。
解决方法:
$this->cache->flush()
清除全部缓存,可是会清除全部缓存,因此若是是memcache或者redis缓存能够设置一下statsKey,避免清除了全部缓存。