CodeIgniter and DataMapper - php

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.

Related

Eloquent (WITHOUT Laravel) get data from table with dynamic name

I'm sure this is a totally simple question but for the life of me I'm stuck here- we're using Eloquent outside of Laravel due to PHP restrictions. I have a support ticket tracking app that I'm trying to update.
The data structure of this app is such that each ticket is assigned a UUID on submission and a table with that UUID as its name is generated and all changes to the ticket are tracked as new entries in that table.
Following some tutorials on Eloquent I got our models and controllers set up and working but for each one I see that I'm defining the table name in the model itself. IE our ticket model is
namespace Models;
use \Illuminate\Database\Eloquent\Model;
class Ticket extends Model {
protected $table = 'tickets';
protected $fillable = [table columns here];
}
and anything called in the tickets controller correctly and successfully reads and writes data to our tickets table.
So... my question is: how would I go about reading/writing/creating/deleting those previously mentioned UUID tables?
I've tried the built in table selector (ie- DB::table(uuid here) and DB::setTable(uuid here) but to no avail. I get Fatal error: Call to undefined method Models\Database::setTable()
What I'm after is a model/controller that I can reuse for ANY dynamically-named table.
You could create a generic model and dynamically set the table name, like this:
namespace Models;
use \Illuminate\Database\Eloquent\Model;
class FormerUUIDTicket extends Model {
protected $table = 'some_table';
protected $fillable = [table columns here];
}
class SomeController
{
public function someAction()
{
$uuid = $_POST['uuid_field']; //some uuid, the table name
$model = new FormerUUIDTicket;
$model->setTable($uuid);
return $model->get(); //do anything using eloquent with proper table
}
}
Make sure that you always set the table name before use, or it will fail. Don't use static function either, for the same reason.

Laravel Eloquent can't get simple hasMany relation working

Background
I have an internationalized DB that stores its strings for different languages like this:
products
id
price
product_translation
id
product_id
language_id
name
description
languages
id
name (e.g. 'English', 'German')
code (e.g. 'en', 'de')
With appropriate Models for each table (Product, ProductTranslation, Language). In my views I want to fetch a list of products like this:
// get first 20 products, list name and price.
#foreach(Product::take(20)->get() as $product)
{{$product->translations->name}} {{$product->price}}
#endforeach
Problem
My app will return product names according to what the current App::getLocale() is set to (i.e. en and de).
I'm just starting out with Laravel's Eloquent, I'm unsure how to specify the correct relationships (or if I'm actually doing it correctly at all).
My attempt
I have specified a OneToMany relationship in between Product and ProductTranslation:
class Product extends \Eloquent {
protected $with = ['translations'];
public function translations()
{
return $this->hasMany('ProductTranslation');
}
}
This works fine but will return all the translations (we only want the current locale).
I then specify a OneToOne relationship between ProductTranslation and Language:
class ProductTranslation extends \Eloquent {
protected $with = ['language'];
public function language()
{
return $this->hasOne('Language')
->where('code', App::getLocale());
}
}
I know this doesn't work and I am stumped at what to do next. Does anyone have a cleaner approach?
class ProductTranslation extends \Eloquent {
protected $with = ['language'];
public function language()
{
return $this->hasOne('Language');
}
}
In route or controller
ProductTranslation::language()->where('code', '=', App::getLocale())->get();
To keep this in the model do this
public static function getLocale()
{
return static::language()->where('code', '=', App::getLocale())->get();;
}
Call the function using ProductTranslation::getLocale()
Laravel has built-in system for translations and with a little work you can make it work with the database, however that is probably not what it was designed for.
You can't fetch the ones you want cause relationships are based on ids (foreign keys) and not for string constraints or similar.
In your view you could look into filtering out the ones that are not for the language code you wanted using filter(): http://laravel.com/docs/4.2/eloquent#collections
Or You could consider moving the translations to the proper place as hard-coded: http://laravel.com/docs/4.2/localization and if that is not possible you could look into fetching the translations from database still using the method described by that link. Eventually it just returns the array of the translations and does not care how did you build the array, hard-coded or from database.

multiple one to one relationships laravel

Okay so I'm building a pretty large application in Laravel. Users manage their own virtual soccer teams. I have a users table then I have a teams table with team specefic things like name, level,and arena, etc. For the arena though I decided to add a arenas table and then add a arena_id column in the teams table instead of just adding the arena name to the teams table.
so here is the basic relantionship:
User hasOne Team
Team hasOne User
Team hasOne Arena
Arena hasOne Team
so if I wanted to get the arena for a user I call the method
$user = User::with('team')->where('username', '=', $username)->first();
$user->team->arena->arena_name;
and everything works fine; however I feel there is a much cleaner or simpler way of doing this. Is there or is this fine for the aplication?
There is nothing wrong with the way you are doing it. That is a perfectly good way of doing it for your needs. However something that might help is creating a getArenaFromUsername() method in the User model. Your User model would look something like this:
<?php
class User extends \Eloquent {
protected $fillable = [];
public function getArenaFromUsername($username)
{
$user = User::with('team')->where('username', '=', $username)->first();
return $user->team->arena->arena_name;
}
}
So then to get the arena name from a controller you just do:
$user = new User;
$arena = $user->getArenaFromUsername($username);
-----------------------------------------OR-----------------------------------------------
Or use dependency injection by doing the following in your controller using the same method we just created in the model:
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
then to use it you can use one line in any method in your controller like so:
$this->user->getArenaFromUsername($username);
These are all different ways of abstracting your query to make it more reusable and cleaner to call in your controller. Don't be afraid to make public methods in your model to call.
A couple things.
You can eager load the sub-relationship like so:
User::with('team', 'team.arena')...
You can also create an accessor function (http://laravel.com/docs/eloquent#accessors-and-mutators) on your User model to make it a first-class property on the User object:
// accessed via $user->arena
public function getArenaAttribute {
return $this->team->arena;
}
// accessed via $user->arenaName
public function getArenaNameAttribute {
return $this->team->arena->arena_name;
}

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/

Loading data from Database with Atk4

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.

Categories