• Home
  • Yii Framework
 
 

Yii Framework

677 Items
  • Yii Framework
    [Wiki] Add Beautiful Radio/Checkbox Buttons To Grid

    Overview This is a tutorial on how to create slick looking status buttons to update a model's status via a grid. Note** This tutorial uses Yii Bootstrap for styling. The basic idea is to render a grid and, for each row, render a set of radio buttons that asynchronously update their respective model. Requirements Yii Bootstrap Yii 1.1.+ News Model This tutorial assumes your DB table has a field called status and is a varchar field. We need to add the statuses that a news item can have. For the sake of simplicity, I've added them as constants but you could use a separate DB lookup table. const STATUS_PUBLISHED = 'published'; const STATUS_DRAFT = 'draft'; const STATUS_ARCHIVED = 'archived'; /** * Returns true if the model is published. * @return boolean whether the model is published or not */ public function isPublished() { return ($this->status == self::STATUS_PUBLISHED) ? true : false; } /** * Returns true if the model is a draft. * @return boolean whether the model is a draft or not */ public function isDraft() { return ($this->status == self::STATUS_DRAFT) ? true : false; } /** * Returns true if the model is archived. * @return boolean whether the model is archived or not */ public function isArchived() { return ($this->status == self::STATUS_ARCHIVED) ? true : false; } /** * Returns a well formatted status for the news item. * @return string the status of the news item */ public function getStatus() { return ucwords($this->status); } News Controller We need to add actions (actionPublish, actionDraft, actionArchive) that will handle the calls to update the status of the news item. I've kept these very simple but you should do some checking before allowing the status of items to be changed - only POST, only AJAX etc. public function actionPublish($id) { $model = $this->loadModel($id); $model->status = News::STATUS_PUBLISHED; $model->save(); } public function actionDraft($id) { $model = $this->loadModel($id); $model->status = News::STATUS_DRAFT; $model->save(); } public function actionArchive($id) { $model = $this->loadModel($id); $model->status = News::STATUS_ARCHIVED; $model->save(); } News Views The views consist of the normal admin view and a partial view called status_button. The _status_button view is rendered for each row in the grid. We include a bit a javascript at the bottom of the admin view which will do the actual AJAX calls and disable the button if it is in that state. For example, a published news items should have it's _Publish radio button disabled. Note** This grid uses an anonymous function (closure) to render the partial view. This PHP feature became available in 5.3.0. admin.php h1>Manage Newsh1> php $this->widget('bootstrap.widgets.TbGridView', array( 'type' => 'striped bordered', 'id' => 'news-grid', 'dataProvider' => $model->search(), 'filter' => $model, 'columns' => array( array( 'name' => 'title', 'htmlOptions' => array( 'class' => 'span10' ) ), array( 'name' => 'status', 'value' => function($data) { Yii::app()->controller->renderPartial('_status_button', array( 'data' => $data )); }, 'filter' => array( News::STATUS_PUBLISHED => 'Published', News::STATUS_ARCHIVED => 'Archived', News::STATUS_DRAFT => 'Draft' ), 'htmlOptions' => array( 'class' => 'span1' ) ), array( 'class' => 'bootstrap.widgets.TbButtonColumn', ), ), )); ?> script type="text/javascript"> jQuery('#news-grid a.toggleStatus').live('click',function() { if ($(this).hasClass('disabled')) return false; var th=this; var afterDelete=function(){}; $.fn.yiiGridView.update('news-grid', { type:'POST', url:$(this).attr('href'), success:function(data) { $.fn.yiiGridView.update('news-grid'); afterDelete(th,true,data); }, error:function(XHR) { return afterDelete(th,false,XHR); } }); return false; }); script> _status_button.php One important thing to note about the _status_button.php view file is this line: 'class' => ($data->isPublished()) ? 'toggleStatus disabled' : 'toggleStatus', The bit of javascript at the bottom of admin.php listens to the click event of links with a class of toggleStatus. Therefore, don't forget to change the JS if you change the class of these radio buttons. $this->widget('bootstrap.widgets.TbButtonGroup', array( 'toggle' => 'radio', 'buttons' => array( array( 'label' => ucwords(News::STATUS_PUBLISHED), 'type' => ($data->isPublished()) ? 'info' : '', 'url' => Yii::app()->createUrl('admin/news/publish', array('id' => $data->id)), 'htmlOptions' => array( 'id' => 'status' . $data->id, 'class' => ($data->isPublished()) ? 'toggleStatus disabled' : 'toggleStatus', ), 'active' => ($data->isPublished()) ? true : false, ), array( 'label' => ucwords(News::STATUS_ARCHIVED), 'type' => ($data->isArchived()) ? 'info' : '', 'url' => Yii::app()->createUrl('admin/news/archive', array('id' => $data->id)), 'htmlOptions' => array( 'id' => 'status' . $data->id, 'class' => ($data->isArchived()) ? 'toggleStatus disabled' : 'toggleStatus', ), 'active' => ($data->isArchived()) ? true : false, ), array( 'label' => ucwords(News::STATUS_DRAFT), 'type' => ($data->isDraft()) ? 'info' : '', 'url' => Yii::app()->createUrl('admin/news/draft', array('id' => $data->id)), 'htmlOptions' => array( 'id' => 'status' . $data->id, 'class' => ($data->isDraft()) ? 'toggleStatus disabled' : 'toggleStatus', ), 'active' => ($data->isDraft()) ? true : false, ), ) )); ?> That's it. Hopefully you found this helpful.

    14
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Yii CGridView add custom button

    Hi buddies !, This tutorial shows about how to add a custom button with your own icon for your CGridView of Yii framework Step 1 Add a new array element under 'class' => 'CButtonColumn' as follow The default buttons are 'template' => '{view}{update}{delete}', Now I am adding a new button for reply 'template' => '{reply}{view}{update}{delete}', Step 2 Then add a new element in the name reply under button array as follows 'buttons' => array( 'reply' => array( //the name {reply} must be same 'label' => 'Reply', // text label of the button 'url' => 'CHtml::normalizeUrl(array("dashboard/mail/id/".rawurlencode($data->feedback_email)."/f_id/".$data->feedback_id))', //Your URL According to your wish 'imageUrl' => Yii::app()->baseUrl . '/images/reply_mail_icon.png', // image URL of the button. If not set or false, a text link is used, The image must be 16X16 pixels ), ),

    7
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] How to change the confirmation message on admingridview button and call a ajax..Dynamic

    Hi Friends, if category is assigned to any product and can not delete the category.... or if you want to change the status on dynamic this article is helpful... In this example liquor_category is assigned to liquor table so if i want to delete the any liquor_category then display the alert message (it's already assigned to liquor) so you can't delete the liquor Category and create the custom message $alert = 'Are you sure you want to delete this Category?'; ?> 1) First apply the ajax on admin grid-view... array( 'header' => 'Action', 'class' => 'CButtonColumn', 'template' => '{update}{delete}', 'buttons' => array('delete' => array( 'url' => 'Yii::app()->controller->createUrl("delete",array("id"=>$data->primaryKey))', 'label' => 'delete', 'options' => array(// this is the 'html' array but we specify the 'ajax' element 'confirm' => $alert, 'class' => 'grid_action_set1', 'ajax' => array( 'type' => 'POST', 'url' => "js:$(this).attr('href')", // ajax post will use 'url' specified above 'success' => 'function(data){ if(data == "true"){ //update the grid... $.fn.yiiGridView.update("liquor-category-grid"); return false; }else{ window.location="admin?del=exist"; return false; } }', ), ), ), 'update' => array( 'options' => array('class' => 'grid_action_set'), ), ), 'htmlOptions' => array('width' => '8%') ), 2) Change the delete function on Controller.. public function actionDelete($id) { if (Yii::app()->getRequest()->getIsPostRequest()) { //fetch the liquor_category_id on liquor table $data=Liquor::model()->findAll('liquor_category_id='.$id); $flag = 0; UtilityHtml::AdminDelete($flag,$data,$id,$model='LiquorCategory'); } else throw new CHttpException(400, Yii::t('app', 'Your request is invalid.')); // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser } 3) Create the common-function file and put the function on AdminDelete //in my artical i will create the** UtilityHtml.php** (/protocted/comoponets/UtilityHtml.php file) public function AdminDelete($flag, $data, $id, $model) { if (isset($data) && count($data) > 0) { $flag = 1; } if ($flag == 0) { echo "true"; $this->loadModel($id, $model)->delete(); Yii::app()->end(); } else { echo "false"; Yii::app()->end(); } } 4) Finally you want to display the alert message on admin view file(admin.php) $delete = ''; if (isset($_GET['del']) && !empty($_GET['del'])) { $delete = $_GET['del']; } ?> script type="text/javascript"> $(document).ready(function() { var del = ''; if (del == 'exist') { alert('Category Can not be deleted as there is already liquor is assigned for particular liquor category.'); window.location.href = ''admin'); ?>'; } }); script> Hope it will be helpful...

    11
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Creating a Simple CRUD App With Yii2

    Getting Started With Yii Framework 2. A Basic Tutorial Disclaimer This guide is meant to help you started with Yii2. Yii2 is by no means "production" ready. I do not recommend using this in production. Edit This guide has been updated to reflect some changes that should import the quality of this post. Namely: 1) Getting ActiveRecord to autoincriment the database 2) Changing the charset of utf8. 3) Removal of model() method in Post Model 4) Update findallMethod 5) Added Flash Messages instead of 404 errors. 6) Removal of XSS Injection Vector Today Yii Framework made the announcement that Yii2 was now available for a public preview. A lot has changed from Yii1 to Yii2, This tutorial will go over making a simple blog site in Yii2. For this guide, we'll be getting and installing Yii2, creating a base app, connecting to a database, and configuring logic to create, updated, read, and delete posts. For this tutorial, here's what you'll need: A webserver, either Apache or Nginx. For this guide I'll be using Nginx. The conversion to Apache should be trivial however, so don't worry if you don't have an Nginx server lying around. A database to connect our app to. I'll be using MySQL 5.5 Basic PHP knowledge. I'll try to keep it as simple as possible, but the more PHP you know, the easier it will be to follow along. Basic Knowledge of either Yii or MVC. If you don't have any experience with MVC, I recommend you read up on MVC fundamentals. You can follow this guide without them, however things will make more sense if you have a concept of what MVC is. So, lets get started! For this tutorial I'm going to assume that you already have your webserver setup. For this guide, I'm going to be using the following directories and urls: /var/www/yii2 for my DocumentRoot yii2.erianna.com for my hosting url Additionally, by the end of this tutorial you will be able to view a demo of the app we've made at yii2.erianna.com. Downloading Yii2 Download a copy of Yii2 from Github either by cloning the repository or by downloading a tar archive. git clone git@github.com:yiisoft/yii2.git /dir/to/yii2 or wget https://github.com/yiisoft/yii2/archive/master.zip unzip master.zip /dir/to/yii2 Once you've extracted Yii2, navigate to /dir/to/yii2/framework cd /dir/to/yii2/framework And run the following commands to setup your first webapp, providing yes to the first prompt. php yiic.php app/create /var/www/yii2 yes This is the equivalent of creating a new webapp in Yii 1.x. Now navigate to /var/www/yii2. Inside this folder you'll see one file and one folder. $ ls -l total 8 -rwxrwxrwx 1 user www-data 265 May 4 09:30 index.php drwxrwsr-x 5 user www-data 4096 May 4 09:07 protected Before we can get our site up and running, we'll need to make some modifications to our index.php file. In my opinion, there are some questionable design choices. Hopefully these will be fixed before Yii2's final release to make it more user friendly to get setup. Change your index.php to look like this. define('YII_DEBUG', true); // Change this to your actual Yii path require '/path/to/yii2/framework/yii.php'; // Change __DIR__ to __FILE__ so we can load our config file $config = require dirname(__FILE__).'/protected/config/main.php'; $config['basePath'] = dirname(__FILE__).'/protected'; $app = new \yii\web\Application($config); $app->run(); Lets break down the changes we made: // Change this to your actual Yii path require '/path/to/yii2/framework/yii.php'; First, we need to change our "require" path to point to to where our framework/yii.php is actually located at. By default, this makes the assuming it is in the current directory, It's possible it might be, but it needs to know exactly where Yii2 is located at. $config = require dirname(__FILE__).'/protected/config/main.php'; $config['basePath'] = dirname(__FILE__).'/protected'; Next, we updated our config path to use __FILE__ instead of __DIR__. We're making this change so our webapp can actually load. Before we continue, it's important to notice there's something new in Yii" Name spaces $app = new \yii\web\Application($config); The point of name spaces is to encapsulate code in logical units to prevent collision of multiple code bases. So you have two classes, both named Foo and that both have the method Bar, assuming they are both name spaces you can call both of them independently of each other as follows, without any collision of classes. $foo = new \namespace\Foo; $foo2 = new \namespace2\Foo; Name spaces are an easy way to prevent collision of code. I'd recommend you'd read up on them, since Yii2 has been name spaced. And like that, you've just created your fist web app! Navigate to where yii2 is located at, and you should see the following page. Your First Yii2 App! Unlike Yii 1.x's skeleton app, the base skeleton app for Yii2 isn't that exciting yet. Lets make it do a little more. First, open up your /protected/views/layout/main.php file, then replace it with the following code: use yii\helpers\Html as Html; ?> doctype html> html lang="$app->language?>"> head> meta charset="utf-8" /> title>php echo Html::encode(\Yii::$app->name); ?>title> link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet"> script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js">script> head> body> div class="container"> div class="navbar navbar-inverse"> div class="container"> div class="navbar-inner"> a class="brand" href="/">php echo Html::encode(\Yii::$app->name); ?>a> div> div> div> div class="content"> php echo $content?> div> div> body> html> Then refresh the page. See? Isn't everything prettier with Twitter Bootstrap? Again, not much has changed from Yii1 to Yii2. You still have $content being the variable you use for displaying content in views. Yii::app() has changed to be Yii::$app however. Again, everything in Yii2 has been name spaced, so it's important to remember to access everything by their new name space instead of just calling the raw class. Now lets do some real coding! Connecting To Your Database For this app, we'll just have a simple Posts table containing our blog posts. Creating the Database Table Login to MySQL, and create a user and database both named yii2. Then run the following command to update the db structure for yii2. DROP TABLE IF EXISTS `posts`; CREATE TABLE IF NOT EXISTS `posts` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(255) COLLATE utf8_bin NOT NULL, `content` text COLLATE utf8_bin NOT NULL, `created` datetime NOT NULL, `updated` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ; INSERT INTO `yii2`.`posts` (`id`, `title`, `content`, `created`, `updated`) VALUES ('1', 'Example Title', 'New Post', NOW(), NOW()); Updating Your Config Then, navigate to /var/www/yii2/protected/ and open up config.php in your favorite editor and replace it with the following. return array( 'id' => 'webapp', 'name' => 'My Web Application', 'components' => array( // uncomment the following to use a MySQL database 'db' => array( 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhostt;dbname=yii2', 'username' => 'yii2', 'password' => '', ), 'cache' => array( 'class' => 'yii\caching\DummyCache', ), ), ); If you're familiar with Yii2, this is a massive improvement over the hideous config files that were generated in Yii1. While the same structure is there, this is the only thing that is needed to get your database up and running. Creating a Post Model Create a new folder called models under protected, and then created a new file call Post.php in models and add the following code to it. namespace app\models; class Post extends \yii\db\ActiveRecord { /** * @return string the associated database table name */ public static function tableName() { return 'posts'; } /** * @return array primary key of the table **/ public static function primaryKey() { return array('id'); } /** * @return array customized attribute labels (name=>label) */ public function attributeLabels() { return array( 'id' => 'ID', 'title' => 'Title', 'content' => 'Content', 'created' => 'Created', 'updated' => 'Updated', ); } } If you're familiar with Yii1, the only thing that has really changed in ActiveRecord (at least in this example) is that the functions primaryKey, and tableName are now static methods. Everything else is basically the same. For the most part, ActiveRecord has remained unchanged. The most important part of this class is the inclusion of the name space app\models. This tells Yii where we can reference this file at. Unlike Yii1, where you can just call the class name, Yii2 uses a different type of auto loaded which requires you to explicitly define what classes you intent on using. While this might make development a little slower (Trying to remember to include \yii\framework\web\Html can get old really fast instead of just calling CHtml), it should make Yii2 significantly faster. Since the autoloader won't have to search through the entire framework just to get one class. At least in theory. CRUD! Now that we've name spaced our Post model, we can get to working creating our basic CRUD app. Viewing Everything First, lets start by updating our index action so that we can view everything. I like to be able to view everything from my index action, so lets start there. Open up controllers/SiteController.php and update your index action so it looks as follows: public function actionIndex() { $data = Post::find()->all(); echo $this->render('index', array( 'data' => $data )); } A couple of things to notice here. First, ::model()-> is gone. Raw model data from ActiveRecord and Model can now be accessed directly by calling the method you want information on. So $post->find()->all(). While I am personally pretty fond of Post::model()->findAll(), the new way of accessing data pretty standard and is easier to read. Secondly, findAll has been replaced by find()->all(). All find methods now stem either from find() or findBySql(). Finally, $this->render() now requires an echo in front of it. Personally, I hate this. It feels very CakePHP ish, and is in my opinion redundant. The idea behind this however is that stuff you want to be rendered to the screen should be echoed, otherwise it is simply available as a $variable for you to manipulate. Personally, I prefer the older way of rendering to a variable (passing a function parameter to the render method), but maybe it will grow on me. Now refresh the page... If you're familiar with namespaces, your probably screaming at me right now asking me why I didn't include the Post model. If you're not familiar with name spaces, you're probably confuses as to why your getting an error. The reason is simple. _You have to remember your name spaces in Yii2__. Anything you want to use, you have to explicitly define unless it already has been defined. Add the following line to top of SiteController. Then refresh the page. use app\models\Post; Now lets add some markup to display our posts. Open up protected/views/site/index.php and replace the content with the following: use yii\helpers\Html; ?> php echo Html::a('Create New Post', array('site/create'), array('class' => 'btn btn-primary pull-right')); ?> div class="clearfix">div> hr /> table class="table table-striped table-hover"> tr> td># td>Titletd> td>Createdtd> td>Updatedtd> td>Optionstd> tr> php foreach ($data as $post): ?> tr> td> php echo Html::a($post->id, array('site/read', 'id'=>$post->id)); ?> td> td>php echo Html::a($post->title, array('site/read', 'id'=>$post->id)); ?>td> td>php echo $post->created; ?>td> td>php echo $post->updated; ?>td> td> php echo Html::a(NULL, array('site/update', 'id'=>$post->id), array('class'=>'icon icon-edit')); ?> php echo Html::a(NULL, array('site/delete', 'id'=>$post->id), array('class'=>'icon icon-trash')); ?> td> tr> php endforeach; ?> table> Hmmm, looks different doesn't it! CHtml::link() is gone, and has been replaced by a helper name space called Html. Fortunately, the structure from CHtml::link to Html::a hasn't changed at all. So it's simply a matter of filling in the parameters. Read Reading is easy, so lets take care of that next. Create a new method in SiteController with the following definition: public function actionRead($id=NULL) { echo 'HelloWorld'; } Now, if you navigate to ?r=site/read&id=1. You should see HelloWorld being printed to the screen. See it? Good. That means our method is being triggered. Now lets configure it so that we can get some data from our database. First, lets add HttpException to our SiteController so that we can throw HttpExceptions if a post isn't found. use \yii\base\HttpException; Then, lets create our read action public function actionRead($id=NULL) { if ($id === NULL) { Yii::$app->session->setFlash('error', 'A post with that id does not exist'); Yii::$app->getResponse()->redirect(array('site/index')); } $post = Post::find($id); if ($post === NULL) { Yii::$app->session->setFlash('error', 'A post with that id does not exist'); Yii::$app->getResponse()->redirect(array('site/index')); } echo $this->render('read', array( 'post' => $post )); } Just for clarity, HttpException is essentially CHttpException. All we're doing is making querying the database for a post if an id of $id, and rendering it. If the post isn't found, or an id isn't provided then we're throwing an HttpException. Next, we need to create a new file protected/views/site/read.php, and add the following code to it to display our post. use yii\helpers\Html; ?> div class="pull-right btn-group"> php echo Html::a('Update', array('site/update', 'id' => $post->id), array('class' => 'btn btn-primary')); ?> php echo Html::a('Delete', array('site/delete', 'id' => $post->id), array('class' => 'btn btn-danger')); ?> div> h1>php echo $post->title; ?>h1> p>php echo $post->content; ?>p> hr /> time>Created On: php echo $post->created; ?>time>br /> time>Updated On: php echo $post->updated; ?>time> Now, on our index page, click on "Example Post". Tada! You can now view posts for your blog! Delete Deleting posts is also very simple, so we'll do that next. Create a new method with the following definition: public function actionDelete($id=NULL) { } For this method, we're going to be a little more complex. We're going to redirect the user back to the homepage after we've successfully deleted their post. Lets get started. First, lets define our method public function actionDelete($id=NULL) { if ($id === NULL) { Yii::$app->session->setFlash('error', 'A post with that id does not exist'); Yii::$app->getResponse()->redirect(array('site/index')); } $post = Post::find($id); if ($post === NULL) { Yii::$app->session->setFlash('error', 'A post with that id does not exist'); Yii::$app->getResponse()->redirect(array('site/index')); } $post->delete(); Yii::$app->session->setFlash('success', 'Your post has been successfully deleted'); Yii::$app->getResponse()->redirect(array('site/index')); } A couple things to note with Yii2. First, redirecting is now done through Yii::$app->getResponse->redirect() instead of $this->redirect(). While this makes sense from code organization perspective, it's a pain to type out. Additionally, it also gives the feeling that $app is severely overloaded. While a pain to type, it's maintained the same method definition from Yii1. Secondly, setFlash is now accessed through $app instead of app(). You should be getting the hange of that by now though. =) Now that we've handled deleting, lets go back to our protected/views/site/index.php file and catch those flash message we sent. Just add the following below the first tag if(Yii::$app->session->hasFlash('error')): ?> div class="alert alert-error"> php echo Yii::$app->session->getFlash('error'); ?> div> php endif; ?> php if(Yii::$app->session->hasFlash('success')): ?> div class="alert alert-success"> php echo Yii::$app->session->getFlash('success'); ?> div> php endif; ?> Now try deleting "Example Post". Pretty neat huh? You're getting the idea of Yii::$app now, right? Create Now lets get to the fun stuff, creating new entries in our blog. We're going to need a couple of things to post creation. First, we're going to be use ActiveForm to handle the form itself. Secondly we're going to catch catching and validating $_POST data. And finally we're going to be saving it to the database for storage. Lets get started. First, we'll need to create a view for our form. Start by creating a file protected/views/site/create.php. Since we'll be using a widget in our view, you'll also need to create a folder "assets" in the root of our web app and make it writable by your web server. Chmod 755 usually does the trick. Then add the following function definition to SiteController. public function actionCreate() { $model = new Post; if ($this->populate($_POST, $model) && $model->save()) Yii::$app->response->redirect(array('site/read', 'id' => $model->id)); echo $this->render('create', array( 'model' => $model )); } All that this does, is check if the model we're inserting is a new record, and if it is, to get the highest id in the database and add one to it, and use that for our id. Notice the new method "populate". I trid a bunch of different combinations (NULL, 0, _ for $model->id, but for some reason ActiveRecord refused to save the model with anything but 0. I have no idea why it isn't working yet). Now that that has been settled out, add the view for our create file. use yii\helpers\Html; ?> php $form = $this->beginWidget('yii\widgets\ActiveForm', array( 'options' => array('class' => 'form-horizontal'), )); ?> php echo $form->field($model, 'title')->textInput(array('class' => 'span8')); ?> php echo $form->field($model, 'content')->textArea(array('class' => 'span8')); ?> div class="form-actions"> php echo Html::submitButton('Submit', null, null, array('class' => 'btn btn-primary')); ?> div> php $this->endWidget(); ?> And there you go, you've now saved your model. But things are a little weird wouldn't you agree? For instance, why are our created and updated times all 0's? What happens if we input a blank form? Lets fix those two issues before continuing. First, we need to open up our Post model, and add the following method: public function rules() { return array( array('title, content', 'required'), ); } This method makes the title and content field required. Now when you attempt to save the model, you'll get an error if either of those fields are blank. And since we're using bootstrap, it's pretty easy to see what the error was. Give it a try! Next, we're going to auto populate our created and updated times. First, we're going to add another use line to the top of our model. use \yii\db\Expression; Second, we're going to update our beforeSave method to add these automatically for us. Inside our if ($this->isNewRecord) block, add the following line. $this->created = new Expression('NOW()'); Then, before return parent::beforeSave($insert) add: $this->updated = new Expression('NOW()'); Your final method definition should look like this: public function beforeSave($insert) { if ($this->isNewRecord) $this->created = new Expression('NOW()'); return parent::beforeSave($insert); } Now try saving again. Our model now has validation on both the title, and content fields, and will automatically update the created and update time for you. Now lets do updating. Update Our update action is going to be nearly identical to our create action. The only difference between the two is how we determine what model we're going to use. In our create action, we used. $model = new Post; In our update action, we're going to use. $model = Post::find($id); I like HTTPExceptions for stuff when it isn't found. That being said, you should probably be nice to the user and just warn them with a soft flash message instead of a hard http exception that makes it look like your site exploded. public function actionUpdate($id=NULL) { if ($id === NULL) { Yii::$app->session->setFlash('error', 'A post with that id does not exist'); Yii::$app->getResponse()->redirect(array('site/index')); } $model = Post::find($id); if ($model === NULL) { Yii::$app->session->setFlash('error', 'A post with that id does not exist'); Yii::$app->getResponse()->redirect(array('site/index')); } if ($this->populate($_POST, $model) && $model->save()) Yii::$app->response->redirect(array('site/read', 'id' => $model->id)); echo $this->render('create', array( 'model' => $model )); } Notice anything interesting? We're still using the create view in our update action because they are exactly the same. Cool huh? Sanitizing Data Input So you have everything setup now. Easy huh? But what happens if you throw the following into your title. script type="text/javascript">alert("Hello!");script> If you're like me, you probably assumed ActiveRecord would sanitize that for you. I know I certainly did. Bad news folks, it doesn't. Escape and sanitize your stuff. There are evil people about there who want to ruin you because you forgot to sanitize your user input. So, anywhere that you're outputting user inputted data, escape it using Html::encode(). To provide an example, our protected/views/site/read.php should now have output that looks as follows: h1>php echo Html::encode($post->title); ?>h1> p>php echo Html::encode($post->content); ?>p> Now when you visit that page, and some evil person has added a script tag in your form all that is seen is sanatized input. Concluding Thoughts Well there you have it. In a couple of hours you've gone from knowing nothing about Yii Framework 2 to having a very simple CRUD application. Using this knowledge you can easily scale your application to support having users, having authentication for the views, adding additional tables to your database, and even adding more powerful features. Yii2 is very similar to Yii 1.x, however there are still a lot of differences that you'll need to reload. While Yii2 isn't very well documented yet, I wrote this entire blog post just by looking at the source code on Github. The code for Yii2 is pretty well documented, and since the methods are similar to Yii 1.x, it was easy to find what I was looking for, either through examples or just the source code for various classes. If you'd like the browse the source code for this project, you can download it from Github.. If you'd like to play around with the demo itself without installing it, you can browse the app at yii2.erianna.com. The original blog post for this entry can be found on my personal blog here: Getting Started With Yii Framework 2. For more tutorials, guides, source code, and information visit my blog at https://www.erianna.com

    29
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] YiiBooster: How to implement files and images upload on TbRedactor Widget

    Introduction I have been requested to provide a tutorial on how to use the file upload feature of the TbRedactor widget, and even though I am no longer supporting the library due that the work belongs to Clevertech, I feel that I owe that to the Yii developers. So, here is the  tutorial. How to do it As you know, if you try to use TbRedactor "out of the box" and if you click on the "insert image", you will see a "popup window" as the following image: Not bad... but too plain. What about the really cool Fileupload shown on redactorJS site? How do we set it up? The answer is easier that you can imagine. In fact, the only thing that we need to tell the plugin is the URL address that will handle file and image upload processes. // with a TbActiveForm echo $form->redactorRow( $model, 'attribute_name', array( 'class'=>'span4', 'rows'=>5, 'options'=>array( 'fileUpload' => $this->createUrl('site/testFileUpload'), 'imageUpload' => $this->createUrl('site/testImageUpload'), ) ) ); // as a widget $this->widget('bootstrap.widgets.TbRedactorJs', array( 'model'=>$model, 'attribute'=>'attribute_name', 'editorOptions'=>array( 'fileUpload' => $this->createUrl('site/testFileUpload'), 'imageUpload' => $this->createUrl('site/testImageUpload'), 'width'=>'100%', 'height'=>'400px' ) )); As soon as we have that setup, the popup window will display differently: Important How to handle file uploads is out of the scope of this tutorial. If you wish to know how to handle file uploads on the server from redactorJS, I highly recommend you to read the documentation at imperavi. But wait a minute, what about if we wish to insert an image that has been previously uploaded? If we look at the redactor's site we find really cool thumbnail images to choose from. Well, is a bit tricky but not too hard. The only thing that you have to do is to provide a URL where to download the "json" file that will get the uploaded files and their location. // with a TbActiveForm echo $form->redactorRow( $model, 'attribute_name', array( 'class'=>'span4', 'rows'=>5, 'options'=>array( 'fileUpload' => $this->createUrl('site/testFileUpload'), 'imageUpload' => $this->createUrl('site/testImageUpload'), 'imageGetJson'=> $this->createUrl('site/testImageThumbs') ) ) ); // as a widget $this->widget('bootstrap.widgets.TbRedactorJs', array( 'model'=>$model, 'attribute'=>'attribute_name', 'editorOptions'=>array( 'fileUpload' => $this->createUrl('site/testFileUpload'), 'imageUpload' => $this->createUrl('site/testImageUpload'), 'imageGetJson'=> $this->createUrl('site/testImageThumbs') 'width'=>'100%', 'height'=>'400px' ) )); The following is an example action to return the thumbs and image information: public function actionTestImageThumbs() { echo json_encode(array( array( 'thumb' => '/images/image1_thumb.png', 'image' => '/images/image1_big.png', 'title' => 'Title1', // optional 'folder' => 'myFolder' // optional ), array( 'thumb' => '/images/image2_thumb.png', 'image' => '/images/image2_big.png', 'title' => 'Title2', // optional 'folder' => 'myFolder' // optional ) )); } Obviously, the above example has to contain the right resources to work but the result would endup with something similar to the following: Further Reading Imperavi Redactor Doc Settings Imperavi Redactor Doc Files Upload Imperavi Redactor Doc Images Upload web development has never been so funwww.2amigos.us

    15
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Using Google Maps in Yii Applications via Jquery

    Author: Christian Salazar Follow @salazarchris74 This a clear way to implement a human-address-based google map using a jQuery extension. It is very simple and usefull. STEP 1 put this script in your page, using a direct script insertion, or using your Yii script manager: script> $.fn.googlemap = function(){ // author: Christian Salazar christiansalazarh@gmail.com> var src=''; $(this).each(function(){ var z = $(this); var address = jQuery.trim(z.attr('streetnumber')) +'+'+jQuery.trim(z.attr('streetname')) +'+'+jQuery.trim(z.attr('cityname')) +'+'+jQuery.trim(z.attr('statecode')) +'+'+jQuery.trim(z.attr('zipcode')) ; src="https://maps.google.com/maps?" +"client=safari" +"&q="+address +"&oe=UTF-8&ie=UTF8&hq=" +"&hnear="+address +"&gl=us" +"&z="+z.attr('zoom') +"&output=embed"; z.html(""+z.attr('width')+" height=" +z.attr('height')+">"); }); return src; } script> STEP 2 In any place were you require the google map, insert a DIV or any HTML element having this attributes: div id='map' streetnumber='946' streetname='LAKE+DESTINY+RD' cityname='ALTAMONTE+SPRINGS' statecode='FL' zipcode='32714' zoom=18 width=500 height=300> div> STEP 3 Use the script, in this way: script>$('#map').googlemap();script> // you can use it in multiple selectors, // as an example: $("ul.maps li").googlemap(); // will process all LI items having the required attributes // displaying a map each. It will produce: Extras As an extra feature, the jquery extension provided here will return the URL: script> var url = $('#mymap').googlemap(); $('#mymap').parent().append("enlarge map"); script>

    16
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Date Picker by examples

    CJuiDatePicker displays a datepicker. CJuiDatePicker encapsulates the JUI datepicker plugin. Yii CJuiDatePicker: Default h1>Yii CJuiDatePicker: Defaulth1> script> $(function() { $( "#anim" ).change(function() { $( "#datepicker" ).datepicker( "option", "showAnim", $( this ).val() ); }); }); script> p>Animations:br> select id="anim"> option value="show">Show (default) => showoption> option value="slideDown">Slide down => slideDownoption> option value="fadeIn">Fade in => fadeInoption> option value="blind">Blind (UI Effect) => blindoption> option value="bounce">Bounce (UI Effect) => bounceoption> option value="clip">Clip (UI Effect) => clipoption> option value="drop">Drop (UI Effect) => dropoption> option value="fold">Fold (UI Effect) => foldoption> option value="slide">Slide (UI Effect) => slideoption> option value="">Noneoption> select> p> php $this->widget('zii.widgets.jui.CJuiDatePicker',array( 'name'=>'datepicker', // additional javascript options for the date picker plugin 'options'=>array( 'showAnim'=>'slide',//'slide','fold','slideDown','fadeIn','blind','bounce','clip','drop' ), 'htmlOptions'=>array( 'style'=>'height:20px;background-color:green;color:white;', ), )); ?> Yii CJuiDatePicker: Inline h1>Yii CJuiDatePicker: Inlineh1> php $this->widget('zii.widgets.jui.CJuiDatePicker',array( 'name'=>'datepicker-Inline', 'flat'=>true,//remove to hide the datepicker 'options'=>array( 'showAnim'=>'slide',//'slide','fold','slideDown','fadeIn','blind','bounce','clip','drop' ), 'htmlOptions'=>array( 'style'=>'' ), )); ?> Yii CJuiDatePicker: Show/Select Other Month Dates h1>Yii CJuiDatePicker: Show/Select Other Month Datesh1> php $this->widget('zii.widgets.jui.CJuiDatePicker',array( 'name'=>'datepicker-other-month', 'flat'=>true,//remove to hide the datepicker 'options'=>array( 'showAnim'=>'slide',//'slide','fold','slideDown','fadeIn','blind','bounce','clip','drop' 'showOtherMonths'=>true,// Show Other month in jquery 'selectOtherMonths'=>true,// Select Other month in jquery ), 'htmlOptions'=>array( 'style'=>'' ), )); ?> Yii CJuiDatePicker: Display Button Bar(showButtonPanel) Yii CJuiDatePicker: Display Button Bar(showButtonPanel) $this->widget('zii.widgets.jui.CJuiDatePicker',array( 'name'=>'datepicker-showButtonPanel', 'value'=>date('d-m-Y'), 'options'=>array( 'showAnim'=>'slide',//'slide','fold','slideDown','fadeIn','blind','bounce','clip','drop' 'showButtonPanel'=>true, ), 'htmlOptions'=>array( 'style'=>'' ), )); ?> Yii CJuiDatePicker: Display Month & Year Menus h1>Yii CJuiDatePicker: Display Month & Year Menush1> php $this->widget('zii.widgets.jui.CJuiDatePicker',array( 'name'=>'datepicker-month-year-menu', 'flat'=>true,//remove to hide the datepicker 'options'=>array( 'dateFormat' => 'yy-mm-dd', 'showAnim'=>'slide',//'slide','fold','slideDown','fadeIn','blind','bounce','clip','drop' 'changeMonth'=>true, 'changeYear'=>true, 'yearRange'=>'2000:2099', 'minDate' => '2000-01-01', // minimum date 'maxDate' => '2099-12-31', // maximum date ), 'htmlOptions'=>array( 'style'=>'' ), )); ?> Yii CJuiDatePicker: Display Multiple Months h1>Yii CJuiDatePicker: Display Multiple Monthsh1> php $this->widget('zii.widgets.jui.CJuiDatePicker',array( 'name'=>'datepicker-multiple-month', 'flat'=>true,//remove to hide the datepicker 'options'=>array( 'numberOfMonths'=>2, 'showButtonPanel'=>true, ), 'htmlOptions'=>array( 'style'=>'' ), )); ?> Yii CJuiDatePicker: Date Format h1>Yii CJuiDatePicker: Date Formath1> script> $(function() { $( "#date-format" ).change(function() { $( "#datepicker-date-format" ).datepicker( "option", "dateFormat", $( this ).val() ); }); }); script> p>Format options:br /> select id="date-format"> option value="mm/dd/yy">Default - mm/dd/yyoption> option value="yy-mm-dd">ISO 8601 - yy-mm-ddoption> option value="d M, y">Short - d M, yoption> option value="d MM, y">Medium - d MM, yoption> option value="DD, d MM, yy">Full - DD, d MM, yyoption> option value="'day' d 'of' MM 'in the year' yy">With text - 'day' d 'of' MM 'in the year' yyoption> select> p> php $this->widget('zii.widgets.jui.CJuiDatePicker',array( 'name'=>'datepicker-date-format', 'value'=>date('d/m/Y'), 'options'=>array( 'showButtonPanel'=>true, 'dateFormat'=>'mm/dd/yy',//Date format 'mm/dd/yy','yy-mm-dd','d M, y','d MM, y','DD, d MM, yy' ), 'htmlOptions'=>array( 'style'=>'' ), )); ?> Yii CJuiDatePicker: Date Range h1>Yii CJuiDatePicker: Date Rangeh1> php $this->widget('zii.widgets.jui.CJuiDatePicker',array( 'name'=>'datepicker-min-max', 'value'=>date('d-m-Y'), 'options'=>array( 'showButtonPanel'=>true, 'minDate'=>-5, 'maxDate'=>"+1M +5D", ), 'htmlOptions'=>array( 'style'=>'' ), )); ?> Reference: http://www.codexamples.com/101/cjui-datepicker/ http://yii.codexamples.com/v1.1/CJuiDatePicker/

    14
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] using jqbargraph to create beautiful graphs

    If you are about to create a graph, the best option i would suggest is the jqbargraph. The advantages of jqbargraph is its very easy to install it is very simple to use. it contains 3 types of graph (simple multi and stacked) easy customization like colors spaces etc.. So to begin with.. First you need to download the extension and put this is your extensions folder Now like most of the other widgets you need to configure it in config/main file 'import'=>array( 'application.extensions.jqBarGraph.*', ), Now you can use the jqbargraph by calling the widget $this->widget('jqBarGraph',array(parameters)); Now the parameters may vary based on the type of graph you need lets start with the simple graph. this one is the most commonly used graph if you are using simple graph you should give the first parameter type => simple The other parameters are color1: color of the first bar. color2:color of the second bar. width:width of each bar. space:space between each bar. title:title of the graph, will be shown on the top of the graph. values: Most important, should be an multidimensional array like this. array(array(200,'june'),array(129,'july'),array(143,'august'),array(159,'september')); so the final code will be $array=array(array(200,'june'),array(129,'july'),array(143,'august'),array(159,'september')); $this->widget('jqBarGraph', array('values'=>$array, 'type'=>'simple', 'width'=>200, 'color1'=>'#122A47', 'color2'=>'#1B3E69', 'space'=>5, 'title'=>'simple graph')); Now second type of graph is the multigraph In order to use multigraph the type you should give is type=>multi the other attributes are much similar except we need to give arrays for the colors and legends . the final code will be like this $array2=array(array(array(5,15,26),2008),array(array(14,6,26),2009),array(array(17,3,26),2010)); $colors=array('#3D0017','#6B0E1D','#AB2522'); $legends=array('legend1','legend2','legend3'); $this->widget('jqBarGraph', array('values'=>$array2, 'type'=>'multi', 'width'=>500, 'colors'=>$colors, 'legend'=>true, 'legends'=>$legends, 'title'=>'multi graph')); The third type of graph is stacked graph. This has the same parameters as the multigraph except the type the type should be type => stacked so the final code will be like this $array3=array(array(array(5,15,26),2008),array(array(14,6,26),2009),array(array(17,3,29),2010)); $colors2=array('#242424','#437346','#97D95C'); $legends2=array('legend1','legend2','legend3'); $this->widget('jqBarGraph', array('values'=>$array3, 'type'=>'stacked', 'width'=>500, 'colors'=>$colors2, 'legend'=>true, 'legends'=>$legends2, 'title'=>'stacked graph')); you can see the live demo here regards Mahesh E.U

    6
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] jQuery UI Datepicker

    We all love the convenient gadget, namely jQuery UI Datepicker as an input element for date. Yii supports it as CJuiDatePicker. Let's see how to use it. Basics Imagine we have a text field for date in our form. div class="row"> php echo $form->labelEx($model,'date_from'); ?> php echo $form->textField($model, 'date_from', array( 'size' => 10, 'maxlength' => 10, )); ?> php echo $form->error($model,'date_from'); ?> div> As you see, we are using a CActiveForm here. And now replace the text field with a CJuiDatePicker. div class="row"> php echo $form->labelEx($model,'date_from'); ?> php $this->widget('zii.widgets.jui.CJuiDatePicker', array( 'model' => $model, 'attribute' => 'date_from', 'htmlOptions' => array( 'size' => '10', // textField size 'maxlength' => '10', // textField maxlength ), )); ?> php echo $form->error($model,'date_from'); ?> div> Basically this is all that you have to do. You don't need to load the javescript files (i.e. jQuery and jQuery UI) and CSS files by yourself. You don't need to write a text field by yourself. You don't need to write a script to convert the text field into Datepicker by yourself. CJuiDatePicker will do all the tasks for you. (Well, things could be a little complicated in some situations. We will discuss it later.) In the example above, we are using CJuiDatePicker like a CActiveForm::textField, setting $model to model and 'date_from' attribute of $model to attribute. By this settings, CJuiDatePicker will use the same logic as CActiveForm::textField to name the input field and connect the value to the attribute of the model. If you don't use CActiveForm, you may use name and value to specify the name of the input field and the value of it. It correspond to the usage of CHtml::textField. $this->widget('zii.widgets.jui.CJuiDatePicker', array( 'name' => 'date_from', 'value' => $fromDateValue, 'htmlOptions' => array( 'size' => '10', // textField size 'maxlength' => '10', // textField maxlength ), )); Note: You have to use either model-attribute pair or name-value pair. They are mutually exclusive. Do not mix them up. Localization Now, let's localize the Datepicker. $this->widget('zii.widgets.jui.CJuiDatePicker', array( 'model' => $model, 'attribute' => 'date_from', 'language' => 'ja', 'i18nScriptFile' => 'jquery.ui.datepicker-ja.js', 'htmlOptions' => array( 'size' => '10', 'maxlength' => '10', ), )); We have to specify 'language' and 'i18nScriptFile'. Theming And we are applying a jQuery UI theme. $this->widget('zii.widgets.jui.CJuiDatePicker', array( 'model' => $model, 'attribute' => 'date_from', 'language' => 'ja', 'i18nScriptFile' => 'jquery.ui.datepicker-ja.js', 'themeUrl' => Yii::app()->baseUrl . '/css/jui', 'theme' => 'softark', 'cssFile' => 'jquery-ui-1.9.2.custom.css', 'htmlOptions' => array( 'size' => '10', 'maxlength' => '10', ), )); We are in the assumption that '/css/jui' holds a theme named 'softark'. You have to create a jQuery UI theme using ThemeRoller. It's not quite easy to create a good looking theme, though. Options We can set various options. $this->widget('zii.widgets.jui.CJuiDatePicker', array( 'model' => $model, 'attribute' => 'date_from', 'language' => 'ja', 'i18nScriptFile' => 'jquery.ui.datepicker-ja.js', 'themeUrl' => Yii::app()->baseUrl . '/css/jui', 'theme' => 'softark', 'cssFile' => 'jquery-ui-1.9.2.custom.css', 'options' => array( 'showOn' => 'both', // also opens with a button 'dateFormat' => 'yy-mm-dd', // format of "2012-12-25" 'showOtherMonths' => true, // show dates in other months 'selectOtherMonths' => true, // can seelect dates in other months 'changeYear' => true, // can change year 'changeMonth' => true, // can change month 'yearRange' => '2000:2099', // range of year 'minDate' => '2000-01-01', // minimum date 'maxDate' => '2099-12-31', // maximum date 'showButtonPanel' => true, // show button panel ), 'htmlOptions' => array( 'size' => '10', 'maxlength' => '10', ), )); The options are all up to your choice. Please see DatePicker DEMO and API for detailed information. Note: My experience tells that the Datepicker works more stable without 'showAnim' option. Especially when you want to use 2 or more instances on the same screen, you would be better not set this option. Adjusting the appearance But, we don't like the appearance of it at all. The header is divided into 2 rows because the dropdowns of year and month are a little too large. And we would like the font to be a little smaller. Hmm, we have to tweak the CSS that ThemeRoller has created. /* Component containers ----------------------------------*/ /* --- delete : use the default font of my site css --- .ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; } .ui-widget .ui-widget { font-size: 1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; } */ ... /* --- add : font should be a little smaller --- */ #ui-datepicker-div { font-size: 80%;} button.ui-datepicker-trigger { font-size: 80%; line-height: 1.4em; } ... /* --- layout of year and month ... have to modify a bit --- .ui-datepicker select.ui-datepicker-month, .ui-datepicker select.ui-datepicker-year { width: 49%;} */ .ui-datepicker select.ui-datepicker-month { with: 35%; } .ui-datepicker select.ui-datepicker-year { width: 40%; } /* --- for fxxking stupid browsers --- */ * html .ui-datepicker .ui-datepicker-title select.ui-datepicker-month { width: 30%; } * html .ui-datepicker .ui-datepicker-title select.ui-datepicker-year { width: 35%;} /* --- highliting --- */ .ui-datepicker .ui-state-active, .ui-datepicker .ui-state-active.ui-state-highlight { border-color: #0b5110;} .ui-datepicker .ui-state-highlight { border-color: #448844;} So, the boring part of the task has been done. Of course you have to do your own job here. There's no standard way of doing it. Holidays I'm going to use GCalHolidays.js. It will enable you to color Sundays, Saturdays and Japanese Holidays with different colors. Yes, I'm sorry, this part is Japanese specific. But you may find your locale specific counterpart somewhere on the web. Yii::app()->cientScript->registerScriptFile( Yii::app()->baseUrl . '/js/GCalHolidays.js', CClientScript::POS_END ); Inside an AJAX updated area In today's web applications, it's a common practice to update/replace the content of a specific area using AJAX. And if you want to use Datepicker inside such an area (e.g. in a form that will be ajax updated), you will need some extra work. jQuery UI Datepicker modifies the existing HTML code to transform the ordinary text field into a Datepicker. So when the HTML code has been updated by an AJAX, the Datepicker will return to an plain text field. You may encounter an issue like this: the Datepicker works just fine when the page has been loaded for the first time, but after you have done something in the page the Datepicker won't work anymore. Most probably the cause of the issue is that the HTML code has been updated by AJAX and the Datepicker has been reset to the plain text field. To solve this kind of issue, we have to convert the plain text field to a Datepicker again after every ajax updating. There are 2 ways to do that: Include a script to re-create the Datepicker in the AJAX response. Manually re-create the Datepicker after AJAX updating. I don't have much to say about the 1st approach, because I've never used it. Probably you have to set the 4th parameter of Controller::renderPartial() to true to include the script in AJAX response. But, at the same time, you have to tweak CClientScript::scriptMap to avoid the duplication of jQuery and jQuery UI. ... I'm not sure. Personally I feel this approach is tricky, hacky and unstable. I don't like it. I prefer the 2nd approach. I will not include any javascript in the response from the server. It goes like this: $('#submit-button').click(function() { // post the form content by ajax $.ajax({ 'type' : 'POST', 'url' : 'foo-update', 'dataType' : 'json', 'data' : $('#foo-form').serialize(), 'success' : function(data){ // update the form $('#foo-form').html(data.contents); // re-create Datepicker $('#foo-form .d-picker').datepicker(); } }); }); It's just a rough skech, but the point is that we call datepicker() function of jQuery UI after the AJAX updating to re-create the Datepicker. Yes, I'm doing a pure jQuery programming here. Although usually the jQuery support of Yii is quite convenient and useful, the things will be much easier with plain jQuery programming when the things got a little complicated. But I will continue to use CJuiDatePicker for the initial loading of the Datepicker, because it's much more easy. And the following is a sample code to create a Datepicker when it has to be updated by AJAX. $this->widget('zii.widgets.jui.CJuiDatePicker', array( ... 'defaultOptions' => array( 'showOn' => 'both', ... ... more options here ... ... ), 'htmlOptions' => array( ... 'class' => 'd-picker', ), )); We set 'class' in 'htmlOptions' because we want to select this element using jQuery. Of course you may use 'id' instead. And we use 'defaultOptions' instead of 'options'. By doing this, we will be able to call datepicker() function of jQuery UI without explicitly specifying the options. Japanese Translation: Yii で jQuery UI Datepicker を使う

    10
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Email template functionality with manage content from database

    Quick view to Admin side I hadn't specify whole flow as I assume you know yii crud flow well, and Quick understand of my specified admin flow.. :) I use Mailer Extension for email. Create table to store email template content as below, Make pre-define entry in database, so admin can edit particular template contant with specific position of replace variables.. Edit page shown as below. Quick view to Front side Create template file any where in front side (i.e template/templatecontact) as below, table style="width: 100%"> tr> td> php $path = $_SERVER['HTTP_HOST']; ?> a href="$_SERVER['HTTP_HOST']; ?>">img src="$_SERVER['HTTP_HOST']; ?>/img/logo.png"/> a> td> tr> tr> td> table style="border: solid 2px; border-color: #ADCE97; width: 100%"> tr> td> div style="margin: 5px 0px 5px 0px;"> ##CONTENT## div> td> tr> table> td> tr> table> Below code is controller where your template parameters are post (i.e site/contact) if(isset($_POST['Contact'])) { $model->attributes=$_POST['Contact']; // Set this if you save email data OR use direct $_POST data $adminEmail = "AdminEmail [AT] xyzcompanyadminemail . com"; //Receiver $dbTemplateModel = Template::model()->findByAttributes(array('key'=>'CONTACT-REQ-USER')); // From here you can get template content set by admin CONTACT-REQ-USER is key in db $message = $dbTemplateModel->content; $message = str_replace("##MESSAGE##", nl2br($model->message), $message); //Replace ##MESSAGE## by user send message $message = str_replace("##USERNAME##", $model->name, $message); $message = str_replace("##USEREMAIL##", $model->email, $message); $emailTemplate = $this->renderPartial('template/templatecontact',array(),true); //Getting email template content $message = str_replace("##CONTENT##", $message, $emailTemplate); //Replacing ##CONTENT## in email template by $message data $mailer = Yii::createComponent('application.extensions.mailer.EMailer'); $mailer->IsHTML(true); //HTML format $mailer->From = $model->email; //Sender $mailer->AddReplyTo($model->email); //Sender $mailer->AddAddress($adminEmail); //Receiver $mailer->FromName = $model->name; $mailer->CharSet = 'UTF-8'; $mailer->Subject = Yii::t('contact-req', $model->subject); $mailer->Body = $message; $mailer->Send(); Plz comment for any query or updation.

    5
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Custom column in TbGridView with icon by condition, find out icon class glyphicons easy (YiiBooster)

    First of all, You have to find out the class of the desired icon, so visit the http://getbootstrap.com/2.3.2/base-css.html#icons Get the class of corresponding icon You have to create either your CButtonColumn extension or create a simple logic inside of the value column See an example of a custom column array( //the header of the column 'header' => 'custom', //make sure that the below text will be displayed as html 'type'=>'raw', //make a logic decision: if 'anAttribute' value for each data-row is in a region values choose the first icon. Otherwise choose another one 'value' => '($data->anAttribute > 10) ? "\"#\";>\"icon-gift\">" : "\"#\";>\"icon-camera\">"', ), A complete example using bootstrap.widgets.TbGridView $this->widget('bootstrap.widgets.TbGridView', array( 'id' => 'name-grid', 'dataProvider' => $model->search(), 'filter' => $model, 'type' => 'striped bordered condensed', 'columns' => array( 'id', 'name1', 'name2', 'name3', array( 'header' => 'custom', 'type'=>'raw', 'value' => '($data->field1 > 10) ? "\"icon-gift\">" : "\"icon-camera\">"', ), ... ))); Enjoy! :)

    15
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] CGridView Date Range Without Cookies or Session (External Filtering)

    Here's a tutorial on how to create a CGridView with external date filters the trick is to create hidden columns within the CGridView Filters something like in the example below: first we have to create a Class File for the column that we will put our hidden fields you can save this file under protected/components folder this tutorial does not only apply to date filtering but also to other forms of filtering that is outside the CGridView Date Column Class class DateColumn extends CDataColumn{ //put your code here public $from_date; public $to_date; public function renderFilterCellContent() { echo CHtml::activeDateField($this->grid->filter, $this->name, array('id'=>false)); if(isset($this->from_date)) echo CHtml::activeHiddenField($this->grid->filter,$this->from_date); if(isset($this->to_date)) echo CHtml::activeHiddenField($this->grid->filter,$this->to_date); } } View Now we have to edit our CGridView file and make our date column to use this class file i am using the yii's default admin.php and _search.php $this->widget('zii.widgets.grid.CGridView', array( 'id' => 'opportunity-grid', 'dataProvider' => $model->search(), 'filter' => $model, 'columns' => array( array( 'name' => 'name', ), 'amount', array( //here is where we use our DateColumn class 'class'=>'DateColumn', 'name'=>'close_date', 'from_date'=>'start_date', 'to_date'=>'end_date' ), array( //another example of customized column 'class'=>'OpportunityStageColumn', 'name' => 'stage', 'filter' => $stage_list, 'closed'=>'closed', 'open'=>'open', 'value' => '$this->filter[$data->stage]', ), ), )); The extended filter form (i placed this inside my _search.php) $form = $this->beginWidget('CActiveForm', array( 'method' => 'get', 'id'=>'extended-filters' )); //you can replace the DateField inputs with CJuiDatePicker echo $form->dateField($model, 'start_date'); echo $form->dateField($model, 'end_date'); echo $form->submitButton(); if you don't have, you can add the following line of code to your admin.php this makes our form above submit via ajax and then reload the grid with the response data Yii::app()->clientScript->registerScript('search', " $('#extended-filters').submit(function(){ $('#opportunity-grid').yiiGridView('update', { data: $(this).serialize() }); return false; }); "); Model we just now have to add the two attributes class Opportunity extends CActiveRecord{ public $start_date; public $end_date; then don't forget to add the validation rules public function rules(){ return array(.... . . array('start_date, end_date','safe','on'=>'search') ); } public function search() { . . if ($this->start_date != null) { $criteria->addCondition("close_date>=:from"); $criteria->params += array('from' => date('Y-m-d', strtotime($this->start_date))); } if ($this->end_date != null) { $criteria->addCondition("close_date"); $criteria->params += array('to' => date('Y-m-d', strtotime($this->end_date))); } done!

    8
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Email function at Contact page

    ***note : only for linux users. **you should following steps.. step-1: install ssmtp on your computer by running following command. **sudo apt-get install ssmtp** ### step-2: now change in ssmtp.conf (/etc/ssmtp/ssmtp.conf) # # Config file for sSMTP sendmail # # The person who gets all mail for userids ** **step-3: ** now change in php.ini (/etc/php5/apache2/php.ini) **sendmail_path = /usr/sbin/ssmtp -t -i** and then check it by write simple file in php which contain echo phpinfo(); step-4: now change in main.php (/protected/config/main.php) 'params'=>array( // this is used in contact page 'adminEmail'=>'### **webmaster@example.com**', ), put your email instead of webmaster@example.com. and run and test your contact.php .... you find email at your email id....._cool naa_:-) for more information go on : my blog...

    3
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Custom Login Error Messages

    Customizing Errors for Login Authentication The Yii Framework is very powerful and it provides a lot of functionality right from the pre-built webapp. One of the nice things that is already established for you as a developer is the Login authentication. While the default configuration simply sets it up to run against an array of hard coded usernames and passwords, the Yii Blog Tutorial provides a how to in connecting that login authentication method to a database so you can run your logins against the registered users. Talk about sweet deal. But beyond the tutorial, one of the common things that developers seem to want to do after customizing the login authentication of CUserIdentity, is to customize the error messages that are returned from the login portal. It's a valid desire as many developers want to add a multitude of variables to their sign in process. A common example is if you use email validation by emailing a unique activation code. So logically you will run a check of if your user is active or not before allowing them to log in. But how do we modify the error message to signify to the user they need to activate that id? That's the goal of this tutorial. Let's dive in. There are actually several key things that need to be adjusted in order to make a custom error message for the login portal. They are simple but they will drive you nuts unless you can follow the code to establish just why you get the behaviour you do. This is something that not every developer is good at, especially if you don’t have a lot of experience coding in an object oriented fashion. So this tutorial will do a walkthrough of not only how to change those error messages, but also how to follow the code so you can figure those things out as you program. We’ll start with taking a look at the UserIdentity Component because this is where it all starts. By default the following code is what you have within the UserIdenity class found in the Component folder hierarchy. UserIdentity Component class UserIdentity extends CUserIdentity { /** * Authenticates a user. * The example implementation makes sure if the username and password * are both 'demo'. * In practical applications, this should be changed to authenticate * against some persistent user identity storage (e.g. database). * @return boolean whether authentication succeeds. */ public function authenticate() { $users=array( // username => password 'demo'=>'demo', 'admin'=>'admin', ); if(!isset($users[$this->username])) $this->errorCode=self::ERROR_USERNAME_INVALID; else if($users[$this->username]!==$this->password) $this->errorCode=self::ERROR_PASSWORD_INVALID; else $this->errorCode=self::ERROR_NONE; return !$this->errorCode; } } You can already see how there is multiple errorCode references there. However when you do a login and say enter the wrong user name (or really an invalid/unregistered one) you get a generic error code that doesn't really clarify what the issue is. See below. So how do we fix that? Well we have to establish why it's doing it in the first place. That starts by investigating the class responsible for outputting the form. In this case it links to the LoginForm. Now we could show the view code of the LoginForm but understanding MVC architecture, the error code settings will not be defined in the view. They could be set in the controller (which would be sitecontroller) but because an error value is just that, a value (thus a property of a class), there's a good chance this setting is set in the model. So we take a look at the LoginForm model. LoginForm Model class LoginForm extends CFormModel { public $username; public $password; public $rememberMe; private $_identity; /** * Declares the validation rules. * The rules state that username and password are required, * and password needs to be authenticated. */ public function rules() { return array( // username and password are required array('username, password', 'required'), // rememberMe needs to be a boolean array('rememberMe', 'boolean'), // password needs to be authenticated array('password', 'authenticate'), ); } /** * Declares attribute labels. */ public function attributeLabels() { return array( 'rememberMe'=>'Remember me next time', ); } /** * Authenticates the password. * This is the 'authenticate' validator as declared in rules(). */ public function authenticate($attribute,$params) { if(!$this->hasErrors()) { $this->_identity=new UserIdentity($this->username,$this->password); if(!$this->_identity->authenticate()) $this->addError('password','Incorrect username or password.'); } } /** * Logs in the user using the given username and password in the model. * @return boolean whether login is successful */ public function login() { if($this->_identity===null) { $this->_identity=new UserIdentity($this->username,$this->password); $this->_identity->authenticate(); } if($this->_identity->errorCode===UserIdentity::ERROR_NONE) { $duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days Yii::app()->user->login($this->_identity,$duration); return true; } else return false; } } If you follow the code you'll find the following in the authenticate function: if(!$this->_identity->authenticate()) $this->addError('password','Incorrect username or password.'); There's our error! So how can we customize this? If you try to make changes as it stands, assuming you don't get any errors you will notice that you can only change that string there, you cannot add multiple types of errors (which is what we want). If you try to add multiple types of errors you generally get a non-responsive login form where it looks like it takes the values but does nothing. That would be because it's actually spitting out an error to you (if the login is invalid) but doesn't know how to tell you that because of the code adjustments made in the authenticate function. So why can't we add more than one error? This is because of how the relationship returns back from the method call being made there. If you take a look at the login function you see that it actually makes an if case to instantiate the class of UserIdentity, which is what processes the login. It also calls the authenticate function of UserIdentity (not to be confused with the authenticate function used as a validator in LoginForm) to see if the login attempt is successful. The point of the LoginForm authenticate function then is to determine if there are any errors. When you follow the code you can establish that our next step is to revisit the UserIdentity component. Before we go, let's look at the code of the if statement in the authenticate function of LoginForm one more time. if(!$this->_identity->authenticate()) This is important to notice because what that evaluates as is, "if not this", implying that the result of _identity->authenticate() is a boolean (which it is). By looking in the UserIdentity component class we confirm this. if(!isset($users[$this->username])) $this->errorCode=self::ERROR_USERNAME_INVALID; else if($users[$this->username]!==$this->password) $this->errorCode=self::ERROR_PASSWORD_INVALID; else $this->errorCode=self::ERROR_NONE; return !$this->errorCode; What shows there is that if the username or the password is wrong we have an "error" constant association. But when we return that error constant, how come we only get 1 error value? It's because we are only passing a true or false condition. We need to modify this return to make it so it returns the actual value of the constant. // need to modify this return !$this->errorCode; // to this return $this->errorCode; Now let's go back to the LoginForm and look at our authenticate function there: /** * Authenticates the password. * This is the 'authenticate' validator as declared in rules(). */ public function authenticate($attribute,$params) { if(!$this->hasErrors()) { $this->_identity=new UserIdentity($this->username,$this->password); // This value right here depends on what we changed! if(!$this->_identity->authenticate()) $this->addError('password','Incorrect username or password.'); } } Tracing Back Inheritance We now have to modify the if statement. It's a change that takes it from evaluating a boolean to evaluating an actual value. Before we do that however, we need to know what the values are! This unfortunately requires you to follow back each case of the inheritance to find out where things like the constant ERROR_NONE, ERROR_USERNAME_INVALID etc. are. Based on where we see ERROR_NONE used we have to check out the UserIdentity class. When we see no definition of constants (by means of const NAME=VALUE), we have to look at the inheritance. class UserIdentity extends CUserIdentity So UserItentity extends CUserIdentity, which we have to find that class. This class is part of the Yii framework so we have to investigate the Yii folders (outside of our webapp) to find what we want. CUserIdentity can be found in /framework/web/auth/ When you open up the CUserIdentity.php file you won't find any definition to the constants but you do find another Extension: class CUserIdentity extends CBaseUserIdentity Now lucky for us the CBaseUserIdentity.php resides in the same folder, when we open that up we at last have finally found our constants: abstract class CBaseUserIdentity extends CComponent implements IUserIdentity { const ERROR_NONE=0; const ERROR_USERNAME_INVALID=1; const ERROR_PASSWORD_INVALID=2; const ERROR_UNKNOWN_IDENTITY=100; /** * @var integer the authentication error code. If there is an error, the error code will be non-zero. * Defaults to 100, meaning unknown identity. Calling {@link authenticate} will change this value. */ public $errorCode=self::ERROR_UNKNOWN_IDENTITY; Perfect! So now we know what those values are that are associated to the constants. We also learn that errorCode defaults to 100, implying an Unknown Identity error. That means we can go back to our LoginForm and fix the authenticate function. Customizing the Errors // We need to change this public function authenticate($attribute,$params) { if(!$this->hasErrors()) { $this->_identity=new UserIdentity($this->username,$this->password); if(!$this->_identity->authenticate()) $this->addError('password','Incorrect username or password.'); } } // To something like this public function authenticate($attribute,$params) { if(!$this->hasErrors()) { $this->_identity=new UserIdentity($this->username,$this->password); if($this->_identity->authenticate() == 1) $this->addError('username','Invalid username.'); else if($this->_identity->authenticate() == 2) $this->addError('password','Incorrect password.'); } } Now a proper reference would use the constant variable declaration rather than the value but I choose to show you in the value form so you can corrolate what you're evaluating (and thus what's being returned from the authenticate function in UserIdentity). However if you wanted to put in the proper coding it would be defined just like it is shown in the LoginForm login function: if($this->_identity->errorCode===UserIdentity::ERROR_NONE) In our case we would be using UserIdentity::ERROR_USERNAME_INVALID or UserIdentity::ERROR_PASSWORD_INVALID like so: if($this->_identity->authenticate() == UserIdentity::ERROR_USERNAME_INVALID) $this->addError('username','Invalid username.'); else if($this->_identity->authenticate() == UserIdentity::ERROR_PASSWORD_INVALID) $this->addError('password','Incorrect password.'); **Congratulations you have successfully changed the error messages to have multiple types of errors defined and displayed! ** Making your own Custom Errors for Login Authentication But what about making your own error and thus own error message? That's simple, now that we have the framework in place to customize and evaluate errors, we just need to define our own error. We'll take the Blog Tutorials example of UserIdentity to reference a database type login authentication and we'll make a custom error for if a user account "isActive". This of course implies that you have a database field labeled isActive and that it contains a true or false value (1 or 0) in order to process. The Blog Tutorial UserIdentity: class UserIdentity extends CUserIdentity { private $_id; public function authenticate() { $username=strtolower($this->username); $user=User::model()->find('LOWER(username)=?',array($username)); if($user===null) $this->errorCode=self::ERROR_USERNAME_INVALID; else if(!$user->validatePassword($this->password)) $this->errorCode=self::ERROR_PASSWORD_INVALID; else { $this->_id=$user->id; $this->username=$user->username; $this->errorCode=self::ERROR_NONE; } return $this->errorCode==self::ERROR_NONE; } public function getId() { return $this->_id; } } First we need to change this by defining our own constant. Then we need to change the logic flow by assessing the error to a value, in our case isActive to 0 (false) or 1 (true). Finally we need to make sure that we change the return statement to return the value of the error constant not just whether it passes or not. class UserIdentity extends CUserIdentity { // Define your Constant(s) const ERROR_USERNAME_NOT_ACTIVE = 3; private $_id; public function authenticate() { $username=strtolower($this->username); $user=User::model()->find('LOWER(username)=?',array($username)); if($user===null) $this->errorCode=self::ERROR_USERNAME_INVALID; else if(!$user->validatePassword($this->password)) $this->errorCode=self::ERROR_PASSWORD_INVALID; // Add in the logic condition else if($user->isActive == 0) $this->errorCode=self::ERROR_USERNAME_NOT_ACTIVE; else { $this->_id=$user->id; $this->username=$user->username; $this->errorCode=self::ERROR_NONE; } // Change the return statement to return the value not just a pass condition // was: return $this->errorCode==self::ERROR_NONE; return $this->errorCode; } public function getId() { return $this->_id; } } Finally we need to go back to our LoginForm and change / add our custom error. Remember to switch in the constants as oppose to the numerical values. It's just good practice. public function authenticate($attribute,$params) { if(!$this->hasErrors()) { $this->_identity=new UserIdentity($this->username,$this->password); if($this->_identity->authenticate() == 1) $this->addError('username','Invalid username.'); else if($this->_identity->authenticate() == 2) $this->addError('password','Incorrect password.'); // Your Custom Error :) else if($this->_identity->authenticate() == 3) $this->addError('username', 'Username is currently not active, please activate using the activation URL in your email and try again.'); } } The final result is: One final thing to note is that the addError pulls an attribute value first, here you see 'username' or 'password'. These reference to which field to show the error under. In our case with our custom value we know the user authenticates properly and exist in our DB, they just haven't activated their account yet. As such we label the error to the 'username'. That's it for the tutorial, I hope you learned a lot in understanding how to follow the logical flow of code assignments and debugging the functions, variables and classes in this case. I also hope this helps you put to good use how to modify your own custom errors into the login authentication process. Thanks for reading! ~ Whoopass

    2
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] How to create CJui Tabs : Render partial, Ajax tabs, color tabs

    Hey guys, today we will show you how to make a Yii CJuitabs as example. Some feature cases such as Static tabs, render partial tabs, Ajax tabs, color tabs... You can see our code, there are simple 3 steps to make it work. **Note: ** Working for Yiiframework version 1.x In view.php h1>Default CJuiTabs: Static, render partial, Ajax tabh1> php $this->widget('zii.widgets.jui.CJuiTabs',array( 'tabs'=>array( 'StaticTab '=>'Content for tab 1', 'StaticTab With ID'=>array('content'=>'Content for tab 2 With Id' , 'id'=>'tab2'), 'Render Partial'=>array('id'=>'test-id','content'=>$this->renderPartial( '_renderpage', array('Values'=>'This Is My Renderpartial Page'),TRUE )), // panel 3 contains the content rendered by a partial view 'AjaxTab'=>array('ajax'=>$this->createUrl('ajax')), ), // additional javascript options for the tabs plugin 'options'=>array( 'collapsible'=>true, ), 'id'=>'MyTab-Menu', )); ?> br /> h1>Dynamic Yii CJui Tabs Menu With Color h1> php $tablist=array("Red","Green","Blue"); foreach($tablist as $tabs){ $css=''; if($tabs=='Red'){$css='color:red;';} else if($tabs=='Green'){$css='color:green;';} else if($tabs=='Blue'){$css='color:blue';} $tabarray["$tabs"]="$tabs Color"; } ?> php $this->widget('zii.widgets.jui.CJuiTabs',array( 'tabs'=>$tabarray, // additional javascript options for the accordion plugin 'options' => array( 'collapsible' => true, ), 'id'=>'MyTab-Menu1' )); ?> br /> h1>Yii CJui Tabs Mouse Over Event h1> php $this->widget('zii.widgets.jui.CJuiTabs',array( 'tabs'=>$tabarray, // additional javascript options for the accordion plugin 'options' => array( 'event'=>'mouseover', ), 'id'=>'MyTab-Menu-Mouse' )); ?> in ajax.php file: /** ajax.php **/ echo "Ajax Rendered This Page"; //Your processing ?> In _renderpage.php /** _renderpage.php **/ php echo $Values.""; echo "Render Page"; ?> Screenshots: Reference: http://www.codexamples.com/95/yii-cjui-tabs/

    11
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] CButtonColumn and Font Awesome icons

    I was looking for a way to use Font Awsome icons instead of the default images in a CGridView -> CButtonColumn. Perhaps this will be useful to someone. ... array('class'=>'CButtonColumn', 'template'=>'{update} {view} {delete}', 'buttons'=>array ( 'update'=> array( 'label'=>'', 'imageUrl'=>'', 'options'=>array( 'class'=>'icon-edit' ), ), 'view'=>array( 'label'=>'', 'imageUrl'=>'', 'options'=>array( 'class'=>'icon-search' ), ), 'delete'=>array( 'label'=>'', 'imageUrl'=>'', 'options'=>array( 'class'=>'icon-remove' ), ), ), ),

    7
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Cgridview counter column

    some times we want to show the serialNo on cgridview . $this->widget('zii.widgets.grid.CGridView', array( 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( array( 'header'=>'Sr #', 'value'=>'$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)', ), ............ ));

    9
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Using Apostle.io to send formatted, trackable emails from Yii applications

    Apostle provides a nifty facility for sending app-generated, transactional emails from your application including Wordpress-like mail formatting and full tracking (delivery, opening, clicking etc.) of all emails sent. No need to set up email facilities on your app server! Once you've figured your way round the dependencies, it's lovely and straightforward to integrate into a Yii application. Start by installing using Composer, not using Composer leads to dependency hell since Apostle uses Guzzle which uses bits of Symfony..... The composer.json entry is on Apostle's Github page at https://github.com/apostle/apostle-php. Place this in your application/protected directory and run Composer. You then end up with a vendor directory (if you didn't have one already) containing apostle/apostle-php/src, guzzle/guzzle/src and symfony/event-dispatcher/Symfony. In your protected/config/main.php include aliases for each of their namespaces: Yii::setPathOfAlias('Apostle', dirname(__FILE__).'/../vendor/apostle/apostle-php/src/Apostle'); Yii::setPathOfAlias('Guzzle', dirname(__FILE__).'/../vendor/guzzle/guzzle/src/Guzzle'); Yii::setPathOfAlias('Symfony', dirname(__FILE__).'/../vendor/symfony/event-dispatcher/Symfony'); also include an import line for the main Apostle module: // autoloading model and component classes 'import' => array( ....... // Autoload apostle components 'application.vendor.apostle.apostle-php.src.*', ......... ), Then, in whatever controller you're sending the email from, call the Apostle Module and set the domain key (only do this once), which you will get when you sign up to Apostle (it's free for up to 5,000 emails a month!). ......... Apostle::setup("1234567890abcdef1234567890abcdef"); Create an Apostle mail instance using a template that you have already set up using the Apostle site: ........ $mail = new Apostle\Mail('welcome'); and add the email and any other values you want to use in your email ......... $mail->email = $model->email; // Add any values our template needs $mail->firstname = $profile->firstname; Finally, send it to Apostle.... ..... // Send to Apostle.io $mail->deliver(); Simple as that! No need to log emails sent, no need to set up hard coded email templates, no need to have mailing facilities set up on your application server. So long as you have the aliases set correctly for the namespaces used by Apostle, it works a treat. There's more documentation at apostle.io/developers and Mal, the founder of Apostle.io, provides very timely and friendly support!

    4
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] ClientValidation for files (modern browsers)

    There are cases that you want to validate the file format, size, extension etc but how to do that without submit the form ? Also if the file is too large you have to wait for a cetain time until the error displayed back to you (bad to wait for a failed message) An easy way to do that before submit the file is using javascript. But there is no way (not yet) to do this using clientValidate because the file validator does not provides javascript validator So you have to write custom javascript validator. Suppose we have a server side validator In your model/yourModelform.php you should have something like that (model file) public function rules() { return array( .... array('file', 'file', 'types' => 'jpg', 'minSize'=>100, 'maxSize'=>1000000 , 'allowEmpty'=>false), )), Now in your form (that exist in your view/.../_form.php) that is relative with controller/update or controller/create you should to have this one ... echo $form->labelEx($model, 'file'); echo $form->fileField($model, 'file'); echo $form->error($model, 'file') ... Modify the last line like that echo $form->error($model, 'file', array('clientValidation' => 'js:customValidateFile(messages)'), false, true); add this $infoFieldFile = (end($form->attributes)); right below of the $form->error($model, 'file'.... at the end of the _form.php file add this script array('file', 'file', 'types' => 'jpg', 'minSize'=>100, 'maxSize'=>1000000 , 'allowEmpty'=>false), script> function customValidateFile(messages){ var nameC= '#'inputID']; ?>'; var control = $(nameC).get(0); //simulates the required validator and allowEmpty setting of the file validator if (control.files.length==0) { messages.push("File is required"); return false; } file = control.files[0]; //simulates the types setting of the file validator if (file.name.substr((file.name.lastIndexOf('.') +1)) !='jpg') { messages.push("This is not a csv file"); return false; } //simulates the maxSize setting of the file validator if (file.size>1000000) { messages.push("File cannot be too large (size cannot exceed 1.000.000 bytes.)"); return false; } //simulates the minSize setting of the file validator if (file.size100) { messages.push("File cannot be too small (size cannot be smaller 100 bytes.)"); return false; } //simulates the format type (extra checking) see also http://en.wikipedia.org/wiki/Internet_media_type if (file.type!="image/jpeg") { messages.push("This is not a valid file"); return false; } } script> Also remember that is better to use this settings for your submit form $form = $this->beginWidget( 'CActiveForm', array( 'id' => 'your-id-form', 'enableClientValidation' => true, 'clientOptions' => array( 'validateOnSubmit' => true, ), 'htmlOptions' => array('enctype' => 'multipart/form-data'), ) ); That's it! Warning: The one that I described above, works only for modern browsers that support html5 No one client validators can be replace server validator (for security reasons), so use both of them!

    0
    0
    0
    Favorite
    Grab It
  • Yii Framework
    [Wiki] Update a part of content using AJAX when select a GridView row

    Suppose you want to refresh a form or any content when a single row of CGridView is selected how to achieve that ? In your view file modify your cgridview like that $this->widget('zii.widgets.grid.CGridView', array( 'id' => 'my-items-grid', 'dataProvider' => $model->search(), 'selectableRows' => 1, //permit to select only one row by the time 'selectionChanged' => 'updateABlock', //javascript function that will be called 'filter' => $model, 'columns' => array( 'id', ... ... Into the same view just add this (or using javascript register) script type="text/javascript"> function updateABlock(grid_id) { var keyId = $.fn.yiiGridView.getSelection(grid_id); keyId = keyId[0]; //above function returns an array with single item, so get the value of the first item $.ajax({ url: 'createUrl('PartUpdate'); ?>', data: {id: keyId}, type: 'GET', success: function(data) { $('#part-block').html(data); } }); } script> In your controller add the appropriate action method public function actionPartUpdate($id = null) { $model = MyModel::model()->findByPk($id); if ($model === null) throw new CHttpException(404, 'The requested page does not exist.'); $this->renderPartial('_myModelview', array('model' => $model)); Yii::app()->end(); } view file _myModelview.php could be contains any code including $model data. Remember to includes you code between this div id='part-block'> //your php-html code div>

    6
    0
    0
    Favorite
    Grab It

-