I'm trying to figure out how to load/set models/classes in Lithium controller. This is my first so serious framework & I like it very much, but I dont know a lot about them. Have used only simple one.
The problem what I have is: I'm trying to figure out how to display different controllers/models in one view/layout (display posts, polls, login box etc in one page). I found a tutorial for cakePHP, so you can see here whats bothering me. I could find answer in Litihum docs. Maybe becouse I just don't know the real key words for that.
http://nuts-and-bolts-of-cakephp.com/tag/cakephp-dashboard/
If you want to display multiple models at once in the same view (like users, latest posts, etc) you can just reference the class:
use chowly\models\Offers;
use chowly\models\Venues;
class OffersController extends \chowly\extensions\action\Controller{
public function index(){
$venues = Venues::find('all');
$offers = Offers::find('all);
}
}
In lithium, you just need to reference a class and you can use it. (No ClassRegistry)
For a working Lithium application, take a look at https://github.com/masom/Chowly and join the irc channel on irc.freenode.net #li3
Related
Sorry for this very noob question. I started PHP for almost 1 months. I don't have any background in programming. Without using a framework. A friend of mine lets me work with him on a project. which uses a php it had a framework which was built by them. Since their team lead decided to pick a new framework, which was laravel and rewrite the whole project. Luckily he still let me join them. I've been working only on the small stuff in the project. I haven't touched any database related during my work with them. after a week I had to go back to my home town so I can't work with them anymore. Since then I keep reading the laravel documentation. And tried database. I stumbled on this eloquent which builds query from class names or method name. I was so confused. But I don't know what to search for or how does this work. I scanned the code and hell it was so advance I give up. I can't sleep on how to make this. so if any of you could give me an example how this works I would be very happy.
class User extends Model
{
}
which when called like this
User::all()
it will give some data. but how.? it this part of php? All I see about php mysql is about pdo. I can't find any examples like this
A model in laravel is linked to a snake cased table. This means that a User model maps to a users table but this can be overwritten by adding this in your model class
protected $table == "my_custom_table_name"
When you use User:all() It will return all the records in the users table. It simply runs select * from users beneath it.
The all() method is defined in the extended model class. You can check it out to understand how laravel automagically does stuff.
I am new to CakePHP.
I want to have a 'settings' page that links to other models. i.e. "groups" and "accounts".
I created a model/and controller for "Settings" as that is what I figured I had to do. Is this a correct assumption?
Now in the 'settings' page, I want to display the MySQL count of "groups" (want to do other things also, but quickly realizing I'm missing something).
in other words, I want to echo the count of [Group Model] in the database in the [Settings Model]
When I try to do that though, CakePHP freaks out and says that there is no table for "Settings" ... and I don't want there to be one.
Whenever I have issues 95% of times you guys show up in google w/answer, but had trouble finding/and wording this one.
Many thanks for your help!
It makes no sense to have a Settings model if you don't have a DDBB table or other datasource associated with it. Plus, model names are by convention singular, so it should be Setting.
You made the SettingsController and a view to show some mixed info about your app, which is ok, but you don't need the Setting model. What you need to do is tell Cake you'll use the Group model in this controller, by doing
public $uses = array('Group');
In most basic tutorials you might not see this since Cake automagically wires up related controllers and models, like GroupsController and Group model.
Now that your SettingsController has the Group model available, you can do:
$this->Group->find('count');
to find what you need.
You'll probably need to reference more models in SettingsController, like Account.
This is the example from the cookbook:
class IngredientsController extends AppController {
public function index() {
//grab all ingredients and pass it to the view:
$ingredients = $this->Ingredient->find('all');
$this->set('ingredients', $ingredients);
}
So it looks like we're using find('all') and returning all of them to the index. I figure we can also create a method called frenchIngredients() that would return all the french ingredients.
My question is do I have to create a separate function for every find condition I want to have for the Controller?
I'm really new to cakePHP, so maybe I just don't understand how this is supposed to work, but the way I'm seeing it, I'm going to have to create large numbers of functions and/or views just to account for changes in find conditions.
Does cakePHP suck that bad or am I missing something? I thought it would make my PHP OOP easier, but really it just seems like a lot of overhead to convert something working into something I have no idea how to work.
Cake has a lot of "magic" functions. You can do findBy<columName> or even findAllBy<columName>. You can also chain the column names like findBy<colum1>And<colum2>.
I suggest you read their cook book article on models. The cook book is a really great way to start and have information about what the framework can do for you. If you want more information on a function you can always go peek in their api which is more complete.
In any frameworks such as ZF and Codeigniter , I think this is actually the process of building your model.
In your example in CakePHP, if you created it with Bakery then you already have this functionality. There are lots of database functions which is included in every model but your job is to extend it. Not all things is already made in your model.
The only thing I can suggest is to be sure and make sure not to be redundant on building Model methods. If you think "freshIngredients" will be the same with other models you can implement a base Model and extend it to your new models. Like creating a Base model with method of "newItems" which will return newly added items or in your part it's ingredients.
There is happily no need to create a function for each simple conditional find.
The find function takes more than one argument (see the doc in Retrieving Your Data) and one of its parameters are the find conditions.
Do you want to fetch only the french ingredients ? Let's say you have categories for the ingredients, and that the 'french ingredient' category has the ID 2, you would do it like this:
$this->Ingredient->find('all', array('conditions' => array('category_id' => 2)));
And conditions passed to find can be much more complex than this simple example.
But off course, it often makes sense to create functions in models when you have some more complex logic than a simple find query.
Situation:
The simplified situation is this: consider a blog that is build as an MVC project. The YII blog-example is fine for this, but the question is not framework specific: It is nothing special; you have a table with posts and a page build from:
a model (YII will give you a basic active-record setup)
a controller that for instance builds the index (list of all posts)
a view (or some views) that build the actual HTML in the end.
Now I have a working blog, but I also have an external source of information that I want to introduce to this same page: for example an RSS feed.
How do I add this new datasource?
Possible sollutions
To clarify what I am struggling with, here are some things I am considering
Make a new model that gets its information from both sources
Feels like the way of least resistance/work
It would need to sort the blogposts and RSS items by date
It might need to give some sort of flag about what kind of item it is (An RSS item might not have an author, but it does have a source).
The fact that above flag feels neccessairy makes me believe these should be 2 models.
Make a new model for the RSS and make a controller that combines the two sources and feeds it to a view that can handle both types of post
Something more complicated (maybe more framework specific), but the current view of a post is just one view for one post, and it gets repeated. Instead of one view that handles both types you might want not only a model, but also a view for your RSS, and a controller(?) that does all the mixing and matching?
Framework notes:
I'm using YII, but it's not really about YII. Ofcourse if something complicated is to be done I will have to implement it in YII, but it's about the design and the MVC pattern, not about where to put the ; ;D
u can hve something like this (I too use yii so the following code follows yii framework)
class XyzController extends CController
{
.
.
.
public function actionAbc()
{
.
.
.
$this->render('viewname',array(
'model1'=>$model1,//for posts frm table
'model2'=>$model2 //for rss feed
));
}
}
for better understanding try to render two separate views for each type of post inside the parent view "viewname"
If i had to do it, i would make a new controller for the view, and use two models.
I am very new to the mvc pattern, however from what i have gathered till now, it feels like any model should limit itself to only one data source. Also in addition to the CRUD operations, the "business logic" (if any) , should be included within that model. Business logic here would mean logic that applies to the data source pertaining to the web app, i.e the things that you have mentioned, like sorting RSS by date.
Create a controller that accesses these two models, to populate your view(s).
Finally the best way to organize these components/modules/parts of the mvc, with respect to Yii, depends on your app requirements, and ux.
Now, i think you should put this question in the programmers site also.
Hope this helps!
Edit: Not too sure where to put the sorting, controller or view.
A lot of frameworks use URL conventions like /controller/action/{id} which is great, but if you need any configuration beyond that, it's up to you to write your own routes.
How would you handle URLs like /users/{id}/friends on the backend? (to list all of a user's friends)
I'm thinking that in the controller, something like this would be appropriate:
class User {
function index() {
echo 'user index';
}
}
class Friend extends User {
function index($user_id) {
echo 'friend index';
}
}
Then you would have the following map:
/users -> User::index()
/users/{id} -> User::view($id)
/users/{id}/friends -> Friend::index($user_id)
I wanted to put the Friend class inside the User class but apparently you can't do that in PHP so this is the best I could come up with. Thoughts?
What URL would use for editing your list of friends? /users/{id}/friends/edit could work, but it doesn't seem appropriate, since you should never be editing someone else's friend list. Would /account/friends/edit be a better choice? Where would you put the corresponding code for that? In a friend controller, or a user controller, or a specialized account controller?
Bonus question: which do you prefer? /photos/delete/{id} or /photos/{id}/delete
The answers:
So, what I've gathered from the answers is that if the "thing" is complicated (like "friends") but doesn't have its own controller, you can give it one without a model, or if it's not, you should stuff it in with whatever it's most closely related to. Your URLs should not influence where you put your code. Most people seem to think you should stick to /controller/action/{id} whever possible, because it's what people are familiar with.
No one really commented on the extended class aside from saying it's "awkward". Perhaps FriendList would have been a more appropriate class in that case if I really wanted to separate it out.
Thanks for all the answers :)
The routes you're talking about, and the way you're using subclasses to achieve this structure, seems a bit awkward to me. The standard convention of /controller/action/{id} works great for simple actions, but if you're creating a complex application you will always need to create custom routes. There are probably some good guidelines to use when creating these routes, but it really boils down to staying consistent across your application and keeping things as simple as possible.
I don't see any good reason to have /user/{id}/friends mapping to a "Friend" controller. Why not just have "friends" be an action on the User controller? Once you actually drill down to view a specific friend's page, you could use a Friend controller (/friends/view/123) or you could repurpose your User controller so that it works for a friend or the currently logged in user (/user/view/123).
Re: the bonus question, I'd stick with /photos/delete/{id} (/controller/action/{id}) as that's the most widely accepted mechanism.
I would prefer /photos/{id}/delete. My reasoning is that if you take one component off the end of an URL, it should still make sense.
It's pretty easy to assume what /photos/{id} should do: view the set of photos for that {id}.
But what should /photos/delete do? That's really unclear.
I know that there's kind of a default convention of /controller/action/id, but that organization is for the sake of mapping to the class/method architecture of controllers. I don't think it's a good idea to organize the UI to accommodate the code (the URL is in a way part of the UI).
Re comments: Yes, /photos/{id} maybe makes more sense to view a given photo by its id. /users/{id}/photos perhaps to view a collection. It's up to you.
The point is that you should think of the UI in terms of users, not in terms of code organization.
You can do either or. The problem is when you mix the two. /users/{id}/friends and /users/friends/{id} When someone has the id of "friends" this will fail. This may seem like a trivial case but it's very popular to use usernames for ids. You will have to limit user names for every action.
Sometimes you can't do /{controller}/{action}/{id}
I did a indie music site a while back and we did
/artist/{username}
/artist/{username}/albums
/artist/{username}/albums/{album}
We didn't want to test for conditionals so we didn't do
/artist/{username}/{album}
Since we didn't want to check for anyone with an album named "albums"
We could have done it
/artist/{username}
/artist/{username}/albums
/albums/{album}
but then we would lose the SEO advantage of having both the artist name and the album name in the URL. Also in this case we would be forcing album names to be unique which would be bad since it's common for artist to have album names the same as other artist.
You could do pure /{controller}/{action}/{id} but then you would lose some SEO and you can't do URL shortening.
/artist/view/{username}
/artist/albums/{username}
/album/view/{album}
Getting back to your example.
/users/{id}/friends/edit could work,
but it doesn't seem appropriate, since
you should never be editing someone
else's friend list.
In this case it should be /friends/edit since your user id is duplicate information assuming your in a session somehow. In general you want to support URL shortening not URL expansion.
(Bonus question)
Neither, i'd use REST. DELETE /photo?id={id}
It also depends on how you are storing your data. I could imagine in some cases you need a 'friend-list' to be a entity in your model. A logical approach would then be to specify a unique identifier for each friend-list, a primary key.
This would logically result in the following route, as you only need a primary key of the friend-list to edit or delete it...
/friends/edit/{friendListId}
It's up to you to decide. As pix0r stated: convention for small applications is /{controller}/{action}/{id} where {id} should be optional to match with most of your websites actions. In some cases applications get big and you want to define specific routes with more than 3 elements. In some cases certain entities just get a bigger meaning (above example) and you could decide to define a custom controller for it (which makes the default route perfect again...).
I'd stick with the default route /controller/action/id but just don't start making controllers for everything (like friends) in the beginning. The Model-View-Controller pattern makes it very easy for you to change routes later on, as long as all your route-links and actions (forms etc.) are generated based on routes and actions. So you don't really have to bother that much :)
The URLs themselves don't really matter too much. What is more important is what goes in each of your controllers. In your example you had your friend list extend the User class. If your list of friends is really just a list of users, maybe it should extend the Users controller so that you deal with lists of users in one place.
class Users {
public function index() {
$users = $this->findUsers();
}
protected function findUsers($userId=null) { ... }
}
class Friends extends Users {
public function index($userId) {
$users = $this->findUsers($userId);
}
}
If you have a hard time figuring out which class to extend write out what you need from each of the classes and pick the one with the longest list.