I have a table called websites and a table called clients
Clients has many websites and a website belongs to a client
Now for this i have created the following connection in my Models:
class Website extends AppModel
{
public $belongsTo = array(
'Client' => array(
'className' => 'Client',
'dependent' => false,
'foreignKey' => 'client_id'
)
);
}
class Client extends AppModel
{
public $hasMany = array(
'Website' =>array(
'className' => 'Website',
'dependent' => true,
'foreignKey' => 'client_id'
)
);
Now whenever a client goes to edit the client should ONLY be able to edit the website ids that belongs to that user.
However in my case any client is able to edit any websites.
is there a way to deny them access without hardcoding a check at the controller?
I mean there should be a way that the magic in cake can find only websites that belongs to that clientid
Now, if you have properly set the Auth Component with Client Model, i mean that one client can not modify other client, but you need to cross check for the website they are editing belongs to them or not this might help..
public function _check_member($client,$website){
$this->loadModel('Website');
$options = array(
'conditions' => array('Website.client_id' => $client,'Website.id' => $website),
'recursive' => 0
);
$website = $this->Website->find('first', $options);
if($website){
return true;
}else{
return false;
}
}
and you will call the function with $this->_check_member($client_id,$website_id); Now only to the client this website belongs to will return 1.
But if your clients are able to edit one another, you should look into auth component. here is a video tutorial Auth Component setup , if you are having problems setting up auth component using the client model because every tutorial shows how to do it with user model, which is default, let me know in the comments.
Related
How can I use has_one and has_many in codeigniter 3.0?
I would like to create relations through tables like in Ruby on Rails.
I.E
Class User
{
has_many: comments
}
Class Comments
{
belongs_to: users
}
This is the most common usage, and is used in almost every project. There is a simple pattern to defining this relationship.
Post has a creator and an editor, which may be different users. Here's how to set that up.
Post
class Post extends DataMapper {
$has_one = array(
'creator' => array(
'class' => 'user',
'other_field' => 'created_post'
),
'editor' => array(
'class' => 'user',
'other_field' => 'edited_post'
)
);
}
User
class User extends DataMapper {
$has_many = array(
'created_post' => array(
'class' => 'post',
'other_field' => 'creator'
),
'edited_post' => array(
'class' => 'post',
'other_field' => 'editor'
)
);
}
A couple of things to note here.
The relationship is now defined by the relationship key on either
side, not the model name. This has now become the only way to look
up the relationship.
The key on one side of the relationship becomes the other_field on
the opposite side, and vice-versa.
Because we need a way to specify the difference between posts that
were edited and those that were created, we have to declare the
slightly unusual edited_post and created_post relationships. These
could have any name, as long as they were unique and mirrored on
Post.
http://datamapper.wanwizard.eu/pages/advancedrelations.html
Okay, so I have a form in CakePHP that submits to a database. In this form it submits a field called client_id and it is stored in the database as such as well.
Then I have a view to allow me to view all of the invoices that have ever been created. To view the client responsible for the invoice, I can currently only see the id entered in the form by placing: <?php echo $invoice['Invoice']['client_id']; ?> in the view.
The invoices go to one database called: invoices
The clients name is not stored in the invoices table, just the id
The clients information is stored in one database called: clients
I want to be able to actually display out the clients real name in the invoices view rather than the client id.
I tried adding the following query to my index controller, But i'm not sure what to do after this or if this is even right.
$this->set('clients', $this->Invoice->query("SELECT * FROM clients WHERE id='89545'"));
In order to keep this question short in the first place, Please request specific code by commenting. i.e. Controller code, view code, etc... Thank you in advance.
Additional Thoughts
If I wasn't using CakePHP I could use something like the following, So I guess I just don't know how to put this into cakephp "language".
<?php
query($con, "SELECT name FROM clients WHERE id='$client_id'");
echo $row['name'];
?>
roughly!
Update
Here are my models
First one being the Client.php
<?php
class Client extends AppModel {
public $hasMany = array(
'Invoice' => array(
'className' => 'Invoice',
'foreignKey' => 'client_id'
)
);
}
?>
Second one being the Invoice.php
<?php
class Invoice extends AppModel {
public $belongsTo = array(
'Client' => array(
'className' => 'Client',
'foreignKey' => 'client_id'
)
);
}
?>
And finally, to get my invoices from the database, I am using the following inside: InvoicesController.php
public function index() {
$this->set('invoices', $this->Invoice->find('all'));
}
Have you properly set up your model associations? If so you should be able to do something like $invoice['Client']['client_name'] assuming you didn't use recursive = -1.
/edit: Ok I don't mind throwing some code out, but this is a fundamental concept you'll have to try to wrap your head around. Every model that is connected to another model has to have the association set up or things will be painful.
I am assuming a Client hasMany Invoice. So each invoice is specific to a client, and they can have multiple invoices (ex. October 2013 vs November 2013 invoice). From the CakePHP page we see:
class User extends AppModel {
public $hasMany = array(
'Comment' => array(
'className' => 'Comment',
'foreignKey' => 'user_id',
'conditions' => array('Comment.status' => '1'),
'order' => 'Comment.created DESC',
'limit' => '5',
'dependent' => true
)
);
}
So using that as our template, we end up with:
public $hasMany = array(
'Invoice' => array(
'className' => 'Invoice',
'foreignKey' => 'client_id'
)
);
And that goes in Client.php. As the inverse of hasMany is belongsTo, we have an Invoice belongsTo Client. Again, using the CakePHP page as the template, we end up with:
public $belongsTo = array(
'Client' => array(
'className' => 'Client',
'foreignKey' => 'client_id'
)
);
And that goes in Invoice.php. Once you set up those associations, whenever you do something like $this->Invoice->find('all'); or $this->paginate('Invoice');, with proper $recursive settings, Cake will grab the corresponding Client record. This allows you to do what I said before, something like $invoice['Client']['client_name'].
You can also use the $actsAs = array('Containable'); in the model in order to use the 'contain' directive in your controller's find method (instead of using recursive which most likely will get unwanted data on models with many relations)
I have HABTM for Users and Groups. I want to show in a Group view - all the Groups that belong to a User. Or to put it differently - all the Groups that have the User.
I am getting tangled in the MVC and am not able to figure it out. Here are my two models:
class Course extends AppModel
public $name = 'Course';
public $hasAndBelongsToMany = array('User' =>
array(
'unique' => false
)
);
And...
public $name = 'User';
public $hasAndBelongsToMany = array('Course' =>
array(
'unique' => true
)
);
The table name in the database is courses_users - this table houses group ids and user ids.
Should be simple enough but I'm new to CakePHP so I'd love some help. Thank you!
CakePHP has recursive set to 1 by default, which means that assuming you have not changed the recursive setting, it will automatically fetch all associated courses when you call find on a user, assuming you set up the HABTM relationship when doing the find. Therefore, all you have to do is:
$this->User->find('first', array('conditions' => array('User.id' => $this->Auth->user('id'))));
In your User model, I don't think it's strictly necessary, but I like to specify the join table and such on HABTM relationships:
public $hasAndBelongsToMany = array('Course' =>
array(
'unique' => true,
'dependent' => false,
'joinTable' => 'courses_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'course_id',
)
);
Keep in mind that in HABTM relationships, you don't ever really touch the joinTable beyond specifying which table to use as the joinTable when setting up the relationship. CakePHP will automatically do the rest of the work.
I have a model called Forwards this model uses a table from my Database. However it is required for some of the views connected to this model to use my costum datasource (This is a datasource i have created which links it to an API).
Now my question how can i add a datasource to a Model that already has a datasource.
And how can i tell the Paginator that it has to use this datasource when it is paginating (so it doesnt confilct)
Update
I have been reading abit it seems the only way to use two datasource in a model is to Hack abit, so i was wondering is it possible to use two models from one controller while still paginating?
i want to keep these settings
public $paginate = array(
'fields' => array(
'Offer.id',
'Offer.name',
'OfferUrl.preview_url',
'Stat.ltr',
'Stat.cpc',
'Category.name',
'Country.name')
, 'conditions' => array('Stat.date' => array(
'conditional' => 'BETWEEN'
, 'values' => array()
),
),
'group' => array('Stat.offer_id'),
'Method' => 'getStats',
'totals' => true,
'limit' => 20
);
I set these within my controller
You can change the data source by calling Model::setDatasSource().
You can change the model the paginator uses by:
$this->Paginator->paginate($ModelInstance);
Or
$this->Paginator->paginate('ModelName');
You might want to read that page.
Don't use Controller::paginate any more but instead $this->Paginator->settings. For settings per model use
$this->Paginator->settings['ModelName'] = array(/*...*/);
When I was working on my current project, I ran into a rather complex issue. I'll point out my problem much more detailed right now:
There are three Models: User, UsersExtendedField and UsersExtended.
UsersExtendedField contains custom fields that can be managed manually. All custom fields can be shown in the Users view as well, and be filled out of course. The values are then stored in UsersExtended, which has got two foreignKeys: user_id and field_id.
The relations look like this: User hasMany UsersExtendedField, UsersExtendedField hasMany UsersExtended, UsersExtended belongsTo User, UsersExtendedField.
The problem: When accessing the Users view, a form with user information input is shown. Any UsersExtendedFields are available as well, and since these hasMany UsersExtended, they've got plenty of UsersExtended values. But I want to reduce those to only the value(s) that belong to the User, whose view is shown at the moment. Here are my (desired) relations:
Croogo::hookBehavior('User', 'Crooboard.ExtendedUser', array(
'relationship' => array(
'hasMany' => array(
'UsersExtendedField' => array(
'className' => 'Crooboard.UsersExtendedField',
'foreignKey' => '',
'conditions' => array('status' => 1)
),
),
),
));
class UsersExtendedField extends AppModel {
var $name = 'UsersExtendedField';
var $displayField = 'fieldname';
var $hasMany = array(
'UsersExtended' => array(
'className' => 'Crooboard.UsersExtended',
'foreignKey' => 'field_id',
'conditions' => array(
'UsersExtended.user_id = User.id'
)
),
);
}
This is not the full code, these are the important parts. The problem starts right where I wrote 'UsersExtended.user_id = User.id'. Obviously, this won't work. But I do not have any idea how to access the User.id here. I also could not imagine a HABTM structure to solve this task. Do you have any idea how to get the semantics of this 'UsersExtended.user_id = User.id' to work?
Thank your very much for taking the time to read through this and helping me!
It sounds like you need to set up your HABTM relationship properly.
You already have the join table, UsersExtended, which contains your foreign keys.
Remove all previous relationships and set up HABTM in each of your User and UserExtendedField models.
The relationship code in your User model would look like this:
var $hasAndBelongsToMany = array(
'UsersExtended' => array(
'className' => 'UsersExtended',
'joinTable' => 'UsersExtended', //assuming this is the
//name of that model's table
'foreignKey' => 'user_id',
'associationForeignKey' => 'field_id'
)
);
For more information check out the page in the cakephp book
In addition, this blog post helped me grasp the relationship concepts when I was learning cakephp.