Yii framework and multi-language content - php

I've inherited a medium-size website written with a custom (small) php framework. I want to switch to the yii framework but first I need to find a solution for the following problem : the site is basically a series of courses and exercices that are available in multiple languages. In fact all the content is available in multiple languages.
The users can select their preferred language and the localized content is retrieved from the database.
Database organisation :
table exercises with id and language-free columns
table exercises_strings with exerciseId, sLanguage and sContent
How can this be easily integrated with the "Post::model()->findAll()" yii's way of retrieving data from the DB ?
Should I write my custom derived class of CModel that would retrieve language preference from the IUserIdentity class and adapt the query ?
Is there some code arround that I could look at ?

Should I write my custom derived class of CModel that would retrieve language preference from the IUserIdentity class and adapt the query ?
I don't think, you need to do that. There are different ways:
1.)
You can use the cdbcriteria to set the criteria (for example the where clause) after creation an instance of the object and before running findAll
http://www.yiiframework.com/doc/guide/1.1/en/database.ar (look at the end of the 2nd quarter of the page)
2.)
An other way is to overwrite the findAll inside your model:
public function findAll($condition='',$params=array())
{ $condition["criteria"]->compare ....
return parent::findAll($condition,$params);
}
3.)
You also can use the onBeforFind trigger http://www.yiiframework.com/doc/api/1.1/CActiveRecord#onBeforeFind-detail, which fires before (every) the findAll search
i would prefer that 1st or 2nd idea.

Related

MVC - should a model interact with (an)other model(s)? Or the controller should do that?

Apologise if it sounds a dumb question, but if I never ask, I'll never learn. I have been recently working with the MVC implementing pattern, and I'm still learning stuff, so please be patient with me.
I've been recently working on a multi-languages website that uses a custom MVC framework for a client. In some places I'd need to display some information from more than one table, like an article (from the articles table), the name of the languages that this article is written in (from the languages table), the languages that this article is not yet written in (from the languages table also), and the author (from the authors table).
I have a model for the articles, a model for the languages, and a model for the authors, and each has its own controller.
If I only query articles tables only or the authors tables only, there is no issue, but the confusion comes when I want to display information from this different tables into a single view.
How I should do that?
Instantiate a language model object and an author model object in the article controller and call their related functions to get the data and then combine/merge their data with the data from the article model (all in the article controller as mentioned)?
Instantiate the language model and the author model in the article model and call their functions to get their data, then combine/merge the their data with the data from the article model itself?
Do a join or nested select in the article model to get the data from multiple tables, and not interact with any other model, even if that mean some queries will be repeated in more than on model?
Another approach?
What is the best way do that?
This can be done in several ways:
- Create a view (a virtual table of MySQL) which using join, nested select or whatever you want to achieve all necessary information and create a model on top of this view in MVC (this model can only retrieve info from the view not alter it, however)
- Use repository pattern. A repository wrap many models and you can implement business logic (which might be CRUD on multiple models/tables) here. The controller simply use the repository instead of model.
In summary the model, repository should wrapping all the business logic of its own never let the controller do these stuff.
Regards,

How to reuse mysql CRUD in PHP?

I have an idea, but I don't know how to implement it. Let's say there are various tables in our db and each table may have different fields. I need to create a parent class which has some common database functions for CRUD (create, read, update and delete). (It might take the table name as an argument). We can re-use all these CRUD methods in our sub-classes. We don't have to specify field names.
class AllCRUD{
protected function select (){
// select * from ..... comes here
}
protected function create (){
// select * from ..... comes here
}
// update and delete comes then
}
class Users extends ALLCRUD{
protected $table_name="users";
//Mechanism to iterate through field names
}
//create the object
$user=new Users();
$user->select()
//This will select all users from users table
//Likewise we must be able to perform insert, update and delete on any subclass
I believe you guys may have understood what I am trying to say
I need someone's help to implement this concept.
If there is a blog or something that I can read, please post the link.
(I searched, but did not find something which fits for my purpose)
Thanks
Recently I was doing exactly the same problem
And extended child EventModel
In my example, Event Model inheritance AbstractCRUDModel and implement this logic.
For example:
//create model object
$eventModel = new EventModel();
// fetching from database
$event = $eventModel->read(1);
You can refer to a very early version of a lightweight simple ORM framework with just few files and easy to use and understand.
PHP Tiny Framework:
https://github.com/sushilman/ptf
It does not provide enough security by itself (like: against SQL injection ) which you will have to take care of by yourself.
If your project is large enough and if you want other features of a framework, then I would recommend you to use one of several available PHP frameworks : Zend, CodeIgniter, Symphony and so on.

Codeigniter set sidewide database filter

I want to have a filter on my site so they only see what they want to see. For example a user enables a location filter and selects that he only wants to see USA profiles. I save the filters in an different database table then userdata and in json.
This sounds quite simple but it isn't :) I want to prevent that I have to paste a long group of code to almost every model function.
Is it for example possible that I create 1 time a function with json_decode and foreaches to generate the right active record (where) codes and insert it in a model function with for example $this->enableFilters(); ? I use multiple models so I actually don't want to add a function to every model.
Is this all possible?
One option is to extend the core model class to include a common function. Look at the Extending Native Libraries part on the manual.
So, for example, you will create a MY_Model to extend CI_Model and all your models can extend MY_Model. Your common functions can be on MY_Model that is available to all child classes.

Zend_Db_Table joined queries vs database view

I was wondering what would be the best practices and the best way to achieve consistency while accessing your database data :
Current structure goes as follow
Data Access --> Business Logic --> Controller --> View
My data access layer is composed of a Zend_Db_Table, Zend_Db_TableRowset and a Zend_Db_TableRow for each table.
My business logic is stored in the model named based on a the table
Example of problematic query :
I want to get a specific user based on his username. To do so I have a user table and a role table (role.id is referred as role_id in the user table).
I don't want to have to use the findDependentRowset that will run additionnal queries for each row that get returned. (will get problematic in data grid that display the data as many rows can be returned).
The choices I have (getName() is used in this example to simplify, but it can be any processing) :
Make a custom join on the role table in the user table which will return an index array composed of associative array. In that case I can't call my getName() function defined in my Model_DbTable_User to build the name (first name + middle + last name). Even if I "cast" my array to a Zend_Db_Table_Rowset (or my custom table_rowset) I can't access my custom class method since I get a generic Zend_Db_Table_Row object.
Make a custom join but build the name using CONCAT() in my query at runtime, I still get an array but the name is build so I don't need the getName() method. But if I have specific logic to apply i'm stuck.
Make a view joining user and role tables in my database and create a new set of Zend_DbTable, Zend_DbTableRowset and Zend_DbTableRow. This way I can have specific logic in my database stack.
An ORM (propel or doctrine (1 or 2)), I have no experience with these, I might need more informations to make the right choice.
My alternate goal is to be sure I get consistency in my data structures
ie:
array all the way :
array(
array(row1),
array(row2)
);
object all the way
$row = $rowset->current();
$row->field;
Creating a view should be done regardless because it complements the other ideas more than it competes with them. The view will:
Abstract the database to something that you can more easily work with.
Be faster because there's no parsing.
Be accessible outside of your application.
Once you've created the views, you can choose a strategy that best solves the problem. If you're creating a form that represents a single entity, then an ORM is probably a good fit. But if you're displaying large lists of data or generating reports that contain many entities then using a declarative language like SQL is probably easier and would perform better.

Calculating data fom DB with CodeIgniter

i use a simple PHP framework (like Codeigniter) without ORM.
I have a database with product data (prices, sells, page in catalog...).
And i want to calculate the conversion per page and the conversion per product.
The calculations with SQL are not a problem, but i don't really know where to put them in.
Should I create a "Page" and a "Products" model with methods like
"Page::getConversions($page_id)" or a "ConversionPerPage" and a "ConversionPerProduct" model, or sth. completely other.
I think that the best model classes are to have two classes for each table - one for object and plural for static classes.
For example: if you have Page table then you should have Page and Pages classes.
First one will allow you to have one object from table and you can do the regular methods on it like:
$page = new Page($page_id);
$conversions = $page->getConversions();
$page_number = $page->getNumberInBook(); etc
On the other hand in Pages class you can put the methods that will (usually) return the array of Page and those methods will usually be static:
$pages = Pages::getPagesByCatalog($catalog_id);
This way you will have real OOP and code complete with full model MVC implementation.
I hope that this model hierarchy will help you. We are using it in our office and it showed to be really good.
All the best!
Basically, you create models based on the database schema. So, first option is preferred. Moreover, it should be instance method instead of class method (the object is then identified from the $page_id).
Presumably you are going to have Page and Product models anyway so I would add the getConversions() function to those.

Categories