Yii - Foreign key - Access Data - php

I' m just getting into Yii and am finding it a little confusing (at least compared to Cake or CI). Here's a couple things I'm wondering about:
1) If I have an 'add station' form (using a Station model). In the form, there will be a drop down list of 'Companies' (from Company Model). Station belongsTo Company (Station has a foreign key of company_id).
How do I go about generating the drop down list? Should the Php code used to pull the data be stored in the model, or should it just be a line in the form?
2) I also have the following database tables:
station
- id
- location_id
location
- id
- state_id
- city_id
state
- id
- state
city
- id
- city
For right now, in the same form as above, I wanted to have a 'Location' field, and then 2 drop downs for city and state. Whatever the user chooses, would then be stored in the location table as foreign key pairs. How would I go about doing that?

1) Look at my answer to this question for tips about the downdown (the key is CHtml::listData):
Does CDbcommand method queryAll() in yii return indexed entries only?
2) Is location just a relation table between state and city? Then just do a MANY_MANY relation() in your City and State models. The AdvancedAR extension makes life a little easier for managing MANY_MANY releationships.
Otherwise, just set up a Model for each of your tables, and add the appropriate relations() between them. Then in your form post action, create a new Location and set the state_id and city_id, and save() it.

Related

Yii framework: populate data from related table

I have two tables Customer and Location. Location has fields id, country, zone, state and city. Customer table has a foreign key location_id.
While creating a customer, I need to display dropdowns for country, zone, state and city on the create customer form and the values in the dropdown should be populated from the location table. When a user selects these fields, the corresponding location id should be saved in the location_id field of the Customer table.
While updating a customer, values for country, zone, state and city dropdowns should be populated in the form based on the location_id foreign key. Any changes in the values of these dropdowns should be saved as location_id foreign key.
Any inputs or pointers to any existing posts/articles will be of great help.
Any inputs or pointers to any existing posts/articles will be of great help.
OK, some hints
1.
values in the dropdown should be populated from the location table.
For this, i think, you need to get acquainted with the post on dependent dropdowns in yii for populating one dropdown when choosing from another one.
2.
When a user selects these fields, the corresponding location id should be saved in the location_id field of the Customer table.
For this you might need to do some ajax call upon dropdown/textField selection/changing. You might do this by external js function but i recommend the Select2 with Yii.
For example here on item change in Select2 the ajax call is performed to the controller eventsPerformance and action save with data as serialization of the whole form js:$("#performance-form").serialize():
$this->widget('ext.select2.ESelect2',array(
'attribute' => 'subStatus',
'model'=>$performance,
'data'=>$subStatusArray,
'htmlOptions'=>array(
'onChange'=>CHtml::ajax(array('type'=>'POST',
'url'=>'eventsPerformance/save',
'data'=>'js:$("#performance-form").serialize()',)),
),
));
Feel free to ask if some more help needed.
Here is nothing special. Just use methods whose name starts with active and your dropdowns will preselect right option. I believe you are using Gii to create your CRUD operations. So you need only to add Location dropdows in users update / create view. E.g.
$user = User::model()->findByPk(99);
$locations = Location::model()->findAll();
$locationList = CHtml::listData($locations, 'id', 'country');
echo CHtml::activeDropDownList($user, 'location_id', $locationList);
But I think your description is not correct because in your Location table one ID identify whole combination of country-zone-state-city, i.e.:
1 | USA | NULL | Arizona | Phoenix
2 | ... | ...
If you need drop-downs for every of them, you need to create separate DB tables.
// countries
id | title
// cities
id | country_id | title

solution how to save/update data into few tables(models) in Yii Active Record

I am new in Yii and Active Record and I want to ask you some solution how to do some things.
I have 3 tables in db: car - info about cars, car_model - info about models of the cars, car__car_model - relation table, which binds this 2 tables in Many_to_Many relation - it has fileds - id_car,id_model,is_hidden,orderby.
Task is to show some (till 5) similar car models on car page.
i have a big form in which i enter information about car (car table), and i have 5 html blocks (5 rows in db in table car_model)with some input fields. Each block it is a row in car_model table - it contain fields: id_model - (primary key in car_model table), and some info fields which in this car_model table. Records in car_model table are always already exist, user just choose model_id in form and update this row and by checkbox he can do this relation hidden (is_hidden field) In other words, user just updates car_model table records and binds them to car table (car__car_model table).
My question is following: how can i implement it, using activeFields and correct using Active Record ideology. Have any ideas?
I set up relation with this tables - and display this data with no problem - saving/updating data i implement using static content (Chtml) - set up static names for this html fields and in Controller i foreach this fields - but i think it is not correct
Image of this form: http://programmer.pp.ua/out/1.png
Tables:
car: id,other fields
car_model: id,other text fields which need to update
car__car_model:id_car,id_model,is_hidden(checkbox in form),orderby**
Relations in Car Model:
'carAdviceModel'=> array(self::HAS_MANY,'CarCarModel', 'id_car'),
'adviceModels' => array(self::HAS_MANY, 'CarModel', 'id_model', 'through' => 'carAdviceModel'),
Thanks you in advance
Sorry for my bad English - it is my first question here.
Ok, this is a bit odd, but maybe you want to send three models to the view, each an array of 5 models. The models can be brand new, or some can start out populated. Search the Yii definitive guide for 'Collecting Tabular Input'. It will give you everything you need to know about how to do this. You can validate all the models. You can also save all the models without having to validate them all again by using save(false).

