Change Client id to Client Name with CakePHP - php

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)

Related

CakePHP: Show value stored in another model based on primary key

Getting started with CakePHP and loving it. However I'm stuck in this noob situation and I'm not sure which way to solve this.
Basically, I have two models, departures and ports. The tables look like this:
departures
id
port_from
port_to
time_arrival
time_departure
ports
id
name
location
active
note
Now I want to list all the departures, port_from and port_to contains ID from ports. Instead of showing just the port ID, I want to show the port name instead, but I have no idea how this could be done?
Using two sets of $this->set in my Departures controller, I have the possibility to show values from the Ports table. I have been looking for solutions but I don't think belongsTo or hasMany is the way to go here?
Thank you for any help.
You have to set relationship in your model:
class Departure extends AppModel {
public $belongsTo = array(
'From' => array(
'className' => 'Port',
'foreignKey' => 'port_from'
),
'To' => array(
'className' => 'Port',
'foreignKey' => 'port_to'
)
) ;
} ;
Then you just use find or read to get your departure (in your controller):
$this->set('departure', $this->Departure->read(null, $id)) ;
And in view, you access ports name using:
$departure['From']['name'] ;
$departure['To']['name'] ;
And you access normal Departure info using:
$departure['Departure']['time_arrival'] ;
You can set two belongsTo associations in Departure model.
$belongsTo = array(
'PortForm' => array(
'className' => 'Port',
'foreignKey' => 'port_from'
),
'PortTo' => array(
'className' => 'Port',
'foreignKey' => 'port_to'
),
);
Now when you do a find() on Departure model in the results array, for each Departure record you will have the corresponding PortFrom and PortTo records.

Database table to make drop down select using cakephp

I have one controller for invoices and another for clients.
I have made some "relationships" in the models of these controllers as below:
Client.php
<?php
class Client extends AppModel {
public $hasMany = array(
'Invoice' => array(
'className' => 'Invoice',
'foreignKey' => 'client_id'
)
);
}
?>
Invoice.php
<?php
class Invoice extends AppModel {
public $belongsTo = array(
'Client' => array(
'className' => 'Client',
'foreignKey' => 'client_id'
)
);
}
?>
So I thought that making a drop down with each client would be easy. Although, I can't figure out how to do this.
First off this is what I want as a result:
<select>
<option value="1">Client Name</option>
</select>
Where value is equal to id in client table and Client Name is equal to name in client table.
I tried placing the following into the invoices controleler:
$client = $this->Client->find('all');
and then the following into my view:
echo $this->Form->select('client_name',client, array(
'class' => 'form-control',
'name' => 'client_id'
));
But I received the following error:
Call to a member function find() on a non-object
Directly on page load. What do I need to do to make this work?
More than likely, your problem is that the Client model is not automatically loaded in the Invoices controller. Since Client has a relationship with Invoice, you can call find on Client like this instead:
$data = $this->Invoice->Client->find('list', array('fields' => array('id', 'name')));
$this->set('clients', $data);
Then in the view,
echo $this->Form->select('Invoice.client_id', $clients);
or
echo $this->Form->input('Invoice.client_id', array('type' => 'select', 'options' => $clients));
This should output a dropdown where the values are the client id's and the visible options in the drop down are the client names. You will want to go by id's rather than client names when associating invoices with the clients.

Getting All groups that belong to user

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.

Cakephp limit view of items to users

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.

CakePHP/Croogo: A veeery complex association

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.

Categories