Я хочу предложить решение, в котором могут быть достигнуты оба варианта конфигурации «многие-ко-многим».
«catch» - нам нужно создать представление, которое нацелено на таблицу объединения, поскольку EF проверяет, что таблица схемы может отображаться не более одного раза за EntitySet
.
ответ добавляет к тому, что уже было сказано в предыдущих ответах, и не отменяет ни один из этих подходов, он основывается на них.
Модель:
public class Member
{
public int MemberID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection Comments { get; set; }
public virtual ICollection MemberComments { get; set; }
}
public class Comment
{
public int CommentID { get; set; }
public string Message { get; set; }
public virtual ICollection Members { get; set; }
public virtual ICollection MemberComments { get; set; }
}
public class MemberCommentView
{
public int MemberID { get; set; }
public int CommentID { get; set; }
public int Something { get; set; }
public string SomethingElse { get; set; }
public virtual Member Member { get; set; }
public virtual Comment Comment { get; set; }
}
Конфигурация:
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
public class MemberConfiguration : EntityTypeConfiguration
{
public MemberConfiguration()
{
HasKey(x => x.MemberID);
Property(x => x.MemberID).HasColumnType("int").IsRequired();
Property(x => x.FirstName).HasColumnType("varchar(512)");
Property(x => x.LastName).HasColumnType("varchar(512)")
// configure many-to-many through internal EF EntitySet
HasMany(s => s.Comments)
.WithMany(c => c.Members)
.Map(cs =>
{
cs.ToTable("MemberComment");
cs.MapLeftKey("MemberID");
cs.MapRightKey("CommentID");
});
}
}
public class CommentConfiguration : EntityTypeConfiguration
{
public CommentConfiguration()
{
HasKey(x => x.CommentID);
Property(x => x.CommentID).HasColumnType("int").IsRequired();
Property(x => x.Message).HasColumnType("varchar(max)");
}
}
public class MemberCommentViewConfiguration : EntityTypeConfiguration
{
public MemberCommentViewConfiguration()
{
ToTable("MemberCommentView");
HasKey(x => new { x.MemberID, x.CommentID });
Property(x => x.MemberID).HasColumnType("int").IsRequired();
Property(x => x.CommentID).HasColumnType("int").IsRequired();
Property(x => x.Something).HasColumnType("int");
Property(x => x.SomethingElse).HasColumnType("varchar(max)");
// configure one-to-many targeting the Join Table view
// making all of its properties available
HasRequired(a => a.Member).WithMany(b => b.MemberComments);
HasRequired(a => a.Comment).WithMany(b => b.MemberComments);
}
}
Контекст:
using System.Data.Entity;
public class MyContext : DbContext
{
public DbSet Members { get; set; }
public DbSet Comments { get; set; }
public DbSet MemberComments { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new MemberConfiguration());
modelBuilder.Configurations.Add(new CommentConfiguration());
modelBuilder.Configurations.Add(new MemberCommentViewConfiguration());
OnModelCreatingPartial(modelBuilder);
}
}
Из альбома Saluma (@ Saluma) answer
Если вы сейчас хотите найти все комментарии членов с LastName = «Смит», например, вы можете написать такой запрос:
blockquote>Это все еще работает ...
var commentsOfMembers = context.Members .Where(m => m.LastName == "Smith") .SelectMany(m => m.MemberComments.Select(mc => mc.Comment)) .ToList();
... но теперь также может быть ...
var commentsOfMembers = context.Members .Where(m => m.LastName == "Smith") .SelectMany(m => m.Comments) .ToList();
Или создать список членов с именем «Смит» (мы предполагаем, что их более одного) вместе с их комментариями можно использовать проекцию:
blockquote>Это все еще работает ...
var membersWithComments = context.Members .Where(m => m.LastName == "Smith") .Select(m => new { Member = m, Comments = m.MemberComments.Select(mc => mc.Comment) }) .ToList();
... но теперь также может быть ...
var membersWithComments = context.Members .Where(m => m.LastName == "Smith") .Select(m => new { Member = m, m.Comments }) .ToList();
Если вы хотите удалить комментарий от пользователя
var comment = ... // assume comment from member John Smith var member = ... // assume member John Smith member.Comments.Remove(comment);
Если вы хотите
Include()
комментарии участникаvar member = context.Members .Where(m => m.FirstName == "John", m.LastName == "Smith") .Include(m => m.Comments);
Все это похоже на синтаксический сахар, однако он дает вам несколько преимуществ, если вы захотите пройти дополнительную настройку. В любом случае, вы, похоже, сможете получить лучшее из обоих подходов.
Не беспокойтесь о open / readdir и вместо этого используйте glob
:
foreach(glob($log_directory.'/*.*') as $file) {
...
}
Поскольку принятый ответ имеет два важных недостатка, я отправляю улучшенный ответ тем новым посетителям, которые ищут правильный ответ:
foreach (array_filter(glob('/Path/To/*'), 'is_file') as $file)
{
// Do something with $file
}
globe
результаты с is_file
необходимы, потому что он может также возвращать некоторые каталоги. .
в своих именах, поэтому */*
шаблон в целом сосет. Другой способ перечислить каталоги и файлы будет использовать RecursiveTreeIterator
, на который вы ответили: https://stackoverflow.com/a/37548504/2032235 .
объяснение RecursiveIteratorIterator
и итераторов в PHP можно найти здесь: https://stackoverflow.com/a/12236744/2032235
glob()
и FilesystemIterator
примеры:
/*
* glob() examples
*/
// get the array of full paths
$result = glob( 'path/*' );
// get the array of file names
$result = array_map( function( $item ) {
return basename( $item );
}, glob( 'path/*' ) );
/*
* FilesystemIterator examples
*/
// get the array of file names by using FilesystemIterator and array_map()
$result = array_map( function( $item ) {
// $item: SplFileInfo object
return $item->getFilename();
}, iterator_to_array( new FilesystemIterator( 'path' ), false ) );
// get the array of file names by using FilesystemIterator and iterator_apply() filter
$it = new FilesystemIterator( 'path' );
iterator_apply(
$it,
function( $item, &$result ) {
// $item: FilesystemIterator object that points to current element
$result[] = (string) $item;
// The function must return TRUE in order to continue iterating
return true;
},
array( $it, &$result )
);
Вы можете просто попробовать функцию scandir(Path)
.
$files = scandir("somePath");
Эта функция возвращает список файлов в массив.
, чтобы просмотреть результат, вы может попробовать
var_dump($files);
Или
foreach($files as $file)
{
echo $file."< br>";
}
Просто используйте glob('*')
. Вот Документация
Тип SPL :
foreach (new DirectoryIterator(__DIR__) as $file) {
if ($file->isFile()) {
print $file->getFilename() . "\n";
}
}
Проверьте классы DirectoryIterator и SplFileInfo для списка доступных методов, которые вы можно использовать.
getPathname
: php.net/manual/en/splfileinfo.getpathname.php
– Ilija
8 November 2015 в 09:42
Это связано с приоритетом оператора. Попробуйте изменить его на:
while(($file = readdir($handle)) !== FALSE)
{
$results_array[] = $file;
}
closedir($handle);
Вот более продвинутый пример для , показывающий все файлы в папке
Вам нужно окружить $file = readdir($handle)
круглыми скобками.
Здесь вы:
$log_directory = 'your_dir_name_here';
$results_array = array();
if (is_dir($log_directory))
{
if ($handle = opendir($log_directory))
{
//Notice the parentheses I added:
while(($file = readdir($handle)) !== FALSE)
{
$results_array[] = $file;
}
closedir($handle);
}
}
//Output findings
foreach($results_array as $value)
{
echo $value . '<br />';
}
Рекурсивный код для изучения всего файла, содержащегося в каталоге («$ path» содержит путь к каталогу):
function explore_directory($path)
{
$scans = scandir($path);
foreach($scans as $scan)
{
$new_path = $path.$scan;
if(is_dir($new_path))
{
$new_path = $new_path."/";
explore_directory($new_path);
}
else // A file
{
/*
Body of code
*/
}
}
}
На некоторых ОС вы получаете .
..
и .DS_Store
, ну мы не можем их использовать, поэтому давайте спрячем их.
Сначала начните получать всю информацию о файлах, используя scandir()
// Folder where you want to get all files names from
$dir = "uploads/";
/* Hide this */
$hideName = array('.','..','.DS_Store');
// Sort in ascending order - this is default
$files = scandir($dir);
/* While this to there no more files are */
foreach($files as $filename) {
if(!in_array($filename, $hideName)){
/* echo the name of the files */
echo "$filename"{<br>$filename}";<br>";
}
}
У меня есть меньше кода для этого:
$path = "Pending2Post/";
$files = scandir($path);
foreach ($files as &$value) {
echo "<a href='http://localhost/".$value."' target='_black' >".$value."</a><br/>";
}
.php
для каждого файла.)
– KSPR
24 July 2018 в 10:03
array_filter(..., 'is_file')
вокруг этого глоба, поскольку вопрос запрашивает файлы. – salathe 27 May 2010 в 19:09*.*
: вместо этого используйте*
. – jameshfisher 24 February 2014 в 19:17something.something
. Лучше использоватьarray_filter
иglob($log_directory.'/*')
. – Andrew 29 May 2014 в 17:33*.*
. Более надежное выражение сделало бы это еще лучшим ответом. – TecBrat 24 May 2017 в 17:08