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/
Related
I want to know if there's a way to filter the result from ORM. I wish to create a custom method to my Model, for example, one to filter the output from my Data Base. Right now, only is possible to filter the data from the POST in a form to save them into a Data Base, but, I want the opposite.
If I have one field on my table called "identification" with the value "8-985-256", I want that value as "08-0985-00256" (don't worry about how to add the extra zeros, that part is easy).
Let's say that I have a custom method on my Model called "format_identification".
Then, I get the data using the ORM class like so:
$user = ORM::factory('user', 1);
I want to echo the identification, but, with the correct format:
echo $user->format_identification();
This should print "08-0985-00256". If I use the name of the field, that works, but, the format of the value not.
I hope you understand what I'm trying to do.
Thank you for your time.
Add public method to your Model_User file called format_identification like:
<?php defined('SYSPATH') or die('No direct access allowed.');
class Model_User extends ORM {
public function format_identification() {
$identification_value = $this->identification;
// Add the extra zeros to value
return $identification_value;
}
}
I think there is a better way to solve your problem:
class Model_User extends ORM {
public function __get($column) {
if($column=='identification'){
// Do your stuff
}
return parent::__get($column);
}
}
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.
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.
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'));
}
}
I have a controller/model for projects. so this controls the projects model, etc, etc. I have a homepage which is being controlled by the pages_controller. I want to show a list of projects on the homepage. Is it as easy as doing:
function index() {
$this->set('projects', $this->Project->find('all'));
}
I'm guessing not as I'm getting:
Undefined property: PagesController::$Project
Can someone steer me in the right direction please,
Jonesy
You must load every model in the controller class by variable $uses, for example:
var $uses = array('Project');
or in action use method
$this->loadModel('Project');
In my opinion the proper way to do this is add a function to your current model which instantiates the other model and returns the needed data.
Here's an example which returns data from the Project model in a model called Example and calls the data in the Example controller:
Using Project Model inside Example Model:
<?php
/* Example Model */
App::uses('Project', 'Model');
class Example extends AppModel {
public function allProjects() {
$projectModel = new Project();
$projects = $projectModel->find('all');
return $projects;
}
}
Returning that data in Example Controller
// once inside your correct view function just do:
$projects = $this->Example->allProjects();
$this->set('projects', $projects);
In the Example view
<?php
// Now assuming you're in the .ctp template associated with
// your view function which used: $projects = $this->Example->allProjects();
// you should be able to access the var: $projects
// For example:
print_r($projects['Project']);
Why is this "better" practice than loading both models into your controller? Well, the Project model is inherited by the Example model, so Project data now becomes part of the Example model scope. (What this means on the database side of things is the 2 tables are joined using SQL JOIN clauses).
Or as the manual says:
One of the most powerful features of CakePHP is the ability to link relational mapping provided by the model. In CakePHP, the links between models are handled through associations.
Defining relations between different objects in your application should be a natural process. For example: in a recipe database, a recipe may have many reviews, reviews have a single author, and authors may have many recipes. Defining the way these relations work allows you to access your data in an intuitive and powerful way. (source)
For me it's more reasonable to use requestAction. This way the logic is wrapped in the controller.
In example:
//in your controller Projects:
class ProjectsController extends AppController {
function dashboard(){
$this->set('projects', $this->Project->find('all'));
}
$this->render('dashboard');
}
Bear in mind that you need to create dashboard.ctp in /app/views/projects of course.
In the Page's dashboard view (probably /app/views/pages/dashboard.ctp) add:
echo $this->requestAction(array('controller'=>'projects', 'action'=>'dashboard'));
This way the logic will remain in the project's controller. Of course you can request /projects/index, but the handling of the pagination will be more complicated.
more about requestAction(). but bear in mind that you need to use it carefully. It could slow down your application.