Loading data from Database with Atk4 - php

To be hones working with Atk4 is a great adventure for such a rookie as I am. and now i have really a problem i can't solve by myself.
I have two tables in MySQL database. The first one is named user (id, username, email) and the second one is named trips (id, user_id, name). I have made a login and register form for users. I want a logged user to be able to see it's own trips. I used to make this thing for its profile information using the following code:
<?php
class page_userprofile extends Page{
function init(){
parent::init();
$this->api->auth->check();
$model = $this->add('Model_user');
$this->add('FormAndSave')->setModel($model)->loadData($this->api->auth->get('id'));
}
}
I have to do something similar with Model_trips but I do not know what. i have tried with
that example from Atk4 website:
// Traverse foreign keys. Automatically loads proper model and data
$company=$emp->getRef('company_id');
This is the last code I have written:
<?php
class page_mytrips extends Page{
function init(){
parent::init();
$this->api->auth->check();
$model = $this->add('Model_trips');
$this->add('FormAndSave')->setModel($model)->loadData($this->getRef('user_id'));
}
}

You are very close:
$model = $this->add('Model_trips');
$model->setMasterField('user_id', $this->api->auth->get('id'));
Afterwards you can use model inside CRUD, MVCGrid, MVCForm or MVCLister, the following rule will apply:
When listing, only trips belonging to current user will be shown
When adding, user_id will be set to current user's id
Sometimes I add function:
class Model_User extends Model_Table {
function getTrips(){
return $this->add('Model_trips')
->setMasterField('user_id',$this->get('id'));
}
}
Then you can make use the following.
$model = $this->add('Model_user')->loadData($user_id)->$getTrips();
Handy if you want to see other users trips.

Related

Best way to name controllers and models in codeigniter

I am trying to make some basic web apps using code igniter and I have realized that I have a lot of elements calling controller methods which grab data from its corresponding model and I am trying to figure out the best way to name these methods which pretty much do the same thing.
For an example, say I want to grab all the users on my site. I would have a method in my controller named get_users() and then that method would load and call a method in my model named fetch_users() which would grab the users from the database and return the result_array to the controller and then from there to the view.
This seems a little redundant (Calling get_users() which calls yet another function named fetch_users())
I just want to know if this is the only way to do this sort of action, or if there is another "cleaner" way of doing it.
Hope this makes sense.
Thanks!
I like to separate more code, to be more clear.
For example:
USERS
I crate one controller class with name Users and with:
function index() {} // (where show the list),
function add() {} // (add one user)
function edit($user_id) {} // (edit one user)
function view($user_id) {} // (view one user)
function delete($user_id) {} // (delete one user)
I create one model with name Users_model and with:
function get_list() {} // Get list of users
function get_one($user_id) {} // Get one user
function add() {} // add one user on db
function update($id, $data) {} // Update one user on db
function delete($id) {} // Delete one user on db
In this form I do with other things like (Blog, posts, comments etc).
Dear if you are going to build a large application try to put each of your controllers
and models
in different folders and name all of your controllers as home or index and different name for each folders
for example:
you have a controller for assets so create a folder inside your applications controller
folder and name it assets and than inside this assets create a controller name it home.php
class Home extends CI_Controller
{
function __construct()
{
parent::__construct();
}
}
for models you should use the name of operations which your models perform
for example for CRUD model do create something like this: crud_model
class Crud_model extends CI_Model
{
function __construct()
{
parent::__construct();
}
}
for functions you should give function names which is understandable and separate each part with underlines
for example if you have a function that gets total of users you may do write like this:
function get_total_users()
{}
or for users function
function users()
{
}
for update, delete and insert the same way.

how to extract a specific list from a Model with Agile Toolkit

