次に最近投稿した一覧を表示させます。
今回は、コントローラーの PostsController::RecentPosts メソッドから作っていきますね。
■コントローラーを LINQ で作る。
public ActionResult Recent()
{
int max = 5;
wordpressEntities ent = new wordpressEntities();
var model = (from p in ent.wp_posts
join u in ent.wp_users on p.post_author equals u.ID
where p.post_status == "publish"
orderby p.post_date descending
select new
{ Post = p, User = u }
).Take(max);
return View(model);
}
投稿した人の名前(User.display_name)を表示させたいので、wp_users テーブルとリンクさせます。そていて、最初の5行だけ表示させたいので Take 関数を使っています。
このための専用のモデルを作るのは面倒なので、無名クラスを作って new { Post = p, User = u } として作成しています。
こうすると、ビュー側で
- item.Post.post_author
- item.User.display_name
のように参照ができるハズですね(実は、うまくいきません…)。
■ビューを作る
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Recent
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>最近投稿した記事</h2>
<table>
<tr>
<th>ID</th>
<th>post_date</th>
<th>post_title</th>
<th>post_author</th>
<th>User.display_name</th>
<th>guid</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td><%: item.Post.ID %></td>
<td><%: item.Post.post_title %></td>
<td><%: item.Post.post_date %></td>
<td><%: item.Post.post_author %></td>
<td><%: item.User.display_name %></td>
<td><%: item.Post.guid %></td>
</tr>
<% } %>
</table>
<h2>最近投稿した記事(リンク版)</h2>
<ul>
<% foreach (var item in Model) { %>
<li>
<a href="<%: item.Post.guid %>"><%: item.Post.post_title %></a>
by <%: item.User.display_name %>
at <%: item.Post.post_date %>
</li>
<% } %>
</ul>
</asp:Content>
型無しの指定なので、ViewPage
それぞれの表示は、そんまま aspx に記述するとタイピングミスが起こるので、あらかじめコントローラー内でコーディングしたものをコピー&ペーストしました。
コントローラーで、
foreach (var item in model)
{
Debug.Print("{0},{1}",
item.Post.ID,
item.Post.post_date,
item.Post.post_author,
item.User.display_name,
item.Post.guid );
}
のように作っていくと、インテリセンスが使えて便利です。
さて、これを実行するとですね。。。実行エラーが発生するのです。
なんででしょうね?無名クラスで定義したものが、ビューのところではうまく取得できないようです。
■仕方がないのでモデルクラスを作る
という訳で、仕方がないので Posts モデルクラスを作ります。先に作った FindPosts メソッドも踏まえて、こんな感じです。
public class Posts : wp_posts
{
public wp_users User { get; set; }
public wp_posts Post { get; set; }
public IQueryable<wp_posts> FindPosts()
{
wordpressEntities ent = new wordpressEntities();
var model = from t in ent.wp_posts
where t.post_status == "publish"
select t;
return model;
}
public List<Posts> RecentPosts(int max)
{
wordpressEntities ent = new wordpressEntities();
var model = (from p in ent.wp_posts
join u in ent.wp_users on p.post_author equals u.ID
where p.post_status == "publish"
orderby p.post_date descending
select new { Post = p, User = u }
).Take(max);
List<Posts> posts = new List<Posts>();
foreach (var item in model)
{
posts.Add(
new Posts { Post = item.Post, User = item.User });
}
return posts;
}
}
プロパティで wp_posts と wp_users のテーブルが参照できるように Post, User を定義しておきます。後は、コントローラーで作成していた LINQ の文をコピー&ペーストして、この結果を List に詰めて返します。
対して、コントローラーの RecentPosts メソッドは非常になるのでが、なんだかなぁ、という感じですね。
public ActionResult Recent()
{
int max = 5;
Models.Posts post = new Models.Posts();
var model = post.RecentPosts(max);
return View(model);
}
これを動かすと、ビューはそのままで綺麗に動きます。
一応、動くには動くのですが、wp_posts と wp_users のテーブルをいちいち join させないといけないのが CakePHP よりも劣っていますよね。
というのは、EDM(Entitiy Data Model)のところでリレーションを設定していないのが原因なのです。CakePHP では Model::$belongsTo などで join を指定しているのですが、wordpress のテーブルから引っ張ってきたテーブルでは、この join が設定されていません。
なので、お次は、リレーションを設定したうえで、最近投稿した一覧を表示させてみます。



item.Post が aspx 内で参照されない件は不具合っぽいですね…
直接 aspx に <% ... %> で model を抽出するコードを書くと動くので、controller から view に引き渡すところで、何かが違ってしまっているようです。