I am using Kohana 3.2, not that it matters much, but I am writing an application where I am wrapping any and all returned database records in a specific class. I don't know that I understand the best way to load the database row into the class, because sometimes it is a ORM model and sometimes it might just be an row ID.
So from a controller if I wanted a list of all the users it would look something like:
Controller:
$users = User::find_all();
User Class
public static function find_all()
{
$users_model = ORM::factory('user')->find_all();
$users = array();
foreach ($users_model as $user_model)
{
$users[] = User::instance($user_model);
}
return $users;
}
That works great, but sometimes I need to load a user object with just an id, like after some action, again a example:
Controller
$user_id = $_POST['user_id'];
$user = User::instance($user_id);
So is the User class responsible for trying to identify if an ID or a ORM object was passed into it. It seems like that isn't right for good OOP practices, but I am really not sure what the best way to do it is. What I have been currently doing is in the construct:
public function __construct($user, $load = 'model')
{
if ($load == 'model')
{
$this->user_model = $user;
}
if ($load == 'id')
{
$this->user_model = ORM::factory('user', $user);
}
}
But that really just doesn't feel right. Any advice would be greatly appreciated.
If you already have a user model that extends ORM then you probably don't need static methods in the class to get all users or to get a particular user.
In your controller you can just do to get all the users
$users = ORM::factory('user')->find_all();
To get a single user
$user = ORM::factory('user', $user_id);
If you still want to go down the wrapping route you could use functions like so
public static function all() {
$users = ORM::factory('user')->find_all();
if (count($users)) {
return $users;
}
return false;
}
public static function get($user_id) {
$user = ORM::factory('user', $user_id);
if ($user->id) {
return $user;
}
return false;
}
In your controller, use the ORM to get the user based on the ID.
$user_id = $_POST['user_id'];
$user = ORM::factory('user', $user_id);
Or given that you already have a find all in your user class, add a find_one() method:
User Class
public static function find_one($user_id)
{
$user = ORM::factory('user', $user_id);
return $user;
}
Controller
$user_id = $_POST['user_id'];
$user = User::find_one($user_id);
See the Kohana docs.
http://kohanaframework.org/3.1/guide/orm/using#finding-an-object
http://kohanaframework.org/3.1/guide/orm/examples/simple
Maybe like this:
public function __construct($user)
{
$this->user_model = is_object($user) ? $user : ORM::factory('user', (int)$user);
}
Related
I have a User model, in which I have the following function:
public function employees()
{
return $this->hasOne('App\Employee','userid');
}
Then there is an Employee model, which has a function:
public function users()
{
return $this->belongsTo('App\User','userid');
}
Now I want to implement this functionality, can I do this:
$user = User::findOrFail($user->id);
$employee = $user->employees()->where('userid',$user->id)->get();
$employeeStartDate = $employee->startdate;
You can do this:
$user = User::with('employees')->findOrFail($user->id);
dd($user->employees);
Or, since it's one-to-one relationship you could try this:
$user = User::findOrFail($user->id);
dd($user->employees());
Since you're working with one to one relationships, it'd be easier to understand your relationships if you renamed them to their singular versions (employee(), user()).
Then, you can load the relationship in your query using the with() method:
public function index()
{
$user = User::with('employee')->findOrFail($id);
$startDate = $user->employee->startdate;
}
i have two tables users its model (User) ... and servs it model (servs) .... the relation is one to many .... when i try to select all sevices with belong to one user .... it select first service only and ignore others ... this is code i used it
public function getserv(){
return View::make('infos.serv');
}
public function postserv(){
$user = User::find(Auth::user()->id);
$user_id = $user->id;
$serv = servs::where('user_id','=',$user_id);
if($serv->count()){
$serv = $serv->get();
//return $serv->user_id;
foreach ($serv as $servs) {
return $servs->serv_id;
}
}
}
Instead of returning the data at the first loop, you should better do something like this:
$result = array();
foreach ($serv as $servs) {
$result[] = $servs->serv_id;
}
return $result;
Try this.
public function postserv(){
$user = User::find(Auth::user()->id);
$user_id = $user->id;
$serv = servs::where('user_id','=',$user_id)->get()->first;
if($serv)
return $serv->serv_id;
else
return null;
}
You only see the first one because when you return something the function ends and the rest of $serv doesn't get processed.
I recommend you first set up Eloquent relations properly
class User extends Eloquent {
public function servs(){
return $this->hasMany('servs');
}
}
After that you can retrieve all servs for a user like this:
$user = Auth::user();
$servs = $user->servs;
foreach ($servs as $serv) {
echo $serv->serv_id;
}
Sorry for posting such a noob question, but I've had hard times when working with returning a single
row from database and pass it to model. Here's my method from my model:
public function test($user_id)
{
$query = $this->db->query("SELECT COUNT(*) AS test FROM test WHERE user_id = '.$user_id.'");
return $query->first_row('array');
}
Here's an example of my controller with some other returned value from my model:
class MY_Controller extends CI_Controller
{
public $layout;
public $id;
public $data = array();
public function __construct()
{
parent::__construct();
$this->output->nocache();
$this->load->model('subject_model');
$this->load->model('user_model');
$this->load->model('survey_model');
$this->id = $this->session->userdata('user_id');
$this->data['check_if_already_posted_it_survey'] = $this->survey_model->checkIfAlreadyPostedSurvey('it_survey', $this->id);
$this->data['check_if_already_posted_lvis_survey'] = $this->survey_model->checkIfAlreadyPostedSurvey('lvis_survey', $this->id);
$this->data['test']= $this->survey_model->test($this->id);
$this->layout = 'layout/dashboard';
}
I can pass all the values from that data array to my view except "test". I've basically tried everything.
CheckIfAlreadyPostedSurvey method will return
number of rows with num_rows and I can easily print the value from them in my view by writing:
<?=$check_if_already_posted_it_survey?>
What should I do to print out that "test" in my view?
Thanks in advance and apologizes...
I probably got the question wrong, but have you tried
echo $this->survey_model->test($this->id);
Try this:
public function test($user_id)
{
$query = $this->db->query("SELECT COUNT(*) AS test FROM test WHERE user_id = '".$user_id."'");
return $query->row()->test;
}
This will return a single row as an object and then the referenced row name, which in this case is test.
The following will also work.
public function test($user_id)
{
$query = $this->db->query("SELECT * FROM test WHERE user_id = '".$user_id."'");
return count($query->result());
}
You also messed up the quoting in your SQL statement.
With symfony && doctrine 1.2 in an action, i try to display the top ranked website for a user.
I did :
public function executeShow(sfWebRequest $request)
{
$this->user = $this->getRoute()->getObject();
$this->websites = $this->user->Websites;
}
The only problem is that it returns a Doctrine collection with all the websites in it and not only the Top ranked ones.
I already setup a method (getTopRanked()) but if I do :
$this->user->Websites->getTopRanked()
It fails.
If anyone has an idea to alter the Doctrine collection to filter only the top ranked.
Thanks
PS: my method looks like (in websiteTable.class.php) :
public function getTopRanked()
{
$q = Doctrine_Query::create()
->from('Website')
->orderBy('nb_votes DESC')
->limit(5);
return $q->execute();
}
I'd rather pass Doctrine_Query between methods:
//action
public function executeShow(sfWebRequest $request)
{
$this->user = $this->getRoute()->getObject();
$this->websites = $this->getUser()->getWebsites(true);
}
//user
public function getWebsites($top_ranked = false)
{
$q = Doctrine_Query::create()
->from('Website w')
->where('w.user_id = ?', $this->getId());
if ($top_ranked)
{
$q = Doctrine::getTable('Website')->addTopRankedQuery($q);
}
return $q->execute();
}
//WebsiteTable
public function addTopRankedQuery(Doctrine_Query $q)
{
$alias = $q->getRootAlias();
$q->orderBy($alias'.nb_votes DESC')
->limit(5)
return $q
}
If getTopRanked() is a method in your user model, then you would access it with $this->user->getTopRanked()
In your case $this->user->Websites contains ALL user websites. As far as I know there's no way to filter existing doctrine collection (unless you will iterate through it and choose interesting elements).
I'd simply implement getTopRankedWebsites() method in the User class:
class User extends BaseUser
{
public function getTopRankedWebsites()
{
WebsiteTable::getTopRankedByUserId($this->getId());
}
}
And add appropriate query in the WebsiteTable:
class WebsiteTable extends Doctrine_Table
{
public function getTopRankedByUserId($userId)
{
return Doctrine_Query::create()
->from('Website w')
->where('w.user_id = ?', array($userId))
->orderBy('w.nb_votes DESC')
->limit(5)
->execute();
}
}
You can also use the getFirst() function
$this->user->Websites->getTopRanked()->getFirst()
http://www.doctrine-project.org/api/orm/1.2/doctrine/doctrine_collection.html#getFirst()
I have
1.Table:user(userId,userName,userGroup)
2.Model:userModel
3.usercontroller
there i a simple code:
Controller:
class UserController extends Zend_Controller_Action
{
public function getuser()
{
$userModel = new userModel();
$this->view->usergroup = $userModel;
}
}
Model:
class Model_UserGroupModel extends Zend_Db_Table_Abstract {
public function getuser(
{
$select = $this->select();
return $this->fetchAll($select);
}
}
view:
please tell me what code I must insert in view to only have user with specific row like user with group teacher also i use partialoop???
foreach ($this->usergroup->toArray() as $userGroup) {
echo $userGroup['row'];
}
should work
To filter rows based on a particular field like userGroup you need to do a query with where condition.
$where = $this->getAdapter->quoteInto("userGroup = ?", 'teacher');
$select = $this->select()->where($where);
So now you can get users for a particular user group.