i'm working with Agile Toolkit
i got a Model_Product
class Model_Product extends Model_Table {
public $table="product";
function init(){
parent::init();
$this->addField('name')->mandatory(true);
$this->addField('price')->mandatory(true)->type('money');
$this->addField('user_id')->refModel('Model_User')
->defaultValue($this->api->auth->get('id'));
//$this->hasOne('User',null,'email'); => send me an error message
}
}
and Model_User
class Model_User extends Model_Table {
public $table="user";
function init(){
parent::init();
$this->addField('first_name')->mandatory('Prénom nécesssaire');
$this->addField('last_name')->mandatory('Nom nécesssaire');
$this->addField('email')->mandatory('entrez un email valide');
$this->addField('nationality')->mandatory('nécessaire')->enum(array('FR','EN','US'));
$this->addField('birthday')->defaultValue(date('Y-m-d'))->type('date');
$this->addField('is_admin')->type('boolean');
$this->hasMany('Product','user_id');
}
I want to list on a User page all the products from one User
$q=$this->api->db->dsql();
$q->table('product')->where('product.user_id',$this->api->auth->model['id']);
$tab->add('GRID')->setModel($q);
Some way, I get it wrong because I get an error no mater how I try to filter my Model.
If you're not using newest ATK4 version from Github then you should grab it and stay up-to-date.
You should do like this:
1) In Model_Product create hasOne reference and not refModel (it's deprecated).
// adding 'user_id' parameter is not needed, it'll be calculated anyway
// but many developers add it anyway to clear thing up a bit.
$this->hasOne('User','user_id')->defaultValue($this->api->auth->get('id'));
2) Model_User is OK.
Just some side-notes about it:
I don't think you should make birthday = today() by default.
It's quite unbelievable that child at his first day in this world will use computer :)
is_admin should be mandatory + defaultValue(false) - by default user is not admin.
3) How to list all all products from current user.
// model of current user
$model = $this->add('Model_User')
->load($this->api->auth->get('id'));
// add grid
$page->add('Grid')
// reference Product model with condition already set
->setModel($model->ref('Product'));
and that's it.
Maybe even better and safer way is to define new model class for logged in user:
class Model_Myself extends Model_User {
function init(){
parent::init();
$this->addCondition('id', $this->api->auth->get('id'));
$this->loadAny(); // I'm not sure do we have to explicitly load it here
}
}
and then create grid like this
// model of products of current user
$prod_model = $this->add('Model_Myself')->ref('Product');
// add grid
$page->add('Grid')->setModel($prod_model);

CodeIgniter and DataMapper

I've read through a few different posts here and I can't figure out what I'm doing wrong.
My DB is setup like the following:
homes
- id
- address_id
- price
- etc...
address
- id
- home_id
- address1
- address2
- etc...
Then my models look like this, condensed.
home.php
<?php
class Home extends DataMapper {
public var $has_one = array('address');
}
address.php
<?php
class Address extends DataMapper {
public var $has_one = array('home');
}
Then my controller uses the following:
homes.php
class Homes extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->library('datamapper');
}
public function index() {
$homes = new Homes();
$homes->include_related('address');
$homes->get_iterated();
$this->output->enable_profiler(TRUE);
_p($homes); // Self made function that wraps a print_r() in two <pre> tags.
}
}
If I comment out these two lines I get the standard CI return array.
$homes->include_related('address');
$homes->get_iterated();
If I don't then I get a server error. This is my first time using DataMapper and I'm almost certain I'm doing everything wrong, but have no idea where to start.
UPDATE:
I figured out my issue. I had to change the DB table address to addresses and in my address.php model I had to specify var $table = 'addresses';
That fixed everything.
Yes you can specify the table name in your model. Also your example was wrong :
$homes = new Homes();
Should be
$homes = new Home();
I usually redefine the table name within my model to make sure everything is fine.
Your relations is wrong. I assume you are setting a One to One relation ship. The doc say :
http://datamapper.wanwizard.eu/pages/relationtypes.html
Because this is a One to One relationship, the relationship could have been stored in three ways:
As shown, on the workers table.
On the workplaces table, as worker_id
On a dedicated workers_workplaces join table, with the columns id, worker_id, and workplace_id
But here you have added *address_id* to home and *home_id* in address.
You have to choose between on. For example keep *home_id* in address and remove *address_id* in home.

How to call the items from table

