I have a problem with adding comments to photos on my website. In comments table I have:
id, user_id, photo_id, content, created, modified, erased.
In view I create:
echo $this->Form->create('Comment');
echo $this->Form->input('title');
echo $this->Form->input('content');
echo $this->Form->input($this->Session->read('User.id'), array('type'=>'hidden'));
echo $this->Form->input($photo['Photo']['id'], array('type'=>'hidden'));
echo $this->Form->end('Add comment');
I don't know if it is correct way. How cake will know that 2 hidden values are user_id and photo_id ?
Thx for advices.
You will have to populate User ID in the controller when the data is submitted (so users cannot post as other users). You can fetch the user ID with $this->Auth->user('id'); (providing you are using the built in Auth component). As for photo ID, you obviously have this somewhere as you're loading the photo, you just need to pass this data into $this->request->data before you save.
A simple CakePHP 2 approach would be like so:
public function viewPhoto($photoId) { //$photoId comes from your routes or something
if($this->request->is('post')) {
$this->request->data['Comment']['user_id'] = $this->Auth->user('id');
$this->request->data['Comment']['photo_id'] = $photoId;
$this->Photo->Comment->save($this->request->data);
}
}
This structure be slightly different for you, depending on your controller/model setup.
Related
I have a table in database called 'User'. All I want is to get the basic information of the user. I've tried to get data from database but the thing that keep me bugging is that I get all the data inside the table.
UserTable
|id|username|firstname|lasttname|middlename|gender|age|birthdate|address|contact_number|designation|
1 admin lee chiu kim male 47 07-22-87 cebu 0977452445 admin
2 lrose rose loo mar female 27 04-02-88 cebu 0977452445 manager
3 mgray gray men try male 37 01-22-89 cebu 0977452445 employee
UserProfile.php --> Model
<?php
class UserProfile extends Eloquent {
public $timestamps=false;
protected $table = 'users';
protected $fillable=array('firstname','lastname', 'middlename', 'gender', 'age', 'birthdate', 'address', 'contact_number', 'designation');
}
This is the model of my site.
UserProfileContoller.php --> Controller
<?php
class UserProfileController extends \BaseController {
public function index($id)
{
$userprofile = User::find($id);
return View::make('userprofile.index', array('userprofile' => $userprofile));
//return View::make('userprofile.index')->with('UserProfiles',UserProfile::get());
}
For example I am currently log in to username admin and I want to edit and view my profile. How can I get the data just for admin only. Please Help.
The situation hers is that. let say they have 3 employees. So in the table 3 username. lets assume that I'm not the admin. I will log in using lrose. and the other one log in as admin and so.on. If the three of us will go to our profiles the only thing to display there is their own profile and can edit it.
Assuming you property set-up your database why not just use the DB object?
// In the User table find the item with the username 'admin'
DB::table('User')->where('username', '=', 'admin')->get();
To get the information of some user that is logged in (given you have their username), called something like $userprofile. Then all we need to do is find by id then get the username:
// $id is the ID of the logged in user
$userprofile = User::find($id)->username; // get username of logged in user
$userprofile::find($id) will get you the information for admin only, if $id = 1.
find() only returns 1 tuple from the database.
After you call find(), you can access the data as such:
$userprofile->firstname
you mean when you pass $id to index method of User Controller all the data of other users are returned?
That's kinda weird.
$userprofile = User::find($id); change that line to $userprofile = User::find(1); and see if you can only get the data of admin.
If not, probably you are calling other method. Probably you iterate over the index method somewhere else for multiple times so that you get all the data in the database. To confirm both possibilities, just add echo 'I am in' at the entry point of your index method. If no echo message is shown, the first possibility is true. If multiple echo messages occur, the second possibility is true.
Hope this helps.
first of all, you need to use Session after login and store the id of the username in the Session.
e.g.
Step 1:
if($login) //successfull login
{
Session::put('userid', $userid);
//this id, you have to retreive it from the database after successful login
}
Step 2:
Setup the route
Route::get('profile',['uses' => 'UserProfileContoller#index']);
Step 3:
Controller
public function index()
{
if(is_null(Session::get('userid'))) return Redirect::to('login');
return View::make('userprofile.index', ['userprofile' => $this->model->index()]);
// Above code uses dependency injection to retrieve the information from db.
}
Step 4:
UserProfileModel
public function index()
{
return DB::table('user')->where('id','=', Session::get('userid'))->first();
}
p.s. i find it easier to use query builder than eloquent orm. if you want to use orm, change the code where needed.
I am learning cakephp and have made quite a bit already. The only reason I am asking this question is that the docs in cakePHP could be wrong.
I cant see from the docs or past stackoverflow posts on this issue why the (child)Teacher table doesnt save the user_id from the id table in the (parent)User table.
I get no error but the user_id is 0 in the Teacher table so it isnt picking it up from the User table.
I have a one-one relationship on the 2 models.
I am just testing saving over 2 models where I have a User and teacher. I simply enter data in a form and create a new User and also a new teacher with the user_id being a foreign key in the teacher table.
I am loathe to ask this question as there is a lot of material on this but I just cant see my issue after following the docs in cakePHP.
http://book.cakephp.org/2.0/en/models/saving-your-data.html
public function addteacher() {
if ($this->request->is('post')) {
$this->User->create();
}
if (!empty($this->request->data)) {
// We can save the User data:
// it should be in $this->request->data['User']
$user = $this->User->save($this->request->data);
// If the user was saved, Now we add this information to the data
// and save the Profile.
if (!empty($user)) {
// The ID of the newly created user has been set
// as $this->User->id.
$this->request->data['teacher']['user_id'] = $this->User->id; //here is the problem
// Because our User hasOne Profile, we can access
// the Profile model through the User model:
if ($this->User->Teacher->save($this->request->data))
{
$this->Session->setFlash(__('Your post has been saved.'));
return $this->redirect(array('action' => 'login'));
}
}
}
}
<?php
echo $this->Form->create('User');
echo $this->Form->input('User.username');
echo $this->Form->input('User.password');
echo $this->Form->input('Teacher.firstname'); //text
echo $this->Form->input('Teacher.surname');
echo $this->Form->input('Teacher.address'); //text
echo $this->Form->input('Teacher.suburb');
echo $this->Form->input('Teacher.phone');
echo $this->Form->end('Save Post');
?>
$this->request->data['teacher']['user_id'] = $this->User->id;
should be
$this->request->data['Teacher']['user_id'] = $this->User->id;.
Capital "T". Model names are always CamelCased.
That said there is no need for 2 saves. You can just use
$this->User->saveAll($this->request->data);.
It will save both the User record and Teacher record adding proper foreign key value for the Teacher record (assuming you have setup proper association between User and Teacher model).
I am building a Cake PHP application. Different users have different properties so I use two objects to store a user for example
User hasOne Student / Student belongs to User
User hasOne Lecturer / Lecturer belongs to User
The profile edit page will allow the User to edit all their details for both objects. I've set up the form and used saveAll so save both objects. My problem is dynamically populating the dropdown menus depending on which role the user has.
For example the counties field. Admin does not have an address whereas Student and Lecturer do. I have setup my Country model to find all my counties and put them into opt-groups in the select box (sorting them by country as shown here Dropdown list with dyanmic optgroup)
I can do this fine inside the Students/LecturersController as they allow me to access the Country model as I set $uses variable. I do not want to do this inside the UsersController as not all user roles have an address and an address is never stored inside the User object. I tried putting the code in the model but then I don't know how to access other Models inside a Model. Up to now I've had no problem building the app and I feel that I may have made a bad design decision somewhere or there's something I'm not understanding properly.
Essentially I'm asking how do I implement the setForForm() function below.
public function edit() {
//get user
$user = $this->Auth->user();
//get role
$role = $user['User']['role'];
if ($this->request->is('post') || $this->request->is('put')) {
//get IDs
$userID = $user['User']['id'];
$roleID = $user[$role]['id'];
//set IDs
$this->request->data[$role]['user_id'] = $userID;
$this->request->data[$role]['id'] = $roleID;
$this->request->data['User']['id'] = $userID;
//delete data for role that is not theirs
foreach ($this->request->data as $key => $value) {
if($key !== 'User' && $key !== $role) {
unset($this->request->data[$key]);
}
}
if ($this->User->saveAll($this->request->data)) {
//update logged in user
$this->Auth->login($this->User->$role->findByUserId($userID));
$this->Session->setFlash('Changes saved successfully.');
} else {
$this->Session->setFlash(__('Please try again.'));
}
}
//set role for easy access
$this->set(compact('role'));
//sets required variables for role form
$this->User->$role->setForForm();
//fills in form on first request
if (!$this->request->data) {
$this->request->data = $user;
}
//render form depending on role
$this->render(strtolower('edit_' . $role));
}
//this is the method I would like to implement in the Student/Lecturer model somehow
public function setForForm() {
$counties = $this->Country->getCountiesByCountry();
$homeCounties = $counties;
$termCounties = $counties;
$this->set(compact('homeCounties', 'termCounties'));
}
Not sure if I get your question correct, but I think what you want is the following:
User hasOne Student / Student belongs to User
and
Student hasOne Country / Country belongsTo Student
(and the same for Lectureres)
then from your UsersController you can do:
$this->User->Student->Country->findCountiesByCountry();
hope that helps
--
EDIT:
if you want to want to use $role instead of Student/Lecturer you would have to do it like this:
$this->User->{$role}->Country->findCountiesByCountry();
In the end I decided to just load counties in the user controller regardless of whether the form will need them or not since Admin is the only user that doesn't need them.
Try something like this:
public function setForForm() {
App::import('model', 'Country');
$Country = New Country();
$counties = $Country->getCountiesByCountry();
$homeCounties = $counties;
$termCounties = $counties;
$this->set(compact('homeCounties', 'termCounties'));
}
I don't know is this the best solution or not but it is working at least :)
Edited
Here is another mistake. Its not recommended to set variable from model to view , you can return data that will be set then in edit function normally set it to the view , but anyways if you need to set from model to the view you can load controller class to your model using App::import(); and use set function.
A database table for Event model has following fields:
user_id, name, title
in the Event add view the user is asked to insert the name, hours and minutes as following:
echo $this->Form->input('hours');
echo $this->Form->input('minutes');
echo $this->Form->input('name');
Now the name would be obviously stored as it should, but the problem occurs when I want to concacinate the hours and minutes inserted by user and store them into the DBs "title" field.
Any suggestions for how to achieve this?
use the model's beforeSave function to add any fields you like. In this case a title is being injected
in Event.php
public function beforeSave($options=array()){
parent::beforeSave($options);
$this->data['Event']['title'] = $this->data['Event']['hours'].$this->data['Event']['minutes'];
//do other stuff
return true;
}
I'm new to cakePHP and MVC development and trying to create something with cakePHP but can't figure out how to do this :
I'm creating a simple CRUD application which takes in Albums and Songs through simple data entry forms. I created the DB and used the Cake console app to create all the models / controllers etc and it works well. I can CRUD both albums and songs no problem, and the song table in the DB is connected to the album table with a foreign key so all the links and associations are there in the model.
What I want to do is be able to click on an album and see the songs associated with that album, ,but I'm not sure how to go about it. Do I need to add a query in the model, or does that functionality go into the Controller ?
My take is : in the album list make the album names links, which call a |viewAlbum| function in the Songs Controller with the albumID. Not sure where to go from here though ......
Can anyone point me in the right direction ?
Cheers,
Colm
#JohnP Thank you for your reply. How do you create a link to call that function in the controller though ? I have :
echo $html->link(__($album['Album']['title'], true),
array('controller'=>'Songs',
'action'=>'viewAlbum',
$album['Album']['id']));
Where viewAlbum is the name of the function in the songs controller. Any ideas on why this doesn't work ?
Protos -
If I understand correctly -- you're using John's example, and you need to fix the link in your view that calls his controller?
<?
echo $this->Html->link(__($album['Album']['title'], true), array('controller'=>'Album', 'action'=>'viewSongs', $id));
?>
John's example explained how to create a method in the Albums controller, suggested hitting a method in the Songs model that returned the desired results.
So your link would target the Album controller, and its action should be the controller method.
This method makes less sense in the Songs controller, because it requires an Album id. You just want the Album controller to pull associated data from the Songs model / table. John's answer is exactly correct but maybe too complicated if you're just getting started with Cake. John split the needed functionality by putting a method in the Song model, called by a method in the Albums controller, which pulls results for your view to display.
I'm switching this to "fat controller," which is easier to follow for short code but less MVC.
You need a hasMany relationship from Albums to Songs - each Album hasMany Songs:
// ../models/album.php
class Album extends AppModel {
var $name = 'Album';
var $hasMany = array(
'Song' => array(
'className' => 'Song',
'foreignKey' => 'album_id'
)
);
Your controller action will look like this:
// ../controllers/albums_controller.php
function viewSongs($id = null) {
if(isset($id) && $id != null) {
$albums = $this->Album->find('first',
array('conditions'=>array('Album.id'=>$id));
$songs = $this->Album->Song->find('all',
array('conditions'=>array('Song.album_id'=>$id)));
// This returns variables to the view to use
$this->set(compact('albums', 'songs'));
}
}
Your view will be called viewSongs.ctp, and it'll look something like this:
// ../views/albums/viewSongs.ctp
<?php
foreach($albums as $album) {
echo "<h2>{$album['name']}</h2>";
echo "<ul>";
foreach ($songs as $song) {
echo "<li>{$song['Song']['name']}</li>"
}
echo "</ul>";
}
And your link in ../views/albums/view.ctp would be like:
<?php
echo $this->Html->link('View Songs', array('controller'=>'albums',
'action'=>'viewSongs', $id));
?>
Cake's native ORM already does this for you. If you actually go into the view page for an album, it should be showing you all the related songs there it self. This works only if you have setup the relationships properly.
If you want to code this behavior yourself, you could put a viewSongs action in your AlbumController. This method would look at the album ID passed to it, and call a method (e.g. getSongsByAlbum($aid)) in your Song model. Inside that method in your song model would be a call that looks something like
$opts = array(
'conditions' => array(
'album_id' => $aid
)
);
return $this->find('all', $opts);