Advice on database design for portfolio website

So I'm a visual designer type guy who has learned a respectable amount of PHP and a little SQL.
I am putting together a personal multimedia portfolio site. I'm using CI and loving it. The problem is I don't know squat about DB design and I keep rewriting (and breaking) my tables. Here is what I need.
I have a table to store the projects:
I want to do fulltext searcheson titles and descriptions so I think this needs to be MyISAM
PROJECTS
id
name (admin-only human readable)
title (headline for visitors to read)
description
date (the date the project was finished)
posted (timestamp when the project was posted)
Then I need tags:
I think I've figured this out. from researching.
TAGS
tag_id
tag_name
PROJECT_TAGS
project_id (foreign key PROJECTS TABLE)
tag_id (foreign key TAGS TABLE)
Here is the problem I have FOUR media types; Photo Albums, Flash Apps, Print Pieces, and Website Designs. no project can be of two types because (with one exception) they all require different logic to be displayed in the view. I am not sure whether to put the media type in the project table and join directly to the types table or use an intermediate table to define the relationships like the tags. I also thinking about parent-types/sub-types i.e.; Blogs, Projects - Flash, Projects - Web. I would really appreciate some direction.
Also maybe some help on how to efficiently query for the projects with the given solution.
The first think to address is your database engine, MyISAM. The database engine is how MySQL stores the data. For more information regarding MyISAM you can view: http://dev.mysql.com/doc/refman/5.0/en/myisam-storage-engine.html. If you want to have referential integrity (which is recommended), you want your database engine to be InnoDB (http://dev.mysql.com/doc/refman/5.0/en/innodb-storage-engine.html). InnoDB allows you to create foreign keys and enforce that foreign key relationship (I found out the hard way the MyISAM does not). MyISAM is the default engine for MySQL databases. If you are using phpMyAdmin (which is a highly recommended tool for MySQL and PHP development), you can easily change the engine type of the database (See: http://www.electrictoolbox.com/mysql-change-table-storage-engine/).
With that said, searches or queries can be done in both MyISAM and InnoDB database engines. You can also index the columns to make search queries (SELECT statements) faster, but the trade off will be that INSERT statements will take longer. If you database is not huge (i.e. millions of records), you shouldn't see a noticeable difference though.
In terms of your design, there are several things to address. The first thing to understand is an entity relationship diagram or an ERD. This is a diagram of your tables and their corresponding relationships.
There are several types of relationships that can exist: a one-to-one relationship, a one-to-many relationship, a many-to-many relationship, and a hierarchical or recursive relationship . A many-to-many relationship is the most complicated and cannot be produced directly within the database and must be resolved with an intermittent table (I will explain further with an example).
A one-to-one relationship is straightforward. An example of this is if you have an employee table with a list of all employees and a salary table with a list of all salaries. One employee can only have one salary and one salary can only belong to one employee.
With that being said, another element to add to the mix is cardinality. Cardinality refers to whether or not the relationship may exist or must exist. In the previous example of an employee, there has to be a relationship between the salary and the employee (or else the employee may not be paid). This the relationship is read as, an employee must have one and only one salary and a salary may or may not have one and only one employee (as a salary can exist without belonging to an employee).
The phrases "one and only one" refers to it being a one-to-one relationship. The phrases "must" and "may or may not" referring to a relationship requiring to exist or not being required. This translates into the design as my foreign key of salary id in the employee table cannot be null and in the salary table there is no foreign key referencing the employee.
EMPLOYEE
id PRIMARY KEY
name VARCHAR(100)
salary_id NOT NULL UNIQUE
SALARY
id PRIMARY KEY
amount INTEGER NOT NULL
The one-to-many relationship is defined as the potential of having more than one. For example, relating to your portfolio, a client may have one or more projects. Thus the foreign key field in the projects table client_id cannot be unique as it may be repeated.
The many-to-many relationship is defined where more than one can both ways. For example, as you have correctly shown, projects may have one or more tags and tags may assigned to one or more projects. Thus, you need the PROJECT_TAGS table to resolve that many-to-many.
In regards to addressing your question directly, you will want to create a separate media type table and if any potential exists whatsoever where a project is can be associated to multiple types, you would want to have an intermittent table and could add a field to the project_media_type table called primary_type which would allow you to distinguish the project type as primarily that media type although it could fall under other categories if you were to filter by category.
This brings me to recursive relationships. Because you have the potential to have a recursive relationship or media_types you will want to add a field called parent_id. You would add a foreign key index to parent_id referencing the id of the media_type table. It must allow nulls as all of your top level parent media_types will have a null value for parent_id. Thus to select all parent media_types you could use:
SELECT * FROM media_type WHERE parent_id IS NULL
Then, to get the children you loop through each of the parents and could use the following query:
SELECT * FROM media_type WHERE parent_id = {$media_type_row->id}
This would need to be in a recursive function so you loop until there are no more children. An example of this using PHP related to hierarchical categories can be viewed at recursive function category database.
I hope this helps and know it's a lot but essentially, I tried to highlight a whole semester of database design and modeling. If you need any more information, I can attach an example ERD as well.
Another posibble idea is to add columns to projects table that would satisfy all media types needs and then while editting data you will use only certain columns needed for given media type.
That would be more database efficient (less joins).
If your media types are not very different in columns you need I would choose that aproach.
If they differ a lot, I would choose #cosmicsafari recommendation.
Why don't you take whats common to all and put that in a table & have the specific stuff in tables themelves, that way you can search through all the titles & descriptions in one.
Basic Table
- ID int
- Name varchar()
- Title varchar()
etc
Blogs
-ID int (just an auto_increment key)
-basicID int (this matches the id of the item in the basic table)
etc
Have one for each media type. That way you can do a search on all the descriptions & titles at the one time and load the appropriate data when the person clicked through the link from a search page. (I assume thats the sort of functionality you mean when you say you want to be able to let people search.)