I am a newbie in Cake PHP, and I need to transform my html website to use CakePHP. I am having trouble understanding how it works, but i know that if I make one piece work I should be able to continue building it, I just need that initial help hand that I havent been able to clearly understand in the tutorials. So here is a small scenario from my website
I have a MySql Table called cars, this table has the following values
car_id
car_name
car_description
car_price
in app/controllers i created my control cars_controller.php
<?php
class CarsController extends AppController {
var $name = 'Cars';
}
?>
in my model I created a Car.php
<?php
class Car extends AppModel{
var $name = 'Car';
}
?>
What I am having issues with, is now... how can I show these cars, how do I set up a view to just show these cars?.. Usually what I did was just had a show_cars.php that had all the mysql logic in there to pull the data and then pass the results to my showcars.html or showcars.php but now I am totally lost, I tried watching YouTube, went to cakephp.org . Still I am not able to understand. Also once I get the cars, how should I type the url (I am in locahost) to access this view?
Any help, will be much appreciated.
Try in your controller:
class CarsController extends AppController {
var $name = 'Cars';
//use model Car
var $uses = array("Car");
public function list() {
$carList = $this->Car->find("all");
//set to display for view list.ctp inside Car folder
$this->set("list_cars", $carList);
}
}
Now create list.ctp file inside Car folder (this is the view) and do:
print_r($list_cars); // this will show up array of rows from your table
For more info check: http://book.cakephp.org/

How do i restrict the list in a referenced model in ATK4

I have a model called Task defined like this (fields not relevent to question removed)
<?php
class Model_Task extends Model_Table {
public $entity_code='vscrum_task';
public $table_alias='tk';
function init(){
parent::init();
// debug causes error in Ajax in ATK v4.1.1
// $this->debug(true);
$this->addField('id')->system(true)->visible(false);
$this->addField('task_desc')->mandatory(true)->visible(true);
$this->addField('tasktype_id')->mandatory(true)->refModel('Model_TaskType');
$this->addField('team_id')->system(true)->visible(false);
and the refModel tasktype is defined like this (fields not relevent to question removed)
<?php
class Model_TaskType extends Model_Table {
public $entity_code='vscrum_tasktype';
public $table_alias='ty';
function init(){
parent::init();
$this->addField('id')->mandatory(true);
$this->addField('name')->mandatory(true);
$this->addField('team_id');
}
}
I have a CRUD which is based on task and is now (thanks to help from Jancha and Romans on stackoverflow) is working fine.
I want to limit the options in the drop down for TaskType to only those tasktypes defined for the user's team. I tried putting an addCondition in the TaskType Model referencing a session variable i had previously memorized
$this->addCondition('team_id',$p->api->recall('team_id'));
and also using a direct call to a value for the logged in use
$this->addCondition('team_id',$p->api->auth->get('team_id'));
but this results in showing the Tasktype fine in the Grid
but leaves it empty for both Edit and Add in the Ajax dialog.
If i remove the addCondition line from the TaskType Model, it shows all values in the list but i will always want this restricted to a subset.
As this is the referred Model and not the Model that the CRUD is based on, any suggestions on how i get this to work as expected ?
I tried Roman's suggestion of having a model which is the TaskType and a new model extended from that which is the TaskType_Team with the addCondition in it like this
class Model_TaskType_Team extends Model_TaskType {
function init(){
parent::init();
$this->addCondition('team_id',$p->api->auth->get('team_id'));
}
for which i needed to create a subdirectory undel Model called TaskType otherwise it didnt find the new Model but the end result is the same. I think this is related to another issue i previously had where the Ajax dialog loses access to $p->api and so doesnt display the restriction (and this is why it works fine for the grid on the same page as that isnt in an ajax dialog but i dont want to use a stickyGet to resolve this for security (dont want to be able to modify the URL to see other teams data) and session variables ($p->auth->memorise and $p->auth->recall) also dont seem work in this case - any further suggestions ?
Remember that you can extend your models like that. In fact, this is very often used in larger projects.
class Model_TaskType_Team extends Model_TaskType {
function init(){
parent::init();
$this->addCondition('team_id',$this->api->auth->get('team_id'));
}
}

Categories