我已經找遍了這樣的事情不使用`use`聲明,但我相信「用」字爲任何有用的結果也許是太普通了:檢測最簡單的方法/刪除PHP代碼庫
是什麼從PHP代碼庫中的類文件中刪除所有未使用的use
語句的最簡單方法?
編輯:爲了簡單起見,我們可以忽略檢測用於註釋的use
語句。
我已經找遍了這樣的事情不使用`use`聲明,但我相信「用」字爲任何有用的結果也許是太普通了:檢測最簡單的方法/刪除PHP代碼庫
是什麼從PHP代碼庫中的類文件中刪除所有未使用的use
語句的最簡單方法?
編輯:爲了簡單起見,我們可以忽略檢測用於註釋的use
語句。
查看Fabien Potencier的PHP-CS-Fixer https://github.com/fabpot/PHP-CS-Fixer
這個工具是faboo。謝謝! – yitznewton 2013-10-09 15:51:59
'./php-cs-fixer修復文件夾/ --fixers = unused_use'爲我工作 – mrwaim 2015-07-24 04:37:33
'./php-cs-fixer修復src/Backend/--rules = no_unused_imports'爲我做了詭計 – Kitze 2018-01-24 10:29:56
這可能取決於您的代碼設置的方式。如果你的代碼使用這樣的命名空間:
namespace Foo
{
<one or more classes in namespace Foo>
}
那麼你可能很好,如果你只是單獨檢查每個文件。這仍然意味着您將不得不解析PHP代碼以查找使用語句,然後確定使用哪些語句。
簡單的方法是使用已經構建的工具。我最近開始使用PhpStorm IDE(30天免費試用版,或early access program),並且可以通知您何時在文件中有未使用的use
語句(並且您甚至可以指定是否應該將其作爲警告或錯誤)。它仍然會要求你打開每個文件。但是你也可以檢查你正在編輯的文件,最後你的代碼會更清晰。
編輯
我已經完全改寫了,所以現在更強大:
的測試文件,類.PHP:
<?php
use My\Full\Classname as Another, My\Full\NSname, Some\Other\Space;
/* some insane commentary */ use My\Full\NSname1; use ArrayObject;
$obj = new namespaced\Another;
$obj = new Another;
$a = new ArrayObject(array(1));
Space::call();
$a = function($a, $b, $c = 'test') use ($obj) {
/* use */
};
class MyHelloWorld extends Base {
use traits, hello, world;
}
這裏的腳本:
<?php
class UseStatementSanitzier
{
protected $content;
public function __construct($file)
{
$this->content = token_get_all(file_get_contents($file));
// we don't need and want them while parsing
$this->removeTokens(T_COMMENT);
$this->removeTokens(T_WHITESPACE);
}
public function getUnused()
{
$uses = $this->getUseStatements();
$usages = $this->getUsages();
$unused = array();
foreach($uses as $use) {
if (!in_array($use, $usages)) {
$unused[] = $use;
}
}
return $unused;
}
public function getUsages()
{
$usages = array();
foreach($this->content as $key => $token) {
if (!is_string($token)) {
$t = $this->content;
// for static calls
if ($token[0] == T_DOUBLE_COLON) {
// only if it is NOT full or half qualified namespace
if ($t[$key-2][0] != T_NAMESPACE) {
$usages[] = $t[$key-1][1];
}
}
// for object instanciations
if ($token[0] == T_NEW) {
if ($t[$key+2][0] != T_NAMESPACE) {
$usages[] = $t[$key+1][1];
}
}
// for class extensions
if ($token[0] == T_EXTENDS || $token[0] == T_IMPLEMENTS) {
if ($t[$key+2][0] != T_NAMESPACE) {
$usages[] = $t[$key+1][1];
}
}
// for catch blocks
if ($token[0] == T_CATCH) {
if ($t[$key+3][0] != T_NAMESPACE) {
$usages[] = $t[$key+2][1];
}
}
}
}
return array_values(array_unique($usages));
}
public function getUseStatements()
{
$tokenUses = array();
$level = 0;
foreach($this->content as $key => $token) {
// for traits, only first level uses should be captured
if (is_string($token)) {
if ($token == '{') {
$level++;
}
if ($token == '}') {
$level--;
}
}
// capture all use statements besides trait-uses in class
if (!is_string($token) && $token[0] == T_USE && $level == 0) {
$tokenUses[] = $key;
}
}
$useStatements = array();
// get rid of uses in lambda functions
foreach($tokenUses as $key => $tokenKey) {
$i = $tokenKey;
$char = '';
$useStatements[$key] = '';
while($char != ';') {
++$i;
$char = is_string($this->content[$i]) ? $this->content[$i] : $this->content[$i][1];
if (!is_string($this->content[$i]) && $this->content[$i][0] == T_AS) {
$useStatements[$key] .= ' AS ';
} else {
$useStatements[$key] .= $char;
}
if ($char == '(') {
unset($useStatements[$key]);
break;
}
}
}
$allUses = array();
// get all use statements
foreach($useStatements as $fullStmt) {
$fullStmt = rtrim($fullStmt, ';');
$fullStmt = preg_replace('/^.+ AS /', '', $fullStmt);
$fullStmt = explode(',', $fullStmt);
foreach($fullStmt as $singleStmt) {
// $singleStmt only for full qualified use
$fqUses[] = $singleStmt;
$singleStmt = explode('\\', $singleStmt);
$allUses[] = array_pop($singleStmt);
}
}
return $allUses;
}
public function removeTokens($tokenId)
{
foreach($this->content as $key => $token) {
if (isset($token[0]) && $token[0] == $tokenId) {
unset($this->content[$key]);
}
}
// reindex
$this->content = array_values($this->content);
}
}
$unused = new UseStatementSanitzier('class.php');
print_r($unused->getUnused());
/*
Returns:
Array
(
[0] => NSname
[1] => NSname1
)
*/
不錯!我會給你一個鏡頭,讓你知道它是怎麼回事。 – leek 2012-03-27 20:12:11
類(用於PHP 5.4中的特性)和前面的閉包塊中的'use'指令是否具有與名稱空間'use'不同的標記類型?否則,您可能需要確保此代碼忽略這些代碼。 – FtDRbwLXw6 2012-03-27 22:57:14
好的,我知道,我已經忘記了一些情況,我很快就會對代碼做些修改。 – 2012-03-28 06:25:43
此工具如何知道何時不使用名稱空間? – 2012-03-27 18:38:14
那麼你需要收集每個use-statement,用tokenizer解析你的文件,看看它是否是實例化的或靜態調用的。但這需要一點工作。 – 2012-03-27 18:43:34
我已經編輯了我的答案中的代碼,你現在應該再試一次:)。我測試了一些案例,它工作。我希望現在讓你滿意。它只適用於一個文件,但;對於較大的項目,您應該調整它,並建立一個更大的索引。 – 2012-03-28 09:44:08