Gradually introduce Yii2 into legacy site

I have an old (2009) legacy site, which brings income but it’s done in a procedural style, not even oop. So my question is, would I benefit from using Yii2 to develop any new pages and/or any updated pages. I know just enough about “routing” to be dangerous but it seems like that part could be accomplished with proper naming conventions. I have about 25 years of programming, database design, and SQL but I’m new to frameworks. I do not wish to use any ORM - I don’t like them because I know I can write efficient SQL and design efficient DBs. However, I am converting the “mysql” statements that I have to PDO (should have done that long ago, I know). Having said all that, if I were to use Yii2 is there a way to gradually work into it – like, whenever I need a new “page” (which I now know is a “view” and a “controller”), could I do it without disturbing the current functionality of the site? Thanks!

Generally the MVC application should be much more flexible than an application written in the procedural style. Mainly when it comes to disturbing the current functionality. Separation of concerns is one of the key benefits of MVC. It will surely take some time to get used to it, but it will be worth the effort.

You can try to install the Yii 2 Application template (probably the Basic one to start with):

http://www.yiiframework.com/download/

Adding a new static page is quite simple. If you configure ViewAction in your controller you can add pages just by adding View files:

http://www.yiiframework.com/doc-2.0/guide-structure-views.html#rendering-static-pages

It may sound discouraging, but I would not recommend you to try gradual transition from legacy raw PHP system to a web framework. You’d better not do it, at least for your first project with the framework. It would not be an easy task even for an experienced framework developer, and, it would not be very fun. :(

I would rather recommend you to start with a clean project that is free from the past. A small, non-commercial, personal pet project would be nice. It will give you enough experience on the framework within a few months, and you’ll be able to think much more accurately about the migration of your site.

Last but not least, try to use ActiveRecord (Yii’s ORM). IMHO, you should learn it if you are to continue web development job for a next decade or two. Or, do you think yourself too old to start learning a new thing? I’m sure you don’t. Actually, your knowledge on SQL will be a very good help to understand and utilize Yii’s ActiveRecord that is designed to be a handy tool for SQL veterans.

Great comment on the “too old” thing. I know enough about Active Record. I’ve used it in Ruby. I hate it, except for simple SQL, and very little of mine is simple. Same goes for Entity (dot Net) and Eloquent (Laravel). Yeah, the simple stuff like “Trumpty = User.find_by(name: ‘Trumpty’)” is ok – but most of my queries are far more complex – I’m heavily normalized.

I was hired by one company to come in and clean up their ORM junk and sub raw SQL (PDO) for it. Every script I touched ran FAR faster. In fact, they had one script that ran in the background for 9 hours. I profiled it and found it was due to their AR junk. I spent about 2 days ripping all that mess out and subbing SQL PDO statements and the script ran in under 2 minutes. So you can keep your ORM, young man.

Welcome back, kleeh!

Thanks for your compliments. I just thought you are younger than I am. ;)

Anyway, even if you really dislike ORMs, you can still enjoy using Yii, I hope.

I am new to Yii also, and I also have used laravel for some time. I do use the orm some, but I prefer to write normal queries for more complex stuff. Laravel has getPdo() for that. But in yii you can also write normal pdo queries if required. Actually active record isn’t that great for huge databases.

Ok the old data you have, you could slowly migrate over, just have links to old parts, and new parts (completed) would be in yii. Same database right?

Just remember, generally speaking php frameworks are mainly okay for mid-medium to small sites. Usually large enterprise has customized code usually java technology, or if php it’s assisted with compiled c++ classes.

Do you know java technology like Servlet, jsp, javabean classes have much longer backwards compatibility than modern php frameworks. In fact some code I wrote 2006 at a trucking would still be fine today. It would need updated password hashing. But for the most part the small tweaks to update are small.

But that is by design, java does that since enterprise uses java a lot.

It’s no fault of php / pdo they are even stable longer. Seems most frameworks change things every few months.