Should I Populate Country/Region Names at DB or Application Level?

I'm going through a tough decision (at least for me)...
My website would have a list of countries in dropdown list and list of cities based on chosen country. I decided to populate the list at db level as:
CREATE TABLE Country
(
countryID - PK
countryName - FK
);
CREATE TABLE City
(
cityID - PK
countryID - FK
cityName
);
CREATE TABLE Register
(
registerID - PK
cityID - FK
)
However, this can add some complexity in php back-end coding when inserting record into registration as well as retrieving record from countries/cities, because on registration form user will city name on droplist, user won't see cityID, so i will have to fetch cityID based on chosen cityName, etc. Therefore, i said why do i just put the countries and cities list at application level in fixed drop down list and make register table look as:
CREATE TABLE Register
(
registerID - PK
cityName
)
cityName gets inserted directly without us having to join or call multiple tables and get specific ID for a city so we can then grab the cityName, etc...
I will only normalize in crucial tables such as making relationships between Member and Post/Thread tables. A member can have multiple threads one-to-many relationship. Otherwise, things that relate to multi-value as countries list won't be considered at DB level for simplicity and rap sake.
What do you think? Advice ...
The nature of the data should drive the database model. Not your front end issues.
Why not load your cities into a drop down list? Set the display text=cityName. Set the value=cityID.
Not sure I understand the text of your question completely, but to answer the title of your question, I would keep country names in the database. Countries/Cities do change their names from time-to-time.
I would suggest defining XML with the country name/id as the element and city names as the child elements. It makes it edit/read the xml data. I'm not sure whether you would like to consider this.

How to make cakePHP retrieve the data represented by a foreign key?

I have a simple database with multiple tables. I can't figure out how to make cakePHP display the values associated with a foreign key in an index view. Or create a view where the fields of my choice (the ones that make sense to users like location name - not location_id can be updated or viewed on a single page).
I have created an example at http://lovecats.cakeapp.com that illustrate the question. If you look at the page and click the "list cats", you will notice that it shows the location_id field from the locations table. You will also notice that when you click "add cats", you must choose a location_id from the locations table. This is the automagic way that cakePHP builds the app. I want this to be the field location_name.
The database is setup so that the table cats has a foreign key called location_id that has a relationship to a table called locations.
This is my problem: I want these pages to display the location_name instead of the location_id. If you want to login to the application, you can go to http://cakeapp.com/sqldesigners/sql/lovecats and the password 'password' to look at the db relationships, etc.
How do I have a page that shows the fields that I want? And is it possible to create a page that updates fields from all of the tables at once?
This is the slice of cake that I have been trying to figure out and this would REALLY get me over a hump. You can download the app and sql from the above url.
Hah, you figured it out correctly! Cake uses the $displayField variable do decide what to..well, display.
If I remember correctly, by default, cake looks for 'title' and 'name' fields, and if those two are not available, it will simply show your primary key field. Luckily, you can override it the way you figured out yourself ;)
I guess you need to echo $cat['Location']['location_name'] in your view.

Categories