php-activerecord
ActiveRecord implementation for PHP
PHP ActiveRecord - An easy to use ORM for PHP an easy to use orm for php using the activerecord pattern.
I'm using php-activerecord for a short while now and i absolutely love it. Php-activerecord is an open source ORM library based on the ActiveRecord pattern. However, i recently tried to use it in combination with a websocket application based on Wrench.
This works perfectly but to start the script the application has to run as a daemon on linux in order to make the websockets always availeble. After a short while of not using the application and then trying to use it again it throws some database exceptions:
At first it gives a warning:
PHP Warning: Error while sending QUERY packet. PID=XXXXX in /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php on line 322
Then it throws a fatal error:
PHP Fatal error: Uncaught exception 'ActiveRecord\DatabaseException' with message 'exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2006 MySQL server has gone away' in /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php:322
Stack trace:
#0 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php(322): PDOStatement->execute(Array)
#1 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Table.php(218): ActiveRecord\Connection->query('SELECT * FROM ...', Array)
#2 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Table.php(209): ActiveRecord\Table->find_by_sql('SELECT * FROM `...', Array, false, NULL)
#3 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Model.php(1567): ActiveRecord\Table->find(Array)
#4 in /home/user/domains/example.com/public_html/vendor/php-activerecord/lib/Connection.php on line 325
It seems like php-activerecord is keeping the mysql connection open all the time that the websocket server is running, this ofcourse should not be a problem if it then automatically tried to reconnect and run the query again. But it doens't.
I've read something about setting MYSQL_OPT_RECONNECT
. But i'm not sure if that works or how to set that option using php-activerecord. Does anybody here have some experience in this area?
Edit: Here are my global timeout config variables
VARIABLE_NAME VARIABLE_VALUE
DELAYED_INSERT_TIMEOUT 300
WAIT_TIMEOUT 28800
CONNECT_TIMEOUT 10
LOCK_WAIT_TIMEOUT 31536000
INNODB_ROLLBACK_ON_TIMEOUT OFF
THREAD_POOL_IDLE_TIMEOUT 60
NET_WRITE_TIMEOUT 60
INNODB_LOCK_WAIT_TIMEOUT 50
INTERACTIVE_TIMEOUT 28800
DEADLOCK_TIMEOUT_LONG 50000000
SLAVE_NET_TIMEOUT 3600
DEADLOCK_TIMEOUT_SHORT 10000
NET_READ_TIMEOUT 30
Source: (StackOverflow)
I'm picking up PHP Active Record and dealing with associations. I have two related objects using a "Has_Many" and "Belongs_to" (parent/child) and trying to create a child record when creating a new parent record (in this case creating a "skin" for my "unit").
class Unit extends ActiveRecord\Model
{
static $has_many = array(
array('skins')
);
}
class Skin extends ActiveRecord\Model
{
static $belongs_to = array(
array('unit')
);
}
I've found both of these threads here:
http://www.phpactiverecord.org/boards/4/topics/153
Activerecord-association: create new object (find class)
So I my code currently looks like:
$unit = new Unit();
$unit->name = 'somename';
$unit->description = 'somedescription';
$skinArray = array('name' => $unit->name.' Default Skin');
$unit->create_skins($skinArray);
$unit->save();
The code above is not associating the new skin to the unit in the database or in code though it /is/ placing a new skin record in the database (with a unit_id of NULL). Using "build_skins" doesn't put a Skin record in the database.
I was hoping there was a way to add a "child" to the parent model via the model itself as some other ORM's do. The only way I can do this is to do it explicitly:
$unit = new Unit();
$skin = new Skin();
$unit->name = 'somename';
$unit->description = 'somedescription';
$unit->save();
$skin->unit_id = $unit->id;
$skin->name = $unit->name.' Default Skin';
$skin->save();
Perhaps that is the way it is supposed to be done in PHP ActiveRecord and my expectations are wrong. But I was hoping for a way to do it through the objects that didn't require saving the Parent to the DB with an explicit call first. For example the "Recess" PHP framework would have a simple call on the unit like such: $unit->addSkin($skin);
Source: (StackOverflow)
I am working with an app which uses phpActiveRecord
and mySQL to pull in data from a sensor network and plot it onto a number of flot.js graphs on the client.
There are several timeframes the user can chose between to affect the range of data the graphs display. 2hrs, 24hrs, 3 days and 1 week.
The sensors post to the database every 60 seconds, so when plotting the graphs, the query pulls in all rows between now and DATE_SUB(CUR_DATE - INTERVAL ? DAY)
where ? is either 1, 3 or 7 etc.
However this results in a massive number of rows being returned (60,000 + for the full week!)
and is causing huge delays and server errors.
I know I can just massively increase the max memory available for queries in the php.ini
file, but this is hardly a good solution, and doesn't solve the issue of speed.
My question is, is there a way I can easily select only every second or third row from the required date range depending on the length of the interval the user wishes to view?
In C or Java I would do something like a modulo select to return alternate rows but I cannot think of a way to do this in the current framework.
Any ideas would be appreciated. Thanks.
Source: (StackOverflow)
What would be a good way to search a field, ignoring spaces in the search term AND the field?
Example:
SELECT *
FROM tablename
WHERE NOSPACES(fieldname) LIKE '%{search term with spaces removed}%'
Real-world example:
My client has a website selling long block engines. However, they often get people searching on their site for "cat 3306 longblock" (instead of "cat 3306 long block"). We need the "long block" engines to show up when "longblock" is searched.
Note: it probably doesn't matter for purposes of this question, but this website is built using PHP 5.3 and phpActiverecord.
Source: (StackOverflow)
I have a database that I want to pull only certain rows that have dates in specified ranges. I'm not sure how to do this properly in active record. Right now it looks like I'm running a standard mysql query inside of an active record query. I hope this gives you the idea of what I'm looking for.
I would also like to be able to get rows with anything before today, including today and 3 days in the future.
$query = $this->db->query("SELECT * FROM 'topics_list' . 'topic date' WHERE DATE(order_datetime) BETWEEN '2012-10-01' AND '2012-10-3'");
Source: (StackOverflow)
I would like to have a simple a method, that can give back PHP Activerecord results as simple/associative arrays, not an array of ActiveRecord Objects.
In Ruby I believe this is done perhaps with .map()
method. (I am not a Ruby guy...)
What I want is a simple method call, like toArray()
in Zend_DB_Table, not a foreach, or something like that, but I can't seem to find it in their docs.
In PHP ActiveRecord getting a result is really easy:
$settings = SystemSettings::all();
But it gives back something like this:
[0] => SystemSettings Object
(
[errors] =>
[attributes:ActiveRecord\Model:private] => Array
(
[param] => author
[value] => Hawle
)
[__dirty:ActiveRecord\Model:private] => Array
(
)
[__readonly:ActiveRecord\Model:private] =>
[__relationships:ActiveRecord\Model:private] => Array
(
)
[__new_record:ActiveRecord\Model:private] =>
)
[1] => SystemSettings Object
(
[errors] =>
[attributes:ActiveRecord\Model:private] => Array
(
[param] => base_url
[value] => example.com
)
[__dirty:ActiveRecord\Model:private] => Array
(
)
[__readonly:ActiveRecord\Model:private] =>
[__relationships:ActiveRecord\Model:private] => Array
(
)
[__new_record:ActiveRecord\Model:private] =>
)
While this is really great in many cases, here, I would just like to have a simple array, like this:
Array
(
[author] => Hawle
[base_url] => example.com
)
Source: (StackOverflow)
In my controller I am setting the following variables and passing them to the Twig template:
$data = $model::all(); // returns object [phpactiverecord]
$fields = getFields(); // returns associative array
In my template, I am attempting the access them like this:
{% block rows %}
{% for row in data %}
<tr>
{% for field in fields %}
<td>{{ row[field.name] }}</td>
{% endfor %}
</tr>
{% endfor %}
{% endblock %}
In this scenario, $fields is defined as:
Array
(
[0] => Array
(
[name] => id
[display] => Id
)
[1] => Array
(
[name] => name
[display] => Name
)
)
and $data is an array of phpactiverecord objects.
As written above, nothing is output for row[field.name].
Here are the results I see if I change row[field.name]:
row.name -> outputs Value I would expect from row[field.name]
field.name -> outputs "name"
row['name'] -> outputs nothing
row[field.name] -> outputs nothing
According to the Twig site: You can use a dot (.) to access attributes of a variable (methods or properties of a PHP object, or items of a PHP array), or the so-called “subscript” syntax ([]):
Any ideas on getting this to work?
Source: (StackOverflow)
I'm using PHP with php active record. When i retrieve a record from the database the attributes are listed as private. I need to iterate over the attributes and retrieve the key => value pair. How can this be done?
$row = \Models\Locations::find(2);
Models\Locations Object
(
[errors] =>
[attributes:ActiveRecord\Model:private] => Array
(
[id] => 2
[customer_id] => 6
[name] => test location
[address_line1] => 123 test Drive
[address_line2] =>
[city] => Moon Township
[state] => AZ
[zip] => 12345
[country] => USA
[primary_phone_number] => 123.456.7890
[latitude] => 0
[longitude] => 0
[coordinate_precision] =>
)
[__dirty:ActiveRecord\Model:private] => Array
(
)
[__readonly:ActiveRecord\Model:private] =>
[__relationships:ActiveRecord\Model:private] => Array
(
)
[__new_record:ActiveRecord\Model:private] =>
)
Source: (StackOverflow)
I'm new to CodeIgniter and PhpActiverecord and I'm wondering how to best propagate errors from the Model to the Controller when using CI and phpactiverecord. As a simple example consider this:
class Book extends ActiveRecord\Model {
static $validates_presence_of = array(
array('title')
);
public static function new_book($title){
$new_record = Book::create(array(
'title' => $title
));
if($new_record->is_invalid())
//propagate error with $new_record->errors->full_messages()
else
return $new_record;
}
}
Should I have a variable in my controller that checks if errors has been set or should I just return $new_record
whatever happens and do the is_invalid()
check in the controller? I would like to do most of the work in the model (to follow the "fat model skinny controller" principle) but I can't really see a "nice" way of propagating the errors to the controller and on to the view.
Source: (StackOverflow)
When trying to create a record in a table using phpActiveRecord I get the following error:
Invalid datetime format: 1292 Incorrect datetime value: '2013-06-20 11:59:08 PDT' for column 'created_at'
The code that is running:
$new_cart = new QuoteRequest();
$new_cart->status = "cart";
$new_cart->save();
I've tracked this down to the pertinent lines in phpActiveRecord. The file Connection.php, lines 55-59:
/**
* Database's datetime format
* @var string
*/
static $datetime_format = 'Y-m-d H:i:s T';
And the line that uses this (Connection.php, lines 457-466):
/**
* Return a date time formatted into the database's datetime format.
*
* @param DateTime $datetime The DateTime object
* @return string
*/
public function datetime_to_string($datetime)
{
return $datetime->format(static::$datetime_format);
}
And where the value is converted (Table.php lines 394-412):
private function &process_data($hash)
{
if (!$hash)
return $hash;
foreach ($hash as $name => &$value)
{
if ($value instanceof \DateTime)
{
if (isset($this->columns[$name]) && $this->columns[$name]->type == Column::DATE)
$hash[$name] = $this->conn->date_to_string($value);
else
$hash[$name] = $this->conn->datetime_to_string($value);
}
else
$hash[$name] = $value;
}
return $hash;
}
I am using MySQL version 5.6.10 and the created_at
field is a timestamp.
Question: Is there something wrong with phpActiveRecord here, or is it a MySQL problem?
Source: (StackOverflow)
I've three models:
// student_id student_name
Student extends ActiveRecord\Model
{
static $has_many = array(
array('studentcourses')
);
}
// course_id course_name
Course extends ActiveRecord\Model
{
static $has_many = array(
array('students')
);
}
// course_id student_id
Studentcourse extends ActiveRecord\Model
{
static $belongs_to = array(
array('student')
);
}
So by doing this I'll be able to retrive data from these tables easy:
$student = Student::find(1);
foreach ($student->studentcourses as $course)
{
echo $course->name;
}
But insted of typing 'studentcourses', I'd like to type $student->courses instead to get all the courses the student goes to and $course->students to get a list of students in a specific course. How would the relationship setup look to get that?
Source: (StackOverflow)
I have an model with a relation, and I want to instantiate a new object of the relations type.
Example: A person has a company, and I have a person-object: now I
want to create a company-object.
The class of the companyobject is defined in the relation, so I don't think I should need to 'know' that class, but I should be able to ask the person-object to provide me with a new instance of type company? But I don't know how.
This is -I think- the same question as New model object through an association , but I'm using PHPActiveRecord, and not the ruby one.
Reason behind this: I have an abstract superclass
person
, and two children have their own relation with a type of company object. I need to be able to instantiate the correct class in the abstract person.
A workaround is to get it directly from the static $has_one
array:
$class = $this::$has_one[1]['class_name'];
$company = new $class;
the hardcoded number can of course be eliminated by searching for the association-name in the array, but that's still quite ugly.
If there is anyone who knows how this is implemented in Ruby, and how the phpactiverecord implementation differs, I might get some Ideas from there?
Some testing has revealed that although the "search my classname in an array" looks kinda weird, it does not have any impact on performance, and in use it is functional enough.
Source: (StackOverflow)
I am having problems getting my sparks
install to work with my codeigniter
install
here are the steps I took which were as follows:
I went to my root of my codeigniter
project folder through my PHPCLI
to install sparks using the below command
php -r "$(curl -fsSL http://getsparks.org/go-sparks)"
i installed the active record library using the spark command below
php tools\spark install -v0.0.2 php-activerecord
2a. this command gave me the follwing folder structure
-application
-sparks
-php-activerecord
-0.0.2
-config
-variables
-vendor
-system
-tests
-tools
-lib
-spark
-sparktypes
-test
-user_guide
2b. this command generates a sparks
containing php active record
folder that makeup the necessary components of php-activerecord
, the command using generates a MY_Loader.php
file which looks like this
<?php if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Sparks
*
* An open source application development framework for PHP 5.1.6 or newer
*
* @package CodeIgniter
* @author CodeIgniter Reactor Dev Team
* @author Kenny Katzgrau <katzgrau@gmail.com>
* @since CodeIgniter Version 1.0
* @filesource
*/
/**
* Loader Class
*
* Loads views and files
*
* @package CodeIgniter
* @subpackage Libraries
* @author CodeIgniter Reactor Dev Team
* @author Kenny Katzgrau <katzgrau@gmail.com>
* @category Loader
* @link http://codeigniter.com/user_guide/libraries/loader.html
*/
class MY_Loader extends CI_Loader
{
/**
* Keep track of which sparks are loaded. This will come in handy for being
* speedy about loading files later.
*
* @var array
*/
var $_ci_loaded_sparks = array();
/**
* Is this version less than CI 2.1.0? If so, accomodate
* @bubbafoley's world-destroying change at: http://bit.ly/sIqR7H
* @var bool
*/
var $_is_lt_210 = false;
/**
* Constructor. Define SPARKPATH if it doesn't exist, initialize parent
*/
function __construct()
{
if(!defined('SPARKPATH'))
{
define('SPARKPATH', 'sparks/');
}
$this->_is_lt_210 = (is_callable(array('CI_Loader', 'ci_autoloader'))
|| is_callable(array('CI_Loader', '_ci_autoloader')));
parent::__construct();
}
/**
* To accomodate CI 2.1.0, we override the initialize() method instead of
* the ci_autoloader() method. Once sparks is integrated into CI, we
* can avoid the awkward version-specific logic.
* @return Loader
*/
function initialize()
{
parent::initialize();
if(!$this->_is_lt_210)
{
$this->ci_autoloader();
}
return $this;
}
/**
* Load a spark by it's path within the sparks directory defined by
* SPARKPATH, such as 'markdown/1.0'
* @param string $spark The spark path withint he sparks directory
* @param <type> $autoload An optional array of items to autoload
* in the format of:
* array (
* 'helper' => array('somehelper')
* )
* @return <type>
*/
function spark($spark, $autoload = array())
{
if(is_array($spark))
{
foreach($spark as $s)
{
$this->spark($s);
}
}
$spark = ltrim($spark, '/');
$spark = rtrim($spark, '/');
$spark_path = SPARKPATH . $spark . '/';
$parts = explode('/', $spark);
$spark_slug = strtolower($parts[0]);
# If we've already loaded this spark, bail
if(array_key_exists($spark_slug, $this->_ci_loaded_sparks))
{
return true;
}
# Check that it exists. CI Doesn't check package existence by itself
if(!file_exists($spark_path))
{
show_error("Cannot find spark path at $spark_path");
}
if(count($parts) == 2)
{
$this->_ci_loaded_sparks[$spark_slug] = $spark;
}
$this->add_package_path($spark_path);
foreach($autoload as $type => $read)
{
if($type == 'library')
$this->library($read);
elseif($type == 'model')
$this->model($read);
elseif($type == 'config')
$this->config($read);
elseif($type == 'helper')
$this->helper($read);
elseif($type == 'view')
$this->view($read);
else
show_error ("Could not autoload object of type '$type' ($read) for spark $spark");
}
// Looks for a spark's specific autoloader
$this->ci_autoloader($spark_path);
return true;
}
/**
* Pre-CI 2.0.3 method for backward compatility.
*
* @param null $basepath
* @return void
*/
function _ci_autoloader($basepath = NULL)
{
$this->ci_autoloader($basepath);
}
/**
* Specific Autoloader (99% ripped from the parent)
*
* The config/autoload.php file contains an array that permits sub-systems,
* libraries, and helpers to be loaded automatically.
*
* @param array|null $basepath
* @return void
*/
function ci_autoloader($basepath = NULL)
{
if($basepath !== NULL)
{
$autoload_path = $basepath.'config/autoload'.EXT;
}
else
{
$autoload_path = APPPATH.'config/autoload'.EXT;
}
if(! file_exists($autoload_path))
{
return FALSE;
}
include($autoload_path);
if ( ! isset($autoload))
{
return FALSE;
}
if($this->_is_lt_210 || $basepath !== NULL)
{
// Autoload packages
if (isset($autoload['packages']))
{
foreach ($autoload['packages'] as $package_path)
{
$this->add_package_path($package_path);
}
}
}
// Autoload sparks
if (isset($autoload['sparks']))
{
foreach ($autoload['sparks'] as $spark)
{
$this->spark($spark);
}
}
if($this->_is_lt_210 || $basepath !== NULL)
{
if (isset($autoload['config']))
{
// Load any custom config file
if (count($autoload['config']) > 0)
{
$CI =& get_instance();
foreach ($autoload['config'] as $key => $val)
{
$CI->config->load($val);
}
}
}
// Autoload helpers and languages
foreach (array('helper', 'language') as $type)
{
if (isset($autoload[$type]) AND count($autoload[$type]) > 0)
{
$this->$type($autoload[$type]);
}
}
// A little tweak to remain backward compatible
// The $autoload['core'] item was deprecated
if ( ! isset($autoload['libraries']) AND isset($autoload['core']))
{
$autoload['libraries'] = $autoload['core'];
}
// Load libraries
if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0)
{
// Load the database driver.
if (in_array('database', $autoload['libraries']))
{
$this->database();
$autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
}
// Load all other libraries
foreach ($autoload['libraries'] as $item)
{
$this->library($item);
}
}
// Autoload models
if (isset($autoload['model']))
{
$this->model($autoload['model']);
}
}
}
}
i modify my autoload.php
to include php active record as below
$autoload['sparks'] = array('php-activerecord/0.0.2');
when i run my codeigniter site i get the following error
A PHP Error was encountered
Severity: Notice
Message: Use of undefined constant EXT - assumed 'EXT'
Filename: core/MY_Loader.php
Line Number: 174
Backtrace:
File: C:\xampp\htdocs\orm\application\core\MY_Loader.php
Line: 174
Function: _exception_handler
File: C:\xampp\htdocs\orm\application\core\MY_Loader.php
Line: 154
Function: ci_autoloader
File: C:\xampp\htdocs\orm\application\core\MY_Loader.php
Line: 67
Function: initialize
File: C:\xampp\htdocs\orm\index.php
Line: 274
Function: require_once
I am curious as to what could be causing this error? Please let me know if there is any other configuration that I am missing or if theres a mistake that I have made.
Source: (StackOverflow)
I have a model defined as follows:
class User extends ActiveRecord\Model {
function get_name() {
return $this->first_name . " " . $this->surname;
}
}
however when I show $item->attributes();
then name doesn't appear. Am I being an idiot here? If so, how do I get my custom attributes into the model?
Thanks,
Gareth
Source: (StackOverflow)