I advise to start with ActiveRecord, and then - only after profiling!! rewrite using DAO / QueryBuilder only where it matters.

ActiveRecord in Yii 2 is much, much better than you give it credit for.

One of the first things to look for is not stop using it, but use eager loading instead of lazy loading.

That makes a huge difference!

Use the Yii debugger to see what needs to be trimmed.

Combine eager loading with batch queries, and Yii 2 performs extremely well with large datasets.

I am sure active record is fine for some things, but concerning eager loading, which just means load when needed.

Here is a situation that doesn’t work well. Say you have a large accounts receivable report that the boss likes to view also on the computer. In the nested foreach (pseudo code)




Joe's big warehouse


======list of receivables for Joe's big warehouse


Another big client


======list of receivables for Another big client


// and many many more



Now the problem, Joe’s big warehouse may only have five receivables.

But Another big client could have in the thousands of receivables.

Solution I have done in past, double pagination. Have a link by company like (next company)

And another paginator for that companies receivables.

Active record will load too many records. There are times in especially reports where you almost need custom queries in the view, and the controller is only used to control where you are in pagination.

But yes for most smaller things I guess active record is okay.

But on any php / php framework forum I am yet to see a main programmer / I.T. person

from Fedex, CH Robinson, JB Hunt, Landstar show up.

Let’s be realistic, I myself came from Java enterprise to php, I am semi retired and that’s what a Humane Society already had is php hosting. I am not going to tell someone that php or a php framework is suited for large enterprise, it is not.

I will say it has come a long way over the last decade. And is fine for up to medium enterprise.

And the yii orm or larvel orm has nothing to to with anything as these shortcuts are converted to normal queries at runtime.

The problem isn’t pdo, it’s the way active record pattern gets the data, you loose all control in a one to many as an example.

Just trying to be realistic. I try my best to give straight shooter answers.

Good points, but eager loading is the opposite: load what you need first.

Lazy loading is load when needed.

You are right that, in some situations, you need to go lower level and hand-craft your queries. Yii 2 makes that easy to do, fortunately :)

jacmoe nice reply, I agree 100 percent. I have used laravel since ver 4.2, prior to that I used Simple mvc framework.

Simple mvc framework evolved into nova framework, I was a contributor to SMVC. Short quick story, main developer’s company also used L4.2, did not want a bunch of upgrading to do, hence he / they kinda took the best of laravel, some cake ideas, and of course some custom code and made nova. Nova now is modern and close to what say laravel 5.* is.

I currently use nova on one project and laravel 5.5 on another. So why am I here. A newbee on the laravel site was trying to decide between laravel and yii2. He had a bunch of trouble getting up and running. Finally after getting discouraged I guess he picked Yii2.

That sparked my curiosity, so I decided to try Yii2.

I have used cake, laravel, nova, and now experimenting with Yii2.

Basically these four are very similar, yes minor differences. But take this older java query as example:




public List<Pet> list() throws SQLException {

        Connection connection = null;

        PreparedStatement st = null;

        ResultSet resultSet = null;

        List<Pet> pets = new ArrayList<Pet>();


        try {

            try {

                Class.forName("com.mysql.jdbc.Driver");

            } catch (ClassNotFoundException ex) {

                Logger.getLogger(PetDAO.class.getName()).log(Level.SEVERE, null, ex);

            }

            offset = 5;

            rowsperpage = 5;

            connection = (Connection) DriverManager.getConnection("jdbc:mysql:///petback2", "root", "secret");

            st  = connection.prepareStatement("select * from pets where petname like ? LIMIT "+ offset + ", " + rowsperpage);

            st.setString(1, this.t1 + "%");

            resultSet = st.executeQuery();


            while (resultSet.next()) {

                Pet pet = new Pet();

                pet.setpetid(resultSet.getString("petid"));

                pet.setpetname(resultSet.getString("petname"));

                pets.add(pet);

            }

            

        } finally {

            if (resultSet != null) try { resultSet.close(); } catch (SQLException ignore) {}

            if (st != null) try { st.close(); } catch (SQLException ignore) {}


            if (connection != null) try { connection.close(); } catch (SQLException ignore) {}

        }


        return pets;

    }

}




All the above mentioned frameworks have access to normal PDO and there are the times when I just like doing a normal query.

But times when




        $query = Dog::where('dogname', 'like', $dogsch);

        if ($aval == "n") {

            $query->where('adopted', '=', 1);

        } else if ($aval == "y") {

            $query->where('adopted', '=', 0);

        }

        $dogs = $query->orderBy('lastedit', 'DESC')->paginate(5);



I like that. So yes Yii and the others are all flexible enough to allow the programmer the freedom to code as needed.

Only thing I did not like right away is Yiis asset thing, So I wrote me a custom class to handle the way I like doing assets:

Basically like




    <link href="<?php echo Resource::asset('css/dogs/style.css'); ?>" rel="stylesheet">

    <script type="text/javascript" src="<?php echo Resource::asset('js/jquery.js'); ?>"></script>




I like keeping things simple.

You asset code looks pretty much what AssetBundles do.

In one of my application, I have this asset bundle:


<?php

namespace app\themes\bourbon\assets;


use yii\web\AssetBundle;


class ThemeAsset extends AssetBundle

{

	public $sourcePath = '@app/themes/bourbon/assets/dist';

	public $css = [

    	YII_ENV_DEV ? 'css/all.css' : 'css/all.min.css'

	];

	public $js = [

    	YII_ENV_DEV ? 'js/all.js' : 'js/all.min.js'

	];

}



The asset manager is configured thus:


    	'assetManager' => [

        	'linkAssets' => true,

        	'appendTimestamp' => true,

    	],



Then I just register the asset bundle in my main layout.

Because the assets are linked, all the various directories in the ‘assets’ folder are symbolic links, pointing to my assets source directory.

Whenever the assets change, the timestamp changes, which means that the browser cache is busted.

I am not a fan of how the asset manager works out of the box either, and this approach is very simple and lightweight, and IMO better than manually inserting links into the views.

The Yii asset manager is very flexible.

jacmoe I usually load just what’s needed, so I did this:

Layout / template




<?php use app\helpers\Resource; ?>


<!DOCTYPE html>

<html lang="en">

<head>


    

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link href="<?php echo Resource::asset('css/dogs/style.css'); ?>" rel="stylesheet">

    <script type="text/javascript" src="<?php echo Resource::asset('js/jquery.js'); ?>"></script>

    <style type="text/css">

    more code not showed



A simple class




<?php


namespace app\helpers;


use yii\helpers\Url;


class Resource

{


    public static function asset($path)

    {

        $path = self::siteUrl() . 'assets' . '/' .  ltrim($path, '/');

        return $path;

    }


    public static function siteUrl()

    {

        return Url::home(true);

                

    }


}



That’s it

Used elsewhere also like




<td class="imgtd"><a href="<?php echo Resource::siteUrl() . 'dog/view?dogid=' . $row['dogid']; ?>"><img src="<?php echo Resource::asset('img/imgdogs') . '/' . $row['dogpic']; ?>" alt="" class="image"></a></td>



of course




<?php echo

//or

<?=



Then my solution - the "Yii way" - is actually less work and more bang.

The asset bundle gets registered in the view, and inserts those two lines; the first in the head and the second in the body:




<link href="[url=""]/assets/d54bbca/css/all.min.css?v=1484742742[/url]" rel="[url=""]stylesheet[/url]">


<script src="[url=""]/assets/d54bbca/js/all.min.js?v=1484742742[/url]"></script>

Notice how the stylesheet and script has a timestamp on them, automatically handled by the asset manager. Also, the minified version is used when in production. I don’t have to do that work. :)

I register the asset bundle in the view (main layout) like this:


$asset = app\themes\bourbon\assets\ThemeAsset::register($view);



That means, that I can use $asset->baseUrl in the view:


<img src="<?= $asset->baseUrl ?>/img/jacmoe_ubernaut.png"/>



If you have a special page or two, where you need additional assets, you can register another asset bundle that you have specified for that purpose.

Or, do it manually - which is going to be both error prone IMO, and tedious. Especially if you want a timestamped url for it.

Try it! You might grow to like it.

[Edit]

What I’m trying to say is, that you can have your cake and eat it too.

You don’t have to accept all or nothing.

That’s one of my favorite things about Yii: you can easily make it accomodate you and your way of doing things.

[/Edit]

One additional reason why I am using the asset manager with linked assets is that I can have my assets outside of the web root.

I generally treat the web root as a do not touch (fill with crap) more than necessary.

At runtime, the asset manager creates a symbolic link in @app/web/assets - I don’t have to worry about it.

jacmoe I do install correct, meaning main Yii core above htdocs (public_html, www) in fact see answer I gave here:

Install

But usually images I put under htdocs. If it was a site where there were private user images, then yes you have a good point.

As far as versions, I don’t. Any playing with css is tested in development, I should never need any version control on live server. Once I upload a css file I intend to use that css file unless I upload a replacement theme / css.

But I am looking into your code, just don’t want those zxcdwes or whatever files/folders are generated in assets folder.

They are generated, and just symlinks, so forget they are even there - that’s what I do :)

Even if you end up using your own, more manual approach, know that you can probably wrangle the asset manager a bit and have it do it for you.

Just wanted to make sure that you didn’t overlook anything

Yes, but once you do upload the new version to the server, you need to either give the new css file a new name, or use the timestamp trick, so that the browser fetches the new version and not the old version for the cache. You are thus making sure that all users of your site gets the new version, and not the old one (on their machine).

That’s the whole point of appending a timestamp.

Finally, the reason why those folders are named ‘zxcdwes’, etc. is to eliminate possible collisions: two or more files with the same name and the like.

I’ve come to appreciate that, because then I can have a set of folders for each asset bundle, all with the same layout.

jacmoe does those generated folders / files auto purge out as needed? When testing yii, it grew from 3 to 6.

That is a very good question, actually.

I wasn’t able to find the answer in the guide or in the API docs…

This is a good assetmanager reference, btw: https://github.com/y...cture-assets.md

You could create a Yii console command that deletes the contents of the ‘asset’ directory periodically, though I haven’t really thought about it since it hasn’t become a problem for the sites I manage.

(Mainly because when I upload a new version of my site, the ‘assets’ folder is not shared between releases - I use Deployer)

Lol!! I just happened to read your post – that newbie comparing Yii and Laravel was ME. And Yessir, I did end up choosing Yii. I know that there are going to be issues learning anything new but I’ve been programming (let’s just say over 20 years) and I can read a manual but I do better with clear-cut examples. Those provided to me regarding Laravel did not work. But Yii … I didn’t even need examples to get a nice bootstrap-style working menu up and running. I’m sure Laravel is fine for those who have the time to deal with it. I don’t. Enjoy Yii ! I’m having a few issues with pretty Urls on the “basic” version, but oddly enough I’ve gotten them working on the Advanced version. Weird. Anyway, welcome to the forum (from a newbie).

kleeh I had never used Yii, but you made me curious. So far it’s alright. Of course like you I have programmed a long time. The good thing about yii and laravel is flexibility. Also if I don’t like the way yii does something out of box, I can write a class to handle it.

One example is pagination, I have my own paginator.

But I hope you all the success possible with your project. We probably can help one another sometimes.

Yii does have good docs, but still tricky - still need good ole stackoverflow.

Also see my reply on yii installation just make sure you install correctly and even in development work that way.