try to change this:
array('users', 'through' => 'users_to_projects')
into:
array('users', 'class_name' => 'users', 'through' => 'users_to_projects')
same with the other relation.
And you naming convention is ugly, but that's your problem.
What do you mean my naming convention is ugly? users_to_projects? what would you call a database that was a mix between users and projects? users_projects maybe? hmmm. ok noted.
Like this?:
http://pastie.org/1775819
that's the error I am getting now. I am thinking it's not matching users id column with users_to_projects user_id column. That's my thought.
about your mistake: users_to_project vs users_to_projects
The ugly, or unconventional, thing is to not have camel cased classes.
ah well ok I can live with that. So any ideas on the error? I really despise how Active Record messes with your class names to tables names. by making things not plural. It doesn't make sense when you get to things like users_to_projects. Because it should be user_to_projects, or users_to_projects or users_to_projects but you don't know because if it's plural it means a one to many relationship which Active Record doesn't know about. That's my opinion on the matter for naming conventions.
ah well ok I can live with that. So any ideas on the error? I really despise how Active Record messes with your class names to tables names. by making things not plural. It doesn't make sense when you get to things like users_to_projects. Because it should be user_to_projects, or users_to_project or users_to_projects but you don't know because if it's plural it means a one to many relationship which Active Record doesn't know about. That's my opinion on the matter for naming conventions.
Did you read my answer above?
“about your mistake: users_to_project vs users_to_projects” (line 14)
And AR knows if it's a one to many relation since you tell it using `$has_many`
I've tried combo, here I isolated my project and my database into one project file.
Still getting the error. Have a see for yourself:
http://www.2shared.com/file/l3Nf-_E_/up_test.html
I won't dive into your code because I prefer to use my time in a better way (sorry mate), but I'm sure you can do it by yourself. Add some breakpoints into `Relationship.php` to figure out what's going on. It's a good exercise I'm sure.
Ah lame. Well, I think it's AR's limited functionality, my teammates warned me against using an active record pattern and I probably should have listed. PHP is not RoR for a reason.
Is there a way to disable the naming conventions in AR?
Apples and oranges.
Naming conventions are there for good, you can mess around but it's at your own risks.
Jonathan,
You might think that naming conventions are a bad thing, but they are not.
Being 'forced' to give your class or table a certain name makes sure that your names are uniform and that someone else understands them (if they are familiar with ActiveRecord).
The class 'users_to_project' is indeed a bad naming convention. Classes should be named after real-life things, not technical stuff. In my example I will use the class name "Task" instead. So here we go:
1 class User extends ActiveRecord\Model {
2 // Table 'Users'
3 static $has_many = array(
4 array('tasks'),
5 array('projects', 'through' => 'tasks')
6 );
7 }
8
9 class Project extends ActiveRecord\Model {
10 // Table 'Projects'
11 static $has_many = array(
12 array('tasks'),
13 array('users', 'through' => 'tasks')
14 );
15 }
16
17 class Task extends ActiveRecord\Model{
18 // Table 'Tasks'
19 static $belongs_to = array(
20 array('user'),
21 array('project')
22 );
23 }
Now you can write for example:
1 $user = User::find(1);
2 print_r($user->projects);
Because I am following the naming conventions I don't have to specify custom class names or table names so I will make less mistakes and my code is more readable.
I hope that you are convinced now, otherwise feel free to ask.
Ah I made a discovery, figures out part of the renaming pattern is not only does it automatically make a plural word singular, but it removes underscores and changes it to camel case.
So everything works as excepted Jan when we have tasks instead of users_to_projects. Just because of the underscores. So for a test I renames "tasks" to "t_asks" and I got the same error as I did before.
There is a reason why my table is named users_to_tasks and I still want to use that because the rest of my app is using is like that. so is there any way to get around AR automatically changing my underscore naming convention to camel case?
I would suggest that you keep the class name "Task" and then add a custom table name:
1 static $table_name = 'users_to_projects';
I don't think it is currently possible to turn of the naming convention. It shouldn't be too hard to add and option for that though.
Ah nice Jan thanks so much, this is exactly what I was looking for. You've been very helpful :)
Are you one of the developers for AR?
No, I'm not one of the developers :)
Some time ago I created a database interface that has a lot in common with PHP ActiveRecord in the way of creating models and accessing attributes. And I used it successfully is a couple of small projects.
But now I use PHP AR, it has nice features like associations and validations. And it still reminds me of my own interface.
I also just discovered that a model class name cannot have camel case in it, or it will freak out and error.
EDIT:
the model class name CAN have camel case in it, but if you refer to, lets say model class name
"UsersToProjects", from $has_many you have to have it all lowercase. even though the class name is camel case. like so:
1 class UsersToProject extends ActiveRecord\Model{ 2 static $table_name = 'users_to_projects'; 3 static $belongs_to = array( 4 array('user'), 5 array('project') 6 ); 7 } 8 9 class user extends ActiveRecord\Model{ 10 static $has_many = array( 11 array('userstoproject'), #actually it's UsersToProject 12 array('projects', 'through' => 'userstoproject') 13 ); 14 }
p.s. I figured out how to paste code :D
`$has_many` implies that they are more than one item (aka an array of items) so you should pluralize it.
I am assuming your talking about pluralizing array('usertoproject') but you cannot. or you'll get this error
it would make sense to pluralize anything in the $has_many variable. But AR thinks differently.
1 Fatal error: Uncaught exception 'ActiveRecord\HasManyThroughAssociationException' with message 'Could not find the association userstoproject in model user' in /Users/Jonathan/Sites/test/lib/Relationship.php:464 2 Stack trace: 3 #0 /Users/Jonathan/Sites/test/lib/Model.php(493): ActiveRecord\HasMany->load(Object(user)) 4 #1 /Users/Jonathan/Sites/test/lib/Model.php(386): ActiveRecord\Model->read_attribute('projects') 5 #2 /Users/Jonathan/Sites/test/index.php(13): ActiveRecord\Model->__get('projects') 6 #3 {main} 7 thrown in /Users/Jonathan/Sites/test/lib/Relationship.php on line 464 8
No, he means this:
1 class user extends ActiveRecord\Model{
2 static $has_many = array(
3 array('userstoproject'),
4 array('projects', 'through' => 'userstoprojects') // <== HERE!
5 );
6 }
Why not also the line above? Wouldn't that make conventional sense as well?
Ehm... yes it would :)
Are you absolutely sure that it does work in singular form?
Did you run the same test on both versions?
AR might try to find the class "Userstoproject" for "userstoproject" and "Userstoprojects" for "userstoprojects" but that both fail because you used the camel case class name "UserToProject".
everything is lowercase and in singular form, but when I try so user has many userstoprojets (plural). it says it doesn't exist. and when I don't it works just fine.
www.chezmoicamarche.org ¹
1 <?php
2
3 include 'ActiveRecord.php';
4
5 ActiveRecord\Config::initialize(function($cfg) {
6 $cfg->set_model_directory('.');
7 $cfg->set_connections(array(
8 'development' => 'sqlite://db.db'
9 ));
10 });
11
12 /*
13 $ sqlite3 db.db # best name ever
14
15 create table users (id integer primary key, name text);
16 create table projects (id integer primary key, name text);
17 create table users_to_projects (id integer primary key, user_id integer, project_id integer);
18 insert into users (name) values ('yoan');
19 insert into projects (name) values ('php-activerecord');
20 insert into projects (name) values ('lithium');
21 insert into users_to_projects (user_id, project_id) values (1,1);
22 insert into users_to_projects (user_id, project_id) values (1,2);
23 */
24
25 class user extends ActiveRecord\Model
26 {
27 static $has_many = array(
28 array('users_to_projects', 'class_name' => 'users_to_project'),
29 array('projects', 'class_name' => 'project', 'through' => 'users_to_projects')
30 );
31 }
32
33 class project extends ActiveRecord\Model
34 {
35 static $has_many = array(
36 array('users_to_projects', 'class_name' => 'users_to_project'),
37 array('users', 'class_name' => 'user', 'through' => 'users_to_projects')
38 );
39 }
40
41 class users_to_project extends ActiveRecord\Model
42 {
43 static $belongs_to = array(
44 array('user'),
45 array('project')
46 );
47 }
48
49 $user = user::find(1);
50 echo $user->name, ' has the following projects:', PHP_EOL;
51 foreach ($user->projects as $project) {
52 echo ' - ', $project->name, PHP_EOL;
53 }
¹ French joke
That works for you huh? Hmmm I am trying to figure out where I went wrong. quite verbose way of doing it but I guess it's better than some alternatives . and I suppose it all makes sense. I'll give it a shot.
I've already told you where you went wrong buddy.
Yoan Blanc wrote:
“about your mistake: users_to_project vs users_to_projects” (line 14)
(1-25/25)
Subject: My First Association :(
This is what my table structure looks like:
http://www.gliffy.com/publish/2602152/
It's as basic as it comes. one "users" table, one "projects" table, one relationship "users_to_projects" table to tie them together. the field name are accurate as well.
The goal is to see which projects user "1" has (can have many). This is how I set up my activerecord and the error I get:
http://pastie.org/1772961