onelixir
Question about Phoenix Directory Structure
The Phoenix Framework Doc shows the Directory Structure like this:
lib/hello_web
├── controllers
│ ├── page_controller.ex
│ ├── page_html.ex
│ ├── error_html.ex
│ ├── error_json.ex
│ └── page_html
│ └── home.html.heex
├── components
│ ├── core_components.ex
│ ├── layouts.ex
│ └── layouts
│ ├── app.html.heex
│ └── root.html.heex
├── endpoint.ex
├── gettext.ex
├── router.ex
└── telemetry.ex
I have some question about this:
- Now we have just one
pagecontroller, insidecontrollersdirectory we have 2page_*files and 1page_*directory, if we also add JSON support, then one more file, one controller = 3 files + 1 directory, if we have 10 controllers, will we have 30 files + 10 directories incontrollersdirectory? - If we also need email, like in Rails, where should we put its directory, do we have some generator? And how about jobs?
I ask these questions because I just come from Rails, Phoenix looks simple but also brought too much confuse.
I truely hope Phoenix world have a book like 《 Agile Web Development with Rails 7》, The official document is good, but lack of focus and best practices.
Most Liked
sodapopcan
It’s really just because the framework isn’t concerned about where your files are. For example, our Rails app was split up by feature so we ended up with many directories that essentially each had a mini Rails apps in them. It’s not the biggest deal in to make this work but you’re still going against the framework conventions. You also lose the social friction of new people coming into the app expecting it to look like a Rails app and it doesn’t. Phoenix doesn’t set up any such expectation. I’m not really saying it’s a massive, life-changing improvement but it is part of what drew me to Phoenix even if I do miss some stuff about Rails.
As far as Ecto vs ActiveRecord goes, I would say that is a massive improvement. It takes a bit to get comfortable with the shift away from an ORM, but Ecto is essentially like a super powerful and better designed arel. You don’t run into the same scaling issues with it since it just returns structs (which are no heavier than bare maps) as opposed to massive objects with methods spanning at least five different concerns.
sodapopcan
Phoenix is not opinionated like Rails. There is a tiny bit of “magic” happening with via some dabs of reflection but it’s not pervasive. Phoenix doesn’t care at all where you put your files and the generated structure is more of a guideline. In fact, Phoenix is arguably closer to Sinatra than it is to Rails with $ mix phx.new being what makes it a full fullstack framework. There are single file examples of Phoenix apps out there!
I also came from Rails so I definitely shared some of your pain. I was particularly perturbed that many examples don’t show you exactly were to put files. I’m not saying this is better or worse, but you get used to it pretty quickly.
Your example is actually slightly flawed when comparing number of files to Rails. In Rails, the equivalent page_ files you mentioned would be controllers/page_controller.rb and views/pages/show.html.erb and helpers/page_helper.rb, so actually 3 files and 3 directories! The _html files in Phoenix are a new concept but basically they used to be called views. Phoenix splits up the concept of “view” into “html” and “template” (it used to be “view” and “template”) where html compiles the templates and controllers render the html. This is actually closer to how the general concept of a view quote-unquote “should” work (the “view” is the presentation logic whereas the “template” is the static markup) whereas Rails simplifies it by combining view+template then optionally allowing a ‘helper’ file if you need added presentation logic. In Phoenix, you would put your “helpers” in the PageHTML module. So, you are right in that Phoenix always forces you to have three modules (er, two modules + one template). If you’re strictly concerned about number of files and you don’t mind putting your templates in functions, you can actually define your templates right in PageHTML then you don’t need the show.html.heex file:
defmodule MyAppWeb.PageHTML do
# ...
def show(assigns) do
~H"""
<h1>I'm the show page</h1>
"""
end
end
I actually don’t use the default directory structure at all for web. I don’t have many controllers as I often have LiveViews but I break up my Web module into site sections, so I don’t have a controllers or live directory. Mine would look like this:
my_app_web/
page/
page_controller.ex
page_html.ex
html/
show.html.heex
You don’t have to do anything special to make this work—just move the files around. Although you’ll have to likely have to change the glob given to PageHTML.embed_templates.
onelixir
Thank you so much again, I think I learn a lot from your answers, I will dive into Phoenix to feel the feeling you feel.
Also, one of the most happy thing in Elixir land is because we have so kindly people like you ![]()
Popular in Discussions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








