Anyone else using DB-Schema-Validation for MVC projects? - php

Ok, inspired in part by CakePHP's Model Validation I created a project which uses a separate database schema file. I didn't like that in CakePHP the model file and the db-schema are combined in the same php file. I like having them separate.
All of my sql updates, inserts, and deletes are first passed by this schema. I wrote update() insert() delete() functions to do this validation automatically.
Why? Because I can accept a post from a visitor and send the un-checked data to my database without having to check it. My schema filters for innocent and not so innocent violations.
Here is an example of a database schema:
<?php
$schemas = array('database_name_hidden'=>array(
'assigned_weeks'=>array(
'id'=>array('id'),
'user_id'=>array('foreign_id','users'),
'week_number'=>array('posint'),
'year'=>array('posint'),
'unit_id'=>array('foreign_id','units'),
'claim_listing'=>array('posint'),
'created'=>array('created'),
'modified'=>array('modified'),
'resort_id'=>array('foreign_id','resorts','required'),
),
'trade_listings'=>array(
'id'=>array('id'),
'assigned_week_id'=>array('foreign_id', 'assigned_weeks','required'),
'listing_assigned_week_id'=>array('foreign_id', 'assigned_weeks'),
'opposite_id'=>array('numeric'),
'listed'=>array('bool'),
'prev_id'=>array('foreign_id','trade_listings'),
'next_id'=>array('foreign_id','trade_listings'),
'listing_email'=>array('email'),
'listing_description'=>array('text'),
'trade_confirmation_number'=>array('text'),
'external_resort_id'=>array('foreign_id','resorts'),
'external_unit_number'=>array('text','size'=>array(1,6)),
'external_start_time'=>array('time_future',),
'external_end_time'=>array('time_future'),
'admin_comment'=>array('text'),
'comment'=>array('text'),
'created'=>array('created'),
'creator'=>array('creator'),
'modified'=>array('modified'),
'modifier'=>array('modifier'),
'resort_id'=>array('foreign_id','resorts','required'),
),
);
?>
Anyone else doing something like this?

I am not sure I really understand the question, but speaking about DB, Validation, Schema, and PHP, I really like the ORM Framework called Doctrine.
(It's the default ORM stack of the PHP Framework symfony, btw ; but can be integrated quite easily with other frameworks -- I've already used it with Zend Framework, for instance)
It's website seems to be down right now (they've been experimenting some high-load-related troubles, those last weeks), but it provides classes/method to do validation of data, based on the YAML-files describing the schema, before inserting data into DB.
You might want to take a look at it...

Related

Where to put custom SQL code in CakePHP 3?

I'm building an application in CakePHP 3. It uses a number of legacy databases which are not built in the Cake conventions.
I do not want to use any of the ORM features Cake provides, as it's more tedious to set up all the relations than just write "Raw SQL". We are also not going to make any changes to the database structures, so the ORM is a non-starter. So I'm going to write raw SQL queries for everything.
However, I'm not sure where this code would be put. I've read https://book.cakephp.org/3.0/en/orm/database-basics.html#running-select-statements but it doesn't say where you actually put that code.
I don't want to put my queries in a controller ideally since that defeats the purpose of MVC.
All I really need is one Model where I can put all my queries in different functions and reference them in my Controller(s).
In Cake 2.x it was easy to just create a model under app/Model/ then load it (loadModel) where needed in controller(s). But with the new Cake 3.x Table and Entity spaces, I'm not sure how this fits in?
I've also read up on Modelless Forms but don't think they're right either. For example the initial page of the application shows a list of chemicals which is just a SELECT statement - it doesn't involve forms or user input at all at this stage.
Obviously there will also be situations where I need to pass data from a Controller to the Model, e.g. queries based on user input.
As mentioned in the comments, I would suggest to not ditch the ORM, it has so many benefits, you'll most probably regret it in the long run.
Setting up the tables shouldn't be a big deal, you could bake everything, and do the refactoring with for example an IDE that does the dirty work of renaming references and filenames, and then set up the rules and associations manually, which might be a little tedious, but overally pretty simple, as there shouldn't really be much more to configure with respect to the database schema, than the foreign keys, and possibly the association property names (which might require updating possible entities #property annotations too) - maybe here and there also conditions and stuff, but oh well.
That being said, for the sake of completeness, you can always create any logic you want, anywhere you want. CakePHP is just PHP, so you could simply create a class somewhere in say the Model namespace (which is a natural fit for model related logic), and use it like any other class wherever needed.
// src/Model/SomeModelRelatedClass.php
namespace App\Model;
class SomeModelRelatedClass
{
public function queryTheDatabase()
{
// ...
}
}
$inst = new \App\Model\SomeModelRelatedClass();
$results = $inst->queryTheDatabase();
See also
Cookbook > Database Access & ORM > Associations - Linking Tables Together > BelongsTo Associations

Easiest way to move data to other database

I have two versions of my blog: the 1st is written in PHP and uses MySQL, but the 2nd, the new one, is written in Python and uses Postgres.
My goal is to move data from one to other. Table names and schema changes.
My idea was to make ORM models for old site, and, using loop, get data using ORM and put it in new database, because I have ORM models for my new site too.
It would look something like:
old_articles = OldArticle.objects.all()
for old_article in old_articles:
new_article = NewArticle()
new_article.title = old_article.name
new_article.content = old_article.body
new_article.save()
ORM would easy abstract differences between the databases and, in my opinion, this could actually work! Or no, are there better ways?
If this migration will only be done once, I wouldn't go the ORM way. Exporting standards-compliant SQL dumps from MySQL is possible and the dumps could easily be imported into PostgreSQL. Once the data is in PostgreSQL, run your migration queries to make the scheme changes or use temporary 'import' tables and copy the data to the tables in the new scheme/lay-out.
Test all your migration queries and write a scenario containing all steps to take, which queries to run and in what order. Also include manual steps that need to be performed.
Once you're sure that the migration scenario is correct, and fully tested, put your old blog in 'maintainance mode' (sorry, we're offline, we'll be back soon) and do it for real!
Most important: test your scenario, validate the result and, take your time, you should never hurry these things!
There are a lot of libraries to do this sort of thing. I would stick to something that is already implemented and well tested. Here is a link to the postgres wiki that has a list of tools to do just this thing.
http://wiki.postgresql.org/wiki/Converting_from_other_Databases_to_PostgreSQL

php oop MVC design - proper architecture for an application to edit data

Now that I have read an awfull lot of posts, articles, questions and answers on OOP, MVC and design patterns, I still have questions on what is the best way to build what i want to build.
My little framework is build in an MVC fashion. It uses smarty as the viewer and I have a class set up as the controller that is called from the url.
Now where I think I get lost is in the model part. I might be mixing models and classes/objects to much (or to little).
Anyway an example. When the aim is to get a list of users that reside in my database:
the application is called by e.g. "users/list" The controller then runs the function list, that opens an instance of a class "user" and requests that class to retrieve a list from the table. once returned to the controller, the controller pushes it to the viewer by assigning the result set (an array) to the template and setting the template.
The user would then click on a line in the table that would tell the controler to start "user/edit" for example - which would in return create a form and fill that with the user data for me to edit.
so far so good.
right now i have all of that combined in one user class - so that class would have a function create, getMeAListOfUsers, update etc and properties like hairType and noseSize.
But proper oop design would want me to seperate "user" (with properties like, login name, big nose, curly hair) from "getme a list of users" what would feel more like a "user manager class".
If I would implement a user manager class, how should that look like then? should it be an object (can't really compare it to a real world thing) or should it be an class with just public functions so that it more or less looks like a set of functions.
Should it return an array of found records (like: array([0]=>array("firstname"=>"dirk", "lastname"=>"diggler")) or should it return an array of objects.
All of that is still a bit confusing to me, and I wonder if anyone can give me a little insight on how to do approach this the best way.
The level of abstraction you need for your processing and data (Business Logic) depends on your needs. For example for an application with Transaction Scripts (which probably is the case with your design), the class you describe that fetches and updates the data from the database sounds valid to me.
You can generalize things a bit more by using a Table Data Gateway, Row Data Gateway or Active Record even.
If you get the feeling that you then duplicate a lot of code in your transaction scripts, you might want to create your own Domain Model with a Data Mapper. However, I would not just blindly do this from the beginning because this needs much more code to get started. Also it's not wise to write a Data Mapper on your own but to use an existing component for that. Doctrine is such a component in PHP.
Another existing ORM (Object Relational Mapper) component is Propel which provides Active Records.
If you're just looking for a quick way to query your database, you might find NotORM inspiring.
You can find the Patterns listed in italics in
http://martinfowler.com/eaaCatalog/index.html
which lists all patterns in the book Patterns of Enterprise Application Architecture.
I'm not an expert at this but have recently done pretty much exactly the same thing. The way I set it up is that I have one class for several rows (Users) and one class for one row (User). The "several rows class" is basically just a collection of (static) functions and they are used to retrieve row(s) from a table, like so:
$fiveLatestUsers = Users::getByDate(5);
And that returns an array of User objects. Each User object then has methods for retrieving the fields in the table (like $user->getUsername() or $user->getEmail() etc). I used to just return an associative array but then you run into occasions where you want to modify the data before it is returned and that's where having a class with methods for each field makes a lot of sense.
Edit: The User object also have methods for updating and deleting the current row;
$user->setUsername('Gandalf');
$user->save();
$user->delete();
Another alternative to Doctrine and Propel is PHP Activerecords.
Doctrine and Propel are really mighty beasts. If you are doing a smaller project, I think you are better off with something lighter.
Also, when talking about third-party solutions there are a lot of MVC frameworks for PHP like: Kohana, Codeigniter, CakePHP, Zend (of course)...
All of them have their own ORM implementations, usually lighter alternatives.
For Kohana framework there is also Auto modeler which is supposedly very lightweight.
Personally I'm using Doctrine, but its a huge project. If I was doing something smaller I'd sooner go with a lighter alternative.

Need a simple ORM or DBAL for existing PHP app

I am working on extending an existing PHP application. Unfortunately for me, the existing app is a mess. It's all spaghetti code with raw mysql_* calls. Groan. No way that I am going to do that in the parts that I am extending.
So, I am looking for a simple ORM of DBAL that I can easily drop in and start using. Desired features:
It must work on an existing database schema. Preferably with minimal or no additional configuration. The existing database schema is the same quality as the existing PHP code (no sensible naming conventions, not normalised, etc.). I don't want to spend days converting the database schema manually into annotated object properties a la Doctrine 2.
It must be able to work alongside the existing raw mysql_* queries. I have no idea how hydrating ORMs like Doctrine 2 or Propel behave when scripts are manually manipulating the data in the database behind their backs, but I assume it's not pretty.
It must run on PHP 5.2.x. I'd love to use PHP 5.3 but I have zero interest in going over the existing 125K lines of spaghetti code mess to make sure it runs on PHP 5.3.
Relationships not required. In the few places I need to get to relational data, I'll be happy to call an extra find() or query() or whatever myself.
Bonus points if it has some trigger support (e.g. beforeSave, afterSave). Not a requirement, but just nice to have.
Edit: Someone put me out of my misery. I just found out that the 125K lines of spaghetti code also changes the database schema. E.g, add an extra option somewhere and a whole slew of ALTER TABLE statements start flying. I could probably fill a year's worth of TheDailyWTF with this codebase. So, one more requirement:
Must be able to cope with a changing database schema automatically (e.g. adding columns).
I have been looking at a few solutions, but I am unsure how well they would work given the requirements. Doctrine 2, RedBeanPhp and the like all require PHP 5.3, so they are out. There's a legacy version of RedBeanPhp for PHP 5.2.x but I don't know if it would work with a messy, existing database schema. NotORM looks okay for getting data out but I don't know if it can be configured for the existing database schema, and how you can easily put data back into the database.
Ideally I would like something simple. E.g:
$user = User::find($id);
$user->name = 'John Woo';
$user->save();
Or:
$articles = ORM::find('article')->where('date' => '2010-01-01');
foreach ($articles as $article) {
echo $article->name;
}
Any tips or even alternative solutions are welcome!
I use...
http://github.com/j4mie/idiorm/
it has an active record implementation too in the form of Paris.
With regard to your edit. Idiorm copes with changing schemas and the syntax almost exactly matches the type you want in your question.
How well did you look into Doctrine? I am using Doctrine 1.2 for these kind of things. Quite easy to setup, allows you to start off with an existing schema. It automatically figures out the relations between tables that have foreign key constraints.
It has extensive trigger and behaviour support, so the bonus points can be spent as well, and it has relational support as well, so your additional queries are not necessary. It has beautiful lazy loading, and it comes with a flexible query language (called DQL) that allows you to do almost exactly the same stuff that you can do in SQL in only a fraction of the effort.
Your example will look like this:
/* To just find one user */
$user = Doctrine::getTable('User')->findOneById($id);
/* Alternative - illustrating DQL */
$user = Doctrine_Query::create()
->from('User u')
->where('u.id = ?',array($id))
->fetchOne();
$user->name = 'John Woo';
$user->save();
It must be able to work alongside the existing raw mysql_* queries. I have no idea how hydrating ORMs like Doctrine 2 or Propel behave when scripts are manually manipulating the data in the database behind their backs, but I assume it's not pretty.
Well, that is technically impossible to auto-manage; a SQL database is simply not pushing back stuff to your ORM, so to update stuff that was changed in the background, you need to perform an additional query one way or the other. Fortunately, Doctrine makes this very easy for you:
/* #var User $user */
/* Change a user using some raw mysql queries in my spaghetti function */
$this->feedSpaghetti($user->id);
/* Reload changes from database */
$user->refresh();

Use of XML for Model class and structuring

I am currently working on a little application:
The structure follows in some way the MVC pattern.
For short it has the basic things, Models, Controllers etc.
Now I am sitting here and do not know whether :
1.
The SQL database is only managed by a model through methods the programmer gives him like: "Hey we have name record so we need a getName() method".
OR
2.
The model dynamically creates the whole database and methods, using a XML file, with which even a non-programmer can design a database.
And should the model class check every/a single request whether it is a valid request e.g. getName() won't work on the houses_tbl, and if it is not valid it does not perform the query, and sends back an error message instead?
I have absolutely no idea how to handle my model class, which structure it should follow and how much the programmer should have to put into a new model so it works as he wants it to work.
Major points:
perfomance (which way saves the most perfomance)
KISS (which way is simple enough, so a second team mate can understand my logic)
extendability (can I extend the structure)
Check these Data Source Architectural Patterns: Table Data Gateway, Row Data Gateway, Active Record, Data Mapper. For code examples to these patterns in PHP, you could check Zend_DB_*.
Which pattern you should pick depends on your application. If you are doing a simple CRUD application, you might want to use Row Data Gateway. If you are building an application with a lot of business logic from a certain domain, you will likely pick a different one.
Just remember that the M in MVC is not just the Persistence layer. The model is the heart of your application. Controller and View are just an end to your application. Further reading by Rob Allen and Matthew Weier O'Phinney.
As for your major points, I suggest to just stick to general established practises. UnitTest your code, write meaningful code and document it, favor aggregation over composition, capsule and separate concerns, code against an interface, refactor, etc.
Why not statically create the objects etc. during development from the database. i.e. use some Object-Relational-Mapping ?
That way you create your Person object from (say) the database schema. It creates a getName() accessor, and the rest of your code compiles against that. If you remove/rename the name field, then the generated code changes and consequently stuff doesn't compile. Catching these errors early will save a lot of grief.
This question details some PHP/ORM options. I confess I've not checked these to see if they're entirely what you want, but hopefully they should point you in the right direction.

Categories