Como localizar um arquivo
Visão Geral
Alguns scripts em suas aplicações podem precisar acessar arquivos sem necessariamente saber onde eles estão. Se você estiver usando o bash, você pode usar o comando find para encontrá-los. No symfony, você pode fazer isso facilmente com a classe sfFinder. Fazer uma busca complexa é apenas uma questão de adicionar novos critérios de busca, e o resultado é uma simples array com o caminho dos arquivos.
A classe sfFinder
A classe sfFinder é uma classe de busca de arquivos baseado no módulo Perl [File::Find::Rule](http://search.cpan.org/~rclamp/File-Find-Rule/). Ela pode buscar arquivos ou diretórios (ou ambos), e filtrar a busca por um conjunto de regras definidas pelo usuário. Segue abaixo o uso básico:
Crie um objeto
sfFinderpara sua procura chamando o método de classetype(). Você deve informar que tipo de resultado você espera (file,dirouany)[php] $finder = sfFinder::type('file');Adicione regras para refinar sua busca e reduzir e número de resultados
[php] $finder = $finder->name('*.php');Execute a busca chamando o método
in(), passando o diretório raiz da busca como arqumento[php] $files = $finder->in('/home/production/myproject');
Todas as chamadas ao métodos podem ser encadeadas em uma única linha, o que geralmente é mais fácil de se ler:
[php]
$files = sfFinder::type('file')->name('*.php')->in('/home/production/myproject');
// can be read as
// find files with name matching '*.php' in the '/home/production/myproject' directory
O método in() retorna uma array de arquivos, que pode ser facilmente usada para manipulação dos arquivos:
[php]
foreach ($files as $file)
{
$handle = fopen($file, "r");
...
}
Nota: A classe
sfFinderé automaticamente carregada e não precisa ser adicionada como requerida em seus scripts.
Princípio das regras
As regras usadas para refinar a busca são escritas como chamadas de métodos de um objeto sfFinder. Todos os métodos retornam o atual objeto sfFinder para permitir um fácil encadeamento.
[php]
$finder1 = sfFinder::type('file')->name('*.php'); // é um objeto sfFinder
$finder2 = sfFinder::type('file')->name('*.php')->size('> 10K'); // também é um objeto sfFinder
$files = $finder1->in('/home/production/myproject'); // é uma array contendo caminhos de arquivos
Todas as regras são invocadas várias vezes, exceto para o método in().
Algumas regras são cumulativas (name() por exemplo) enquanto outras destrutivas (como a maxdepth()). Para regras destrutivas, apenas o método chamado mais recentemente conta:
[php]
// este comando irá filtrar arquivos com nomes que satisfaçam ambas condições
$finder = sfFinder::type('file')->name('*.php')->name('*Success.*');
// faz o mesmo que
$finder = sfFinder::type('file')->name('*Success.php');
// aqui, apenas a última chamada é levada em conta
$finder = sfFinder::type('file')->maxdepth(5)->maxdepth(3);
// faz o mesmo que
$finder = sfFinder::type('file')->maxdepth(3);
Filter rules
Filter by name
To filter the results on file names, add calls to the name() method with patterns in glob or regular expression format:
[php]
$finder = sfFinder::type('file')->name('*.php');
$finder = sfFinder::type('file')->name('/.*\.php/');
You can even exclude certain file names from the result, doing negative filtering with the not_name() method:
[php]
$finder = sfFinder::type('file')->not_name('Base*');
$finder = sfFinder::type('file')->name('/^Base.*$/');
Filter by size
You can filter your search on file size by calling the size() method, which expects a string containing a comparison as argument. The method also understands magnitudes:
[php]
// search only for files bigger than 10 kilobytes
$finder = sfFinder::type('file')->size('> 10K');
// search only for files smaller than 1 kilobyte, or exactly that
$finder = sfFinder::type('file')->size('<= 1Ki');
// search only for files being 123 bytes of size
$finder = sfFinder::type('file')->size(123);
The symbols used for magnitude are the binary prefix defined by the International System of Units.
Limiting the search depth
By default, a search made by the sfFinder object is recursive and scans all the subdirectories. You can override this default behaviour by using the maxdepth() method to set the maximum depth of search in the file tree structure:
[php]
// search in directory and subdirectories
$finder = sfFinder::type('file');
// search only in the directory passed to the in() method,
// and not in any subdirectory
$finder = sfFinder::type('file')->maxdepth(1);
Of course, you can also specify a minimum depth by calling the mindepth() method.
By default, the minimum depth is 0 and the maximum depth is infinite (or close to).
Excluding directories
If you want to exclude directories from the search, you can use two methods:
the
prune()method stops the search in the part of the tree structure where the pattern given as argument is found. See it as an interdiction to go and see what's in a directory:[php] // ignore the content of '.svn' folders $finder = sfFinder::type('any')->prune('.svn');The finder doesn't go deeper in any of the
.svnfolders, but the.svnfolders themselves are still part of the results.the
discard()method removes the files or folders that match the argument from the result, but doesn't stop the tree structure exploration.[php] // remove the '.svn' folders from the result $finder = sfFinder::type('any')->discard('.svn');
These two methods are often used in conjunction, when a directory and its content need to be excluded from a search:
[php]
// remove the '.svn' folders and their content from the result
$finder = sfFinder::type('any')->prune('.svn')->discard('.svn');
Tip: To exclude the files and directories added by version control programs,
sfFinderprovides a shortcut method:ignore_version_control(). It will prune and discard and prune all files and directories looking like.svn,CVS,_darcs,.arch-params,.monotone, and.bzr.
Ponto inicial da busca
O método in() é usado para especificar onde o sfFinder deve procurar por arquivos ou diretórios. Ele pode receber um caminho ou um array de caminhos como argumento:
[php]
// procurar em um único local
$files = $finder->in('/home/production/myproject');
// procurar em diversos locais
$files = $finder->in(array('/home/production/myproject', '/home/production/myotherproject'));
Também pode aceitar tanto um caminho absoluto quanto um caminho relativo:
[php]
// caminho absoluto
$files = $finder->in('/home/production/myproject');
// caminho relativo
$files = $finder->in('../projects/myproject');
Retornando caminhos relativos
Por padrão, os caminhos retornados pelo método in() são caminhos absolutos. Você pode optar por receber uma array com caminhos relativos ao invés, encadeando a chamanda ao método relative() antes de chamar o método in():
[php]
// os caminhos resultantes são relativos ao diretório raiz
$files = $finder->in('/home/production/myproject');
// os caminhos resultantes são relativos ao diretório atual,
// ex. o diretório atual do script
$files = $finder->relative()->in('/home/production/myproject');