Related
I'm totally new to GraphQL and wanted to play arouund with graphql-php in order to build a simple API to get started. I'm currently reading the docs and trying out the examples, but I'm stuck quite at the beginning.
I want my schema to be stored in a schema.graphql file instead of building it manually, so I followed the docs on how to do that and it is indeed working:
<?php
// graph-ql is installed via composer
require('../vendor/autoload.php');
use GraphQL\Language\Parser;
use GraphQL\Utils\BuildSchema;
use GraphQL\Utils\AST;
use GraphQL\GraphQL;
try {
$cacheFilename = 'cached_schema.php';
// caching, as recommended in the docs, is disabled for testing
// if (!file_exists($cacheFilename)) {
$document = Parser::parse(file_get_contents('./schema.graphql'));
file_put_contents($cacheFilename, "<?php\nreturn " . var_export(AST::toArray($document), true) . ';');
/*} else {
$document = AST::fromArray(require $cacheFilename); // fromArray() is a lazy operation as well
}*/
$typeConfigDecorator = function($typeConfig, $typeDefinitionNode) {
// In the docs, this function is just empty, but I needed to return the $typeConfig, otherwise I got an error
return $typeConfig;
};
$schema = BuildSchema::build($document, $typeConfigDecorator);
$context = (object)array();
// this has been taken from one of the examples provided in the repo
$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput, true);
$query = $input['query'];
$variableValues = isset($input['variables']) ? $input['variables'] : null;
$rootValue = ['prefix' => 'You said: '];
$result = GraphQL::executeQuery($schema, $query, $rootValue, $context, $variableValues);
$output = $result->toArray();
} catch (\Exception $e) {
$output = [
'error' => [
'message' => $e->getMessage()
]
];
}
header('Content-Type: application/json; charset=UTF-8');
echo json_encode($output);
This is what my schema.graphql file looks like:
schema {
query: Query
}
type Query {
products: [Product!]!
}
type Product {
id: ID!,
type: ProductType
}
enum ProductType {
HDRI,
SEMISPHERICAL_HDRI,
SOUND
}
I can query it for example with
query {
__schema {types{name}}
}
and this will return the metadata as expected. But of course now I want to query for actual product data and get that from a database, and for that I'd need to define a resolver function.
The docs at http://webonyx.github.io/graphql-php/type-system/type-language/ state: "By default, such schema is created without any resolvers. We have to rely on default field resolver and root value in order to execute a query against this schema." - but there is no example for doing this.
How can I add resolver functions for each of the types/fields?
This approach works without instantiating a Server. In my case, I already have a server and can read HTTP data, all I needed was to read the GraphQL schema and run the query. First I read the schema from a file:
$schemaContent = // file_get_contents or whatever works for you
$schemaDocument = GraphQL\Language\Parser::parse($schemaContent);
$schemaBuilder = new GraphQL\Utils\BuildSchema($schemaDocument);
$schema = $schemaBuilder->buildSchema();
Then I execute the query passing a custom field resolver:
$fieldResolver = function() {
return call_user_func_array([$this, 'defaultFieldResolver'], func_get_args());
};
$result = GraphQL\GraphQL::executeQuery(
$schema,
$query, // this was grabbed from the HTTP post data
null,
$appContext, // custom context
$variables, // this was grabbed from the HTTP post data
null,
$fieldResolver // HERE, custom field resolver
);
The field resolver looks like this:
private static function defaultFieldResolver(
$source,
$args,
$context,
\GraphQL\Type\Definition\ResolveInfo $info
) {
$fieldName = $info->fieldName;
$parentType = $info->parentType->name;
if ($source === NULL) {
// this is the root value, return value depending on $fieldName
// ...
} else {
// Depending on field type ($parentType), I call different field resolvers.
// Since our system is big, we implemented a bootstrapping mechanism
// so modules can register field resolvers in this class depending on field type
// ...
// If no field resolver was defined for this $parentType,
// we just rely on the default field resolver provided by graphql-php (copy/paste).
$fieldName = $info->fieldName;
$property = null;
if (is_array($source) || $source instanceof \ArrayAccess) {
if (isset($source[$fieldName])) {
$property = $source[$fieldName];
}
} else if (is_object($source)) {
if (isset($source->{$fieldName})) {
$property = $source->{$fieldName};
}
}
return $property instanceof \Closure
? $property($source, $args, $context)
: $property;
}
}
Here's what I ended up doing...
$rootResolver = array(
'emptyCart' => function($root, $args, $context, $info) {
global $rootResolver;
initSession();
$_SESSION['CART']->clear();
return $rootResolver['getCart']($root, $args, $context, $info);
},
'addCartProduct' => function($root, $args, $context, $info) {
global $rootResolver;
...
return $rootResolver['getCart']($root, $args, $context, $info);
},
'removeCartProduct' => function($root, $args, $context, $info) {
global $rootResolver;
...
return $rootResolver['getCart']($root, $args, $context, $info);
},
'getCart' => function($root, $args, $context, $info) {
initSession();
return array(
'count' => $_SESSION['CART']->quantity(),
'total' => $_SESSION['CART']->total(),
'products' => $_SESSION['CART']->getProductData()
);
},
and then in the config
$config = ServerConfig::create()
->setSchema($schema)
->setRootValue($rootResolver)
->setContext($context)
->setDebug(DEBUG_MODE)
->setQueryBatching(true)
;
$server = new StandardServer($config);
It feels rather hack-ish to me, and I should probably outsource the resolvers into separate files, but it works... Still baffled that there are no simple examples for this task, maybe in an even better way than my solution...
I'm using root value for this:
<?php
require("vendor/autoload.php") ;
require("exemplo-graphql.php");
require("Usuario.php");
use GraphQL\GraphQL;
use GraphQL\Type\Schema;
use GraphQL\Utils\BuildSchema;
$query = $_REQUEST['query'];
$typeConfigDecorator = function($typeConfig, $typeDefinitionNode) {
$name = $typeConfig['name'];
// ... add missing options to $typeConfig based on type $name
return $typeConfig;
};
$contents = file_get_contents('schema.graphql');
$schema = BuildSchema::build($contents, $typeConfigDecorator);
// $rawInput = file_get_contents('php://input');
$input = json_decode($query, true);
$query = $input['query'];
$variableValues = isset($input['variables']) ? $input['variables'] : null;
try {
// $rootValue = ['prefix' => 'You said: '];
$rootValue = [
'usuario' => function($root, $args, $context, $info) {
$usuario = new Usuario();
$usuario->setNome("aqui tem um teste");
$usuario->setEmail("aqui tem um email");
return $usuario;
},
'echo' => function($root, $args, $context, $info) {
return "aqui tem um echooo";
},
'adicionarUsuario' => function ($root, $args, $context, $info) {
$usuario = new Usuario();
$usuario->setNome("aqui tem um teste");
$usuario->setEmail("aqui tem um email");
return $usuario;
}
];
$result = GraphQL::executeQuery($schema, $query, $rootValue, null,
$variableValues);
if ($result->errors) {
$output = [
'errors' => [
[
'message' => $result->errors
]
]
];
} else {
$output = $result->toArray();
}
} catch (\Exception $e) {
$output = [
'errors' => [
[
'message' => $e->getMessage()
]
]
];
}
header('Content-Type: application/json');
echo json_encode($output);
By default, schema which was created by using BuildSchema::build() was created without any resolvers. So we need to define our custom resolvers as follows:
$contents = file_get_contents($this->projectDir.'/config/schema.graphql');
$typeConfigDecorator = function($typeConfig, $typeDefinitionNode) {
$name = $typeConfig['name'];
if ($name === 'Query') {
$typeConfig['resolveField'] =
function ($source, $args, $context, ResolveInfo $info) {
if ($info->fieldDefinition->name == 'login') {
if ($args['userName'] === 'test' && $args['password'] === '1234') {
return "Valid User.";
} else {
return "Invalid User";
}
} elseif ($info->fieldDefinition->name == 'validateUser') {
if ($args['age'] < 18) {
return ['userId' => $args['userId'], 'category' => 'Not eligible for voting'];
}
}
}
}
;
}
return $typeConfig;
};
$schema = BuildSchema::build($contents, $typeConfigDecorator);
The above example I have added resolvers for my two queries namely 'login' and 'validateUser.'
No need to define any root values and defaultFieldResolver. Our custom resolvers are enough.
I want to upload profile picture in yii user. By so much digging, i came to know that i need to make a profilefield, which i did and called "picture" and then in view of modules/user/registrtaion i need to write this code, given below is my registration view file.
<?php
$profileFields=$profile->getFields();
if ($profileFields) {
foreach($profileFields as $field) {
?>
<div class="row">
<?php
if ($widgetEdit = $field->widgetEdit($profile)) {
echo $widgetEdit;
} elseif ($field->range) {
echo $form->dropDownListControlGroup($profile,$field->varname,Profile::range($field->range));
} elseif ($field->field_type=="TEXT") {
echo$form->textArea($profile,$field->varname,array('rows'=>6, 'cols'=>50));
}
// I added this below elseif for picture upload
elseif ($field->field_type=="VARCHAR" && $field->field_size=="500") {
echo$form->fileField($profile,$field->varname,array('rows'=>6, 'cols'=>50));
}else {
echo $form->textFieldControlGroup($profile,$field->varname,array('size'=>60,'maxlength'=>(($field->field_size)?$field->field_size:255)));
}
?>
and i am hanlding this profile picture in modules/model/registration.php like this. Given below is the code.
<?php
class RegistrationForm extends User {
public $verifyPassword;
public $verifyCode;
public function rules() {
$rules = array(
array('username, password, verifyPassword, email', 'required'),
array('username', 'length', 'max'=>20, 'min' => 3,'message' => UserModule::t("Incorrect username (length between 3 and 20 characters).")),
array('password', 'length', 'max'=>128, 'min' => 4,'message' => UserModule::t("Incorrect password (minimal length 4 symbols).")),
array('email', 'email'),
array('username', 'unique', 'message' => UserModule::t("This user's name already exists.")),
array('email', 'unique', 'message' => UserModule::t("This user's email address already exists.")),
//array('verifyPassword', 'compare', 'compareAttribute'=>'password', 'message' => UserModule::t("Retype Password is incorrect.")),
array('username', 'match', 'pattern' => '/^[A-Za-z0-9_]+$/u','message' => UserModule::t("Incorrect symbols (A-z0-9).")),
// adding this liine
array('picture', 'file','types'=>'jpg, gif, png', 'allowEmpty'=>true, 'on'=>'update'), //
);
if (!(isset($_POST['ajax']) && $_POST['ajax']==='registration-form')) {
array_push($rules,array('verifyCode', 'captcha', 'allowEmpty'=>!UserModule::doCaptcha('registration')));
}
array_push($rules,array('verifyPassword', 'compare', 'compareAttribute'=>'password', 'message' => UserModule::t("Retype Password is incorrect.")));
return $rules;
}
}
and finally in the controller i handle the picture like this given below is the code.
<?php
class RegistrationController extends Controller
{
public $defaultAction = 'registration';
/**
* Declares class-based actions.
*/
public function actions()
{
return array(
'captcha'=>array(
'class'=>'CCaptchaAction',
'backColor'=>0xFFFFFF,
),
);
}
/**
* Registration user
*/
public function actionRegistration() {
$model = new RegistrationForm;
$profile=new Profile;
$profile->regMode = true;
// ajax validator
if(isset($_POST['ajax']) && $_POST['ajax']==='registration-form')
{
echo UActiveForm::validate(array($model,$profile));
Yii::app()->end();
}
if (Yii::app()->user->id) {
$this->redirect(Yii::app()->controller->module->profileUrl);
} else {
if(isset($_POST['RegistrationForm'])) {
// handling picture
$rnd = rand(0, 9999); // generate random number between 0-9999
$model->attributes = $_POST['RegistrationForm'];
$uploadedFile = CUploadedFile::getInstance($model, 'picture');
$fileName = "{$rnd}-{$uploadedFile}"; // random number + file name
$model->picture = $fileName;
if ($model->save()) {
$uploadedFile->saveAs(Yii::app()->basePath . '/../img/' . $fileName);
$this->redirect(array('view', 'id' => $model->id));
}
// hanlding picture ends
$profile->attributes=((isset($_POST['Profile'])?$_POST['Profile']:array()));
if($model->validate()&&$profile->validate())
{
$soucePassword = $model->password;
$model->activkey=UserModule::encrypting(microtime().$model->password);
$model->password=UserModule::encrypting($model->password);
$model->verifyPassword=UserModule::encrypting($model->verifyPassword);
$model->superuser=0;
$model->status=((Yii::app()->controller->module->activeAfterRegister)?User::STATUS_ACTIVE:User::STATUS_NOACTIVE);
if ($model->save()) {
$profile->user_id=$model->id;
$profile->save();
if (Yii::app()->controller->module->sendActivationMail) {
$activation_url = $this->createAbsoluteUrl('/user/activation/activation',array("activkey" => $model->activkey, "email" => $model->email));
UserModule::sendMail($model->email,UserModule::t("You registered from {site_name}",array('{site_name}'=>Yii::app()->name)),UserModule::t("Please activate you account go to {activation_url}",array('{activation_url}'=>$activation_url)));
}
if ((Yii::app()->controller->module->loginNotActiv||(Yii::app()->controller->module->activeAfterRegister&&Yii::app()->controller->module->sendActivationMail==false))&&Yii::app()->controller->module->autoLogin) {
$identity=new UserIdentity($model->username,$soucePassword);
$identity->authenticate();
Yii::app()->user->login($identity,0);
$this->redirect(Yii::app()->controller->module->returnUrl);
} else {
if (!Yii::app()->controller->module->activeAfterRegister&&!Yii::app()->controller->module->sendActivationMail) {
Yii::app()->user->setFlash('registration',UserModule::t("Thank you for your registration. Contact Admin to activate your account."));
} elseif(Yii::app()->controller->module->activeAfterRegister&&Yii::app()->controller->module->sendActivationMail==false) {
Yii::app()->user->setFlash('registration',UserModule::t("Thank you for your registration. Please {{login}}.",array('{{login}}'=>CHtml::link(UserModule::t('Login'),Yii::app()->controller->module->loginUrl))));
} elseif(Yii::app()->controller->module->loginNotActiv) {
Yii::app()->user->setFlash('registration',UserModule::t("Thank you for your registration. Please check your email or login."));
} else {
Yii::app()->user->setFlash('registration',UserModule::t("Thank you for your registration. Please check your email."));
}
$this->refresh();
}
}
} else $profile->validate();
}
$this->render('/user/registration',array('model'=>$model,'profile'=>$profile));
}
}
}
so the problem is,, when i enter the details on registraion form and upload a picture i get this error Property "RegistrationForm.picture" is not defined. The problem lies in controller line number 45 which is
$model->picture = $fileName;
I already have picture field in "profiles" table. But the thing is i am totally confused, and neither at yii framework forum nor at stackoverflow i found a proper documentation over this thing. Please help.
My profile.php (model) code
<?php
class Profile extends UActiveRecord
{
/**
* The followings are the available columns in table 'profiles':
* #var integer $user_id
* #var boolean $regMode
*/
public $regMode = false;
private $_model;
private $_modelReg;
private $_rules = array();
/**
* Returns the static model of the specified AR class.
* #return CActiveRecord the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* #return string the associated database table name
*/
public function tableName()
{
return Yii::app()->getModule('user')->tableProfiles;
}
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
if (!$this->_rules) {
$required = array();
$numerical = array();
$float = array();
$decimal = array();
$rules = array();
$model=$this->getFields();
foreach ($model as $field) {
$field_rule = array();
if ($field->required==ProfileField::REQUIRED_YES_NOT_SHOW_REG||$field->required==ProfileField::REQUIRED_YES_SHOW_REG)
array_push($required,$field->varname);
if ($field->field_type=='FLOAT')
array_push($float,$field->varname);
if ($field->field_type=='DECIMAL')
array_push($decimal,$field->varname);
if ($field->field_type=='INTEGER')
array_push($numerical,$field->varname);
if ($field->field_type=='VARCHAR'||$field->field_type=='TEXT') {
$field_rule = array($field->varname, 'length', 'max'=>$field->field_size, 'min' => $field->field_size_min);
if ($field->error_message) $field_rule['message'] = UserModule::t($field->error_message);
array_push($rules,$field_rule);
}
if ($field->other_validator) {
if (strpos($field->other_validator,'{')===0) {
$validator = (array)CJavaScript::jsonDecode($field->other_validator);
foreach ($validator as $name=>$val) {
$field_rule = array($field->varname, $name);
$field_rule = array_merge($field_rule,(array)$validator[$name]);
if ($field->error_message) $field_rule['message'] = UserModule::t($field->error_message);
array_push($rules,$field_rule);
}
} else {
$field_rule = array($field->varname, $field->other_validator);
if ($field->error_message) $field_rule['message'] = UserModule::t($field->error_message);
array_push($rules,$field_rule);
}
} elseif ($field->field_type=='DATE') {
$field_rule = array($field->varname, 'type', 'type' => 'date', 'dateFormat' => 'yyyy-mm-dd', 'allowEmpty'=>true);
if ($field->error_message) $field_rule['message'] = UserModule::t($field->error_message);
array_push($rules,$field_rule);
}
if ($field->match) {
$field_rule = array($field->varname, 'match', 'pattern' => $field->match);
if ($field->error_message) $field_rule['message'] = UserModule::t($field->error_message);
array_push($rules,$field_rule);
}
if ($field->range) {
$field_rule = array($field->varname, 'in', 'range' => self::rangeRules($field->range));
if ($field->error_message) $field_rule['message'] = UserModule::t($field->error_message);
array_push($rules,$field_rule);
}
}
array_push($rules,array(implode(',',$required), 'required'));
array_push($rules,array(implode(',',$numerical), 'numerical', 'integerOnly'=>true));
array_push($rules,array(implode(',',$float), 'type', 'type'=>'float'));
array_push($rules,array(implode(',',$decimal), 'match', 'pattern' => '/^\s*[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s*$/'));
$this->_rules = $rules;
}
return $this->_rules;
}
/**
* #return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
$relations = array(
'user'=>array(self::HAS_ONE, 'User', 'id'),
);
if (isset(Yii::app()->getModule('user')->profileRelations)) $relations = array_merge($relations,Yii::app()->getModule('user')->profileRelations);
return $relations;
}
/**
* #return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
$labels = array(
'user_id' => UserModule::t('User ID'),
);
$model=$this->getFields();
foreach ($model as $field)
$labels[$field->varname] = ((Yii::app()->getModule('user')->fieldsMessage)?UserModule::t($field->title,array(),Yii::app()->getModule('user')->fieldsMessage):UserModule::t($field->title));
return $labels;
}
private function rangeRules($str) {
$rules = explode(';',$str);
for ($i=0;$i<count($rules);$i++)
$rules[$i] = current(explode("==",$rules[$i]));
return $rules;
}
static public function range($str,$fieldValue=NULL) {
$rules = explode(';',$str);
$array = array();
for ($i=0;$i<count($rules);$i++) {
$item = explode("==",$rules[$i]);
if (isset($item[0])) $array[$item[0]] = ((isset($item[1]))?$item[1]:$item[0]);
}
if (isset($fieldValue))
if (isset($array[$fieldValue])) return $array[$fieldValue]; else return '';
else
return $array;
}
public function widgetAttributes() {
$data = array();
$model=$this->getFields();
foreach ($model as $field) {
if ($field->widget) $data[$field->varname]=$field->widget;
}
return $data;
}
public function widgetParams($fieldName) {
$data = array();
$model=$this->getFields();
foreach ($model as $field) {
if ($field->widget) $data[$field->varname]=$field->widgetparams;
}
return $data[$fieldName];
}
public function getFields() {
if ($this->regMode) {
if (!$this->_modelReg)
$this->_modelReg=ProfileField::model()->forRegistration()->findAll();
return $this->_modelReg;
} else {
if (!$this->_model)
$this->_model=ProfileField::model()->forOwner()->findAll();
return $this->_model;
}
}
}
Your registration form model extends user class. Your field picture is not the attribute of any of them.
It will be the attribute of profile model. You should move your rule to profile model.
Edit: In your profile model put this line
array_push($rules,array('picture', 'file','types'=>'jpg, gif, png', 'allowEmpty'=>true, 'on'=>'update'));
before the line
$this->_rules = $rules;
this code is not tested but it should work.
http error occured while calling data from model using function
model
public function getProductCombo() {
$q = $this->db->get_where('products', array('type' => 'combo'));
if ($q->num_rows() > 0) {
foreach (($q->result()) as $row) {
$data[] = $row;
}
return $data;
}
}
controller
function sets() {
$this->sma->checkPermissions();
$this->load->helper('security');
$this->data['error'] = (validation_errors() ? validation_errors() :
$this->session->flashdata('error'));
// problem in this line also
$this->data['showcombo'] = $this->load->sales_model->getComboProduct();
$bc = array(array('link' => base_url(),
'page' => lang('home')),
array('link' => site_url('sales'),
'page' => lang('products')),
array('link' => '#', 'page' => "sets")
);
$meta = array('page_title' => "Add Sets", 'bc' => $bc);
$this->page_construct('sales/sets', $meta, $this->data);
}
First of all, No need to include the curly braces for $q->result
foreach ($q->result as $row)
{
$data[] = $row;
}
No need to use validation_errors in your php file.You can directly load your form page.Use validation_errors() in view page.
In your Controller, do this
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
Then in your formpage you can echo
<?php echo validation_errors(); ?>
change this line to
$this->data['showcombo'] = $this->load->sales_model->getComboProduct();
this
$this->data['showcombo'] = $this->load->sales_model->getProductCombo();
Because your
model name is
public function getProductCombo()
{
}
Firstly you load model in controller. And then called function, which you have defined in model..
$this->load->model('sales_model','sales'); // sales is alias name of model name
$this->data['showcombo'] = $this->sales->getComboProduct();
I've been scouring the webs and potching with my code for hours now and can't seem to figure out why this isn't working.
I have a template library which scans a template.html for {#tags} and then runs the function associated to the tag to create data for that {#tag}'s content and then replaces {#tag} for the content generated, so I can have widget like parts to my template.
On my account/access page I have a login form and a registration form, now when the template library calls the widget_register() function, the form validation doesn't seem to do anything, the data is posted as I can see from the profiler, but the form validation doesn't seem to do anything with it
Account Controller
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Account extends CI_Controller {
public function index()
{
$this->load->helper('url');
#redirect('/');
}
public function access()
{
$this->load->helper('url');
#if($this->auth->loggedin()) redirect('/');
$this->template->compile_page();
}
public function widget_register($template)
{
$this->output->enable_profiler(TRUE);
$this->load->helper('url');
if($this->auth->loggedin()) redirect('/');
if ($this->input->post('register_submit'))
{
$this->load->model('auth_model');
$this->form_validation->set_rules('register_nickname', 'Nickname', 'required|min_length[3]|max_length[75]');
$this->form_validation->set_rules('register_email_address', 'Email Address', 'required|valid_email|is_unique[users.email]');
$this->form_validation->set_rules('register_confirm_email_address', 'Confirm Email Address', 'required|valid_email|matches[register_email_address]');
$this->form_validation->set_rules('register_password', 'Password', 'required|min_length[5]');
$this->form_validation->set_rules('register_confirm_password', 'Confirm Password', 'required|min_length[5]|matches[register_password]');
if($this->form_validation->run() !== false)
{
echo 'validation successful';
$nickname = $this->input->post('register_nickname');
$email = $this->input->post('register_email_address');
$generate_salt = $this->auth->generate_keys();
$salt = $generate_salt['1'];
$this->load->library('encrypt');
$generate_password = $salt . $this->input->post('register_password');
$password = $this->encrypt->hash($generate_password);
$generate_series_key = $this->auth->generate_keys();
$user_series_key = $generate_series_key['1'];
$this->db->query('INSERT INTO users (nickname, email, password, salt, register_date) VALUES ( "'.$nickname.'", "'.$email.'", "'.$password.'", "'.$salt.'", "'.time().'")');
}
else
{
echo 'invalid';
echo validation_errors();
}
}
$this->load->helper('form');
$view_data = array();
$view_data['form'] = form_open('account/access');
$view_data['input_nickname'] = form_input(array('name' => 'register_nickname', 'value' => set_value('register_nickname'), 'id' => 'register_nickname', 'class' => 'common_input', 'size' => '55'));
$view_data['input_email'] = form_input(array('name' => 'register_email_address', 'value' => set_value('register_email_address'), 'id' => 'register_email_address', 'class' => 'common_input', 'size' => '55'));
$view_data['input_confirm_email'] = form_input(array('name' => 'register_confirm_email_address', 'value' => '', 'id' => 'register_confirm_email_address', 'class' => 'common_input', 'size' => '55'));
$view_data['input_password'] = form_password(array('name' => 'register_password', 'value' => '', 'id' => 'register_password', 'class' => 'common_input', 'size' => '55'));
$view_data['input_confirm_password'] = form_password(array('name' => 'register_confirm_password', 'value' => '', 'id' => 'register_confirm_password', 'class' => 'common_input', 'size' => '55'));
$view_data['form_submit'] = form_submit('register_submit', 'Register');
$view_data['/form'] = form_close();
$view_data['validation_errors'] = validation_errors('<div class="error-box">', '</div>');
return $this->parser->parse(FCPATH.'themes/'.$this->settings->settings['system_settings']['theme'].'/widgets/'.$template.'.html', $view_data, TRUE);
}
function widget_login()
{
$this->load->helper('url');
// user is already logged in
if ($this->auth->loggedin())
{
return $this->load->view(FCPATH.'themes/'.$this->settings->settings['system_settings']['theme'].'/widgets/login/user.html', '', TRUE);
}
if($this->input->post('register'))
{
redirect('authentication/register');
}
// form submitted
if ($this->input->post('login_email_address') && $this->input->post('login_password'))
{
$this->load->library('form_validation');
$this->load->model('auth_model');
$this->form_validation->set_rules('login_email_address', 'Email Address', 'required|valid_email');
$this->form_validation->set_rules('login_password', 'Password', 'required|min_length[4]');
if($this->form_validation->run() !== false)
{
// validation passed verify from db
$remember = $this->input->post('remember') ? TRUE : FALSE;
if($remember == 'remember');
// check user exists and return user data
$user_data = $this->auth_model->user_exists($this->input->post('email_address'), TRUE);
if($user_data != FALSE)
{
// compare passwords
if ($this->auth_model->check_password($this->input->post('password'), $this->input->post('email_address')))
{
$this->auth->login($user_data->uid, $remember);
redirect('/');
}
else { $this->form_validation->set_custom_error('Incorrect password'); }
}
else { $this->form_validation->set_custom_error('There are no users with that email address'); }
}
}
// show login form
$this->load->helper('form');
$view_data = array();
$view_data['form'] = form_open();
$view_data['input_email'] = form_input('login_email_address', set_value('login_email_address'), 'id="login_email_address"');
$view_data['input_password'] = form_password('login_password', '', 'id="login_password"');
$view_data['input_remember'] = form_checkbox('remember', 'rememberme');
$view_data['form_submit'] = form_submit('login_submit', 'Login');
$view_data['register_button'] = form_submit('register', 'Register');
$view_data['/form'] = form_close();
$view_data['validation_errors'] = validation_errors('<div class="error-box">', '</div>');
return $this->parser->parse(FCPATH.'themes/'.$this->settings->settings['system_settings']['theme'].'/widgets/login/login.html', $view_data, TRUE);
}
function logout()
{
$this->load->helper('url');
$this->session->sess_destroy();
$this->load->helper('cookie');
delete_cookie('aws_session');
delete_cookie('aws_autologin_cookie');
redirect('/');
}
}
and the Template library
class Template {
private $settings;
private $_ci;
private $_controller = ''; # Controller in use
private $_method = ''; # Method in use
private $_is_mobile = FALSE; # Is the User agent a mobile?
private $cache_lifetime = '1';
private $page_output = "";
private $partials = array();
private $spts = array(); # Static page tags
function __construct()
{
$this->_ci =& get_instance();
$this->settings = $this->_ci->settings->settings;
$this->_controller = $this->_ci->router->fetch_class();
$this->_method = $this->_ci->router->fetch_method();
$this->_ci->load->library('user_agent');
$this->_is_mobile = $this->_ci->agent->is_mobile();
log_message('debug', "Template Class Initialized");
}
function build_page()
{
$page = $this->_ci->load->view(FCPATH.'themes/'.$this->settings['system_settings']['theme'].'/pages/'.$this->settings['page_settings']['template'].'.html', '', TRUE);
$this->page_output .= $page;
}
# MAIN PAGE FUNCTIONS END ------------------------------------------------------------------------------------------
public function check_static_tags()
{
if(preg_match_all('/{#[A-Z]{1,75}}/', $this->page_output, $matches))
{
$this->spts = $matches['0'];
$this->spts = array_diff($this->spts, array('{#CONTENT}')); # removes stp_content from array list
return TRUE;
}
return FALSE;
}
# Convert static tags
public function convert_static_tags()
{
foreach($this->spts as $key => $static_tag)
{
$static_tag = str_replace(array('{','}'), '', $static_tag);
$this->partials[$static_tag] = $this->build_widget($static_tag);
}
}
# Convert widget tags
function column_widget_tags()
{
if(preg_match_all('/{#COLUMN_[0-9]{1,11}}/', $this->page_output, $matches))
{
if(isset($this->settings['page_settings']['widgets']))
{
$columns = unserialize($this->settings['page_settings']['widgets']);
}
foreach($columns as $column_id => $widgets)
{
if(count($columns[$column_id]) > '0') // if the column contains widgets
{
$this->partials[''.$this->_stp.'_COLUMN_'.$column_id] = '';
foreach($widgets as $key => $widget_id)
{
// build the widget and add it to the $this->page_bits['column_id'] variable for replacing later in the compiler
$this->partials[''.$this->_stp.'_COLUMN_'.$column_id] .= $this->build_widget($widget_id);
}
}
else
{
$this->partials[''.$this->_stp.'_COLUMN_'.$column_id] = '';
}
}
}
}
# Build Widget
function build_widget($widget_id)
{
if(is_numeric($widget_id))
{
$widget_query = $this->_ci->db->query('SELECT * FROM widgets WHERE id = "'.$widget_id.'"'); # BIND STATEMENTS
}
elseif(preg_match('/#[A-Z]{1,75}/', $widget_id))
{
$widget_query = $this->_ci->db->query('SELECT * FROM widgets WHERE tag = "'.$widget_id.'"'); # BIND STATEMENTS
}
else
{
show_error('Could not get widget from database: '.$widget_id);
}
if($widget_query->num_rows() > 0)
{
$widget_info = $widget_query->row_array();
// loads widgets parent controller, builds the widget (class method) and returns it
$this->_ci->load->controller($widget_info['controller'], $widget_info['controller']);
$method_name = 'widget_'.$widget_info['method'];
$complete_widget = $this->_ci->$widget_info['controller']->$method_name($widget_info['template']);
return $complete_widget;
}
else
{
show_error('The requested widget could not be loaded: '.$widget_id);
}
}
# Replace Partials
function replace_partials()
{
$this->_ci->load->library('parser');
$this->page_output = $this->_ci->parser->parse_string($this->page_output, $this->partials, TRUE);
}
## METADATA
public function prepend_metadata($line)
{
array_unshift($this->_metadata, $line);
return $this;
}
# Put extra javascipt, css, meta tags, etc after other head data
public function append_metadata($line)
{
$this->_metadata[] = $line;
return $this;
}
# Set metadata for output later
public function set_metadata($name, $content, $type = 'meta')
{
$name = htmlspecialchars(strip_tags($name));
$content = htmlspecialchars(strip_tags($content));
// Keywords with no comments? ARG! comment them
if ($name == 'keywords' AND ! strpos($content, ','))
{
$content = preg_replace('/[\s]+/', ', ', trim($content));
}
switch($type)
{
case 'meta':
$this->_metadata[$name] = '<meta name="'.$name.'" content="'.$content.'" />';
break;
case 'link':
$this->_metadata[$content] = '<link rel="'.$name.'" href="'.$content.'" />';
break;
}
return $this;
}
# Embed page into layout wrapper
function layout()
{
$this->_ci->load->helper('html');
$this->append_metadata(link_tag('themes/'.$this->settings['system_settings']['theme'].'/css/layout.css')); # default stylesheet
$this->append_metadata('<link rel="shortcut icon" href="/favicon2.ico" />'); # default favicon
$template['template.title'] = $this->settings['page_settings']['title']; # Page title, can be overidden by the controller ?
$template['template.metadata'] = implode("\n\t\t", $this->_metadata); # Metadata
$template['template.body'] = $this->page_output; # The page
return $this->_ci->parser->parse(FCPATH.'assets/layout/L6_layout_wrapper.html', $template, TRUE);
}
# Run all functions to build page and set in output class
function compile_page($content_data = '')
{
$this->partials['#CONTENT'] = $content_data;
$this->build_page();
$this->column_widget_tags();
if($this->check_static_tags())
{
$this->convert_static_tags();
$this->replace_partials();
}
$output = $this->layout();
$this->_ci->output->set_header('Expires: Sat, 01 Jan 2000 00:00:01 GMT');
$this->_ci->output->set_header('Cache-Control: no-store, no-cache, must-revalidate');
$this->_ci->output->set_header('Cache-Control: post-check=0, pre-check=0, max-age=0');
$this->_ci->output->set_header('Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
$this->_ci->output->set_header('Pragma: no-cache');
# Let CI do the caching instead of the browser
#$this->_ci->output->cache($this->cache_lifetime);
$this->_ci->output->append_output($output);
}
}
Sorry for the incredibly long post, I'm really stumped here and didn't want to miss any code out, thanks in advance!
I'm writing a custom component for my work. I'm using hello component for building it. When I edit a form and save it I get this error:
Call to a member function bind() on a non-object
My code:
function save()
{
global $option;
JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components'.DS.'com_abc'.DS.'tables');
$row =& JTable::getInstance('abc', 'Table');
if(!$row->bind(JRequest::get('post')))
{
JError::raiseError(500, $row->getError() );
}
$row->message = JRequest::getVar( 'message', '','post', 'string', JREQUEST_ALLOWRAW );
if(!$row->store()){
JError::raiseError(500, $row->getError() );
}
switch($this->_task)
{
case 'apply':
$msg = 'Change Saved';
$link = 'index.php?option='.$option.'&task=edit&cid[]='.$row->id;
break;
case 'save':
$msg = 'Saved';
$link = 'index.php?option='.$option;
break;
default:
}
$this->setRedirect($link, $msg);
}
The problem is that it's unable to create an instance.
Please let me know if anyone knows a solution.
Thanks.
The problem is you calling the method 'bind' that doesn't exists on the variable $row.
You defined $row as: $row =& JTable::getInstance('abc', 'Table'); which means your problem starts right there. It's trying to fetch database content which fails. I suggest you change the parameters 'abc' and 'Table' to something real, it looks like sample data to me.
The following code will help you:
function addComment($option)
{
global $mainframe;
$row =& JTable::getInstance( 'comment' , 'Table' );
if (!$row->bind(JRequest::get( 'post')))
{
JError::raiseError(500, $row->getError() );
}
$row->comment_date = date ( 'Y-m-d H:i:s' );
$user =& JFactory::getUser();
if($user->id)
{
$row->user_id = $user->id;
}
if(!$row->store())
{
JError::raiseError(500, $row->getError() );
}
$link = JRoute::_( 'index.php?option='.$option.'&id='.$row->id . '&task=view' );
$mainframe->redirect( $link, 'Comment Added' );
}
My table name data to be fetched is jos_abc. The save function is in my_componet/controller.php. The class name of controller is XyzController:
class XyzController extends JController {
function __construct() {
//Get View
if(JRequest::getCmd('view') == '') {
JRequest::setVar('view', 'default');
}
$this->item_type = 'Default';
parent::__construct();
}
function save()
{
global $option;
JTable::addIncludePath(JPATH_ADMINISTRATOR.DS.'components'.DS.'com_tripplanner'.DS.'tables');
$row1 =& JTable::getInstance('xyz', 'jos_abc');
if(!$row1->bind(JRequest::get('post')))
{
JError::raiseError(500, $row->getError() );
}
$row->message = JRequest::getVar( 'message', '','post', 'string', JREQUEST_ALLOWRAW );
if(!$row->store()){
JError::raiseError(500, $row->getError() );
}
switch($this->_task)
{
case 'apply':
$msg = 'Change Saved';
$link = 'index.php?option='.$option.'&task=edit&cid[]='.$row->id;
break;
case 'save':
$msg = 'Saved';
$link = 'index.php?option='.$option;
break;
default:
}
$this->setRedirect($link, $msg);
}
}
Even then I'm unable to save, I get "Call to a member function bind() on a non-object".