EzDevInfo.com

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.

PHP activerecord mysql server has gone away

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)

PHP ActiveRecord creating a child model via Has_Many association

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)

Advertisements

Returning every second row of an SQL query

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)

MySQL - Search a field ignoring spaces

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)

phpactiverecord - display generated query?

Using phpactiverecord from http://www.phpactiverecord.org/, is there any way to see the generated SQL query for debugging, other than viewing the database server's query log?


Source: (StackOverflow)

How to query with active record in codeigniter for dates between specified times

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)

Get a PHPActiveRecord result as simple array, not array of objects

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)

PHP & Twig : Trouble accessing variables in template

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)

Iterate over object with private attributes

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)

Error handling codeigniter and phpactiverecord

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)

phpActiveRecord Incorrect DateTimeFormat

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)

php activerecord many to many

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)

Activerecord-association: create new object (find class)

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)

Problems up setting up codeigniter with sparks & active record

I am having problems getting my sparks install to work with my codeigniter install

here are the steps I took which were as follows:

  1. 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)"
    
  2. 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']);
            }
        }
    }
}
  1. 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)

PHP ActiveRecord doesn't seem to use my custom attribute